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    namespace details
00059    {
00060       inline bool is_whitespace(const char c)
00061       {
00062          return (' '  == c) || ('\n' == c) ||
00063                 ('\r' == c) || ('\t' == c) ||
00064                 ('\b' == c) || ('\v' == c) ||
00065                 ('\f' == c) ;
00066       }
00067 
00068       inline bool is_operator_char(const char c)
00069       {
00070          return ('+' == c) || ('-' == c) ||
00071                 ('*' == c) || ('/' == c) ||
00072                 ('^' == c) || ('<' == c) ||
00073                 ('>' == c) || ('=' == c) ||
00074                 (',' == c) || ('!' == c) ||
00075                 ('(' == c) || (')' == c) ||
00076                 ('[' == c) || (']' == c) ||
00077                 ('{' == c) || ('}' == c) ||
00078                 ('%' == c) || (':' == c) ||
00079                 ('?' == c) || ('&' == c) ||
00080                 ('|' == c) || (';' == c);
00081       }
00082 
00083       inline bool is_letter(const char c)
00084       {
00085          return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
00086       }
00087 
00088       inline bool is_digit(const char c)
00089       {
00090          return ('0' <= c) && (c <= '9');
00091       }
00092 
00093       inline bool is_letter_or_digit(const char c)
00094       {
00095          return is_letter(c) || is_digit(c);
00096       }
00097 
00098       inline bool is_left_bracket(const char c)
00099       {
00100          return ('(' == c) || ('[' == c) || ('{' == c);
00101       }
00102 
00103       inline bool is_right_bracket(const char c)
00104       {
00105          return (')' == c) || (']' == c) || ('}' == c);
00106       }
00107 
00108       inline bool is_bracket(const char c)
00109       {
00110          return is_left_bracket(c) || is_right_bracket(c);
00111       }
00112 
00113       inline bool is_sign(const char c)
00114       {
00115          return ('+' == c) || ('-' == c);
00116       }
00117 
00118       inline bool is_invalid(const char c)
00119       {
00120          return !is_whitespace(c)    &&
00121                 !is_operator_char(c) &&
00122                 !is_letter(c)        &&
00123                 !is_digit(c)         &&
00124                 ('.' != c)           &&
00125                 ('_' != c)           &&
00126                 ('$' != c)           &&
00127                 ('~' != c)           &&
00128                 ('\'' != c);
00129       }
00130 
00131       inline bool imatch(const char c1, const char c2)
00132       {
00133          return std::tolower(c1) == std::tolower(c2);
00134       }
00135 
00136       inline bool imatch(const std::string& s1, const std::string& s2)
00137       {
00138          if (s1.size() == s2.size())
00139          {
00140             for (std::size_t i = 0; i < s1.size(); ++i)
00141             {
00142                if (std::tolower(s1[i]) != std::tolower(s2[i]))
00143                {
00144                   return false;
00145                }
00146             }
00147             return true;
00148          }
00149          return false;
00150       }
00151 
00152       inline bool is_valid_sf_symbol(const std::string& symbol)
00153       {
00154          // Special function: $f12 or $F34
00155          return (symbol.size() == 4)  &&
00156                 ('$' == symbol[0])    &&
00157                 imatch('f',symbol[1]) &&
00158                 is_digit(symbol[2])   &&
00159                 is_digit(symbol[3]);
00160       }
00161 
00162       inline std::string to_str(int i)
00163       {
00164          if (0 == i)
00165             return std::string("0");
00166          std::string result;
00167          bool negative = (i < 0);
00168          if (negative) i *= -1;
00169          while (i)
00170          {
00171             char digit = '0' + char(i % 10);
00172             result = (digit + result);
00173             i /= 10;
00174          }
00175          if (negative)
00176             result = "-" + result;
00177          return result;
00178       }
00179 
00180       inline void cleanup_escapes(std::string& s)
00181       {
00182          std::string::iterator itr1 = s.begin();
00183          std::string::iterator itr2 = s.begin();
00184          std::string::iterator end  = s.end  ();
00185          std::size_t removal_count  = 0;
00186 
00187          while (end != itr1)
00188          {
00189             if ('\\' == (*itr1))
00190             {
00191                ++removal_count;
00192                if (end == ++itr1)
00193                   break;
00194                else if ('\\' != (*itr1))
00195                {
00196                   switch (*itr1)
00197                   {
00198                      case 'n' : (*itr1) = '\n'; break;
00199                      case 'r' : (*itr1) = '\r'; break;
00200                      case 't' : (*itr1) = '\t'; break;
00201                   }
00202                   continue;
00203                }
00204             }
00205 
00206             if (itr1 != itr2)
00207             {
00208                (*itr2) = (*itr1);
00209             }
00210             ++itr1;
00211             ++itr2;
00212          }
00213 
00214          s.resize(s.size() - removal_count);
00215       }
00216 
00217       class build_string
00218       {
00219       public:
00220 
00221          build_string(const std::size_t& initial_size = 64)
00222          {
00223             data_.reserve(initial_size);
00224          }
00225 
00226          inline build_string& operator << (const std::string& s)
00227          {
00228             data_ += s;
00229             return (*this);
00230          }
00231 
00232          inline build_string& operator << (const char* s)
00233          {
00234             data_ += std::string(s);
00235             return (*this);
00236          }
00237 
00238          inline operator std::string () const
00239          {
00240             return data_;
00241          }
00242 
00243          inline std::string as_string() const
00244          {
00245             return data_;
00246          }
00247 
00248       private:
00249 
00250          std::string data_;
00251       };
00252 
00253       struct ilesscompare
00254       {
00255          inline bool operator()(const std::string& s1, const std::string& s2) const
00256          {
00257             const std::size_t length = std::min(s1.size(),s2.size());
00258             for (std::size_t i = 0; i < length;  ++i)
00259             {
00260                if (std::tolower(s1[i]) > std::tolower(s2[i]))
00261                   return false;
00262                else if (std::tolower(s1[i]) < std::tolower(s2[i]))
00263                   return true;
00264             }
00265             return s1.size() < s2.size();
00266          }
00267       };
00268 
00269       static const std::string reserved_words[] =
00270                                   {
00271                                      "break", "case", "continue", "default", "false", "for", "if", "else",
00272                                      "ilike", "in", "like", "and", "nand", "nor", "not", "null", "or", "repeat",
00273                                      "shl", "shr", "switch", "true", "until", "while", "xnor", "xor", "&", "|"
00274                                   };
00275 
00276       static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
00277 
00278       static const std::string reserved_symbols[] =
00279                                   {
00280                                      "abs", "acos", "acosh", "and", "asin", "asinh", "atan", "atanh", "atan2", "avg",
00281                                      "break", "case", "ceil", "clamp", "continue", "cos", "cosh", "cot", "csc", "default",
00282                                      "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", "expm1", "false", "floor",
00283                                      "for", "frac", "grad2deg", "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
00284                                      "like", "log", "log10", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor",
00285                                      "mul", "nand", "nor", "not", "not_equal", "null", "or", "pow", "rad2deg", "repeat",
00286                                      "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinc", "sinh", "sqrt",
00287                                      "sum", "switch", "tan", "tanh", "true", "trunc", "until", "while", "xnor", "xor",
00288                                      "&", "|"
00289                                   };
00290 
00291       static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
00292 
00293       inline bool is_reserved_word(const std::string& symbol)
00294       {
00295          for (std::size_t i = 0; i < reserved_words_size; ++i)
00296          {
00297             if (imatch(symbol,reserved_words[i]))
00298             {
00299                return true;
00300             }
00301          }
00302          return false;
00303       }
00304 
00305       inline bool is_reserved_symbol(const std::string& symbol)
00306       {
00307          for (std::size_t i = 0; i < reserved_symbols_size; ++i)
00308          {
00309             if (imatch(symbol,reserved_symbols[i]))
00310             {
00311                return true;
00312             }
00313          }
00314          return false;
00315       }
00316 
00317       struct cs_match  { static inline bool cmp(const char c0, const char c1) { return c0 == c1; } };
00318       struct cis_match { static inline bool cmp(const char c0, const char c1) { return std::tolower(c0) == std::tolower(c1); } };
00319 
00320       template <typename Iterator, typename Compare>
00321       inline bool match_impl(const Iterator pattern_begin,
00322                              const Iterator pattern_end,
00323                              const Iterator data_begin,
00324                              const Iterator data_end,
00325                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
00326                              const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
00327       {
00328          if (0 == std::distance(data_begin,data_end)) return false;
00329          Iterator d_itr = data_begin;
00330          Iterator p_itr = pattern_begin;
00331          Iterator c_itr = data_begin;
00332          Iterator m_itr = data_begin;
00333          while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
00334          {
00335             if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
00336             {
00337                return false;
00338             }
00339             ++p_itr;
00340             ++d_itr;
00341          }
00342 
00343          while (data_end != d_itr)
00344          {
00345             if (zero_or_more == (*p_itr))
00346             {
00347                if (pattern_end == (++p_itr))
00348                {
00349                   return true;
00350                }
00351                m_itr = p_itr;
00352                c_itr = d_itr;
00353                ++c_itr;
00354             }
00355             else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
00356             {
00357                ++p_itr;
00358                ++d_itr;
00359             }
00360             else
00361             {
00362                p_itr = m_itr;
00363                d_itr = c_itr++;
00364             }
00365          }
00366          while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr;
00367          return (p_itr == pattern_end);
00368       }
00369 
00370       inline bool wc_match(const std::string& wild_card,
00371                            const std::string& str)
00372       {
00373          return match_impl<const char*,cs_match>(wild_card.data(),
00374                                                  wild_card.data() + wild_card.size(),
00375                                                  str.data(),
00376                                                  str.data() + str.size(),
00377                                                  '*',
00378                                                  '?');
00379       }
00380 
00381       inline bool wc_imatch(const std::string& wild_card,
00382                             const std::string& str)
00383       {
00384          return match_impl<const char*,cis_match>(wild_card.data(),
00385                                                   wild_card.data() + wild_card.size(),
00386                                                   str.data(),
00387                                                   str.data() + str.size(),
00388                                                   '*',
00389                                                   '?');
00390       }
00391 
00392       static const double pow10[] = {
00393                                        1.0,
00394                                        10.0,
00395                                        100.0,
00396                                        1000.0,
00397                                        10000.0,
00398                                        100000.0,
00399                                        1000000.0,
00400                                        10000000.0,
00401                                        100000000.0,
00402                                        1000000000.0,
00403                                        10000000000.0,
00404                                        100000000000.0,
00405                                        1000000000000.0,
00406                                        10000000000000.0,
00407                                        100000000000000.0,
00408                                        1000000000000000.0,
00409                                        10000000000000000.0,
00410                                     };
00411 
00412      static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
00413 
00414       namespace numeric
00415       {
00416          namespace constant
00417          {
00418             static const double e       =  2.718281828459045235360;
00419             static const double pi      =  3.141592653589793238462;
00420             static const double pi_2    =  1.570796326794896619231;
00421             static const double pi_4    =  0.785398163397448309616;
00422             static const double pi_180  =  0.017453292519943295769;
00423             static const double _1_pi   =  0.318309886183790671538;
00424             static const double _2_pi   =  0.636619772367581343076;
00425             static const double _180_pi = 57.295779513082320876798;
00426             static const double log2    =  0.693147180559945309417;
00427          }
00428 
00429          namespace details
00430          {
00431             struct unknown_type_tag {};
00432             struct real_type_tag    {};
00433             struct int_type_tag     {};
00434 
00435             template <typename T>
00436             struct number_type { typedef unknown_type_tag type; };
00437 
00438             #define exprtk_register_real_type_tag(T)                          \
00439             template<> struct number_type<T> { typedef real_type_tag type; }; \
00440 
00441             #define exprtk_register_int_type_tag(T)                          \
00442             template<> struct number_type<T> { typedef int_type_tag type; }; \
00443 
00444             exprtk_register_real_type_tag(double)
00445             exprtk_register_real_type_tag(long double)
00446             exprtk_register_real_type_tag(float)
00447             exprtk_register_int_type_tag(short)
00448             exprtk_register_int_type_tag(int)
00449             exprtk_register_int_type_tag(long long int)
00450             exprtk_register_int_type_tag(unsigned short)
00451             exprtk_register_int_type_tag(unsigned int)
00452             exprtk_register_int_type_tag(unsigned long long int)
00453 
00454             #undef exprtk_register_real_type_tag
00455             #undef exprtk_register_int_type_tag
00456 
00457             template <typename T>
00458             struct epsilon_type
00459             {
00460                static inline T value()
00461                {
00462                   const T epsilon = T(0.0000000001);
00463                   return epsilon;
00464                }
00465             };
00466 
00467             template <>
00468             struct epsilon_type <float>
00469             {
00470                static inline float value()
00471                {
00472                   const float epsilon = float(0.000001f);
00473                   return epsilon;
00474                }
00475             };
00476 
00477             template <>
00478             struct epsilon_type <long double>
00479             {
00480                static inline long double value()
00481                {
00482                   const long double epsilon = (long double)(0.000000000001);
00483                   return epsilon;
00484                }
00485             };
00486 
00487             template <typename T>
00488             inline bool is_true_impl(const T v)
00489             {
00490                return (v != T(0));
00491             }
00492 
00493             template <typename T>
00494             inline bool is_false_impl(const T v)
00495             {
00496                return (T(0) == v);
00497             }
00498 
00499             template <typename T>
00500             inline T abs_impl(const T v, real_type_tag)
00501             {
00502                return ((v >= T(0)) ? v : -v);
00503             }
00504 
00505             template <typename T>
00506             inline T equal_impl(const T v0, const T v1, real_type_tag)
00507             {
00508                const T epsilon = epsilon_type<T>::value();
00509                return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
00510             }
00511 
00512             inline float equal_impl(const float v0, const float v1, real_type_tag)
00513             {
00514                const float epsilon = epsilon_type<float>::value();
00515                return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
00516             }
00517 
00518             template <typename T>
00519             inline T equal_impl(const T v0, const T v1, int_type_tag)
00520             {
00521                return (v0 == v1) ? 1 : 0;
00522             }
00523 
00524             template <typename T>
00525             inline T expm1_impl(const T v, real_type_tag)
00526             {
00527                // return std::expm1<T>(v);
00528                if (abs_impl(v,real_type_tag()) < T(0.00001))
00529                   return v + (T(0.5) * v * v);
00530                else
00531                   return std::exp(v) - T(1);
00532             }
00533 
00534             template <typename T>
00535             inline T expm1_impl(const T v, int_type_tag)
00536             {
00537                return T(std::exp<double>(v)) - T(1);
00538             }
00539 
00540             template <typename T>
00541             inline T nequal_impl(const T v0, const T v1, real_type_tag)
00542             {
00543                const T epsilon = epsilon_type<T>::value();
00544                return (abs_impl(v0 - v1,real_type_tag()) > (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
00545             }
00546 
00547             inline float nequal_impl(const float v0, const float v1, real_type_tag)
00548             {
00549                const float epsilon = epsilon_type<float>::value();
00550                return (abs_impl(v0 - v1,real_type_tag()) > (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
00551             }
00552 
00553             template <typename T>
00554             inline T nequal_impl(const T v0, const T v1, int_type_tag)
00555             {
00556                return (v0 != v1) ? 1 : 0;
00557             }
00558 
00559             template <typename T>
00560             inline T modulus_impl(const T v0, const T v1, real_type_tag)
00561             {
00562                return std::fmod(v0,v1);
00563             }
00564 
00565             template <typename T>
00566             inline T modulus_impl(const T v0, const T v1, int_type_tag)
00567             {
00568                return v0 % v1;
00569             }
00570 
00571             template <typename T>
00572             inline T pow_impl(const T v0, const T v1, real_type_tag)
00573             {
00574                return std::pow(v0,v1);
00575             }
00576 
00577             template <typename T>
00578             inline T pow_impl(const T v0, const T v1, int_type_tag)
00579             {
00580                return std::pow(static_cast<double>(v0),static_cast<double>(v1));
00581             }
00582 
00583             template <typename T>
00584             inline T logn_impl(const T v0, const T v1, real_type_tag)
00585             {
00586                return std::log(v0) / std::log(v1);
00587             }
00588 
00589             template <typename T>
00590             inline T logn_impl(const T v0, const T v1, int_type_tag)
00591             {
00592                return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
00593             }
00594 
00595             template <typename T>
00596             inline T log1p_impl(const T v, real_type_tag)
00597             {
00598                if (v > T(-1))
00599                {
00600                   if (abs_impl(v,real_type_tag()) > T(0.0001))
00601                   {
00602                      return std::log(T(1) + v);
00603                   }
00604                   else
00605                      return (T(-0.5) * v + T(1)) * v;
00606                }
00607                else
00608                   return std::numeric_limits<T>::quiet_NaN();
00609             }
00610 
00611             template <typename T>
00612             inline T log1p_impl(const T v, int_type_tag)
00613             {
00614                if (v > T(-1))
00615                {
00616                   return std::log(T(1) + v);
00617                }
00618                else
00619                   return std::numeric_limits<T>::quiet_NaN();
00620             }
00621 
00622             template <typename T>
00623             inline T root_impl(const T v0, const T v1, real_type_tag)
00624             {
00625                return std::pow(v0,T(1) / v1);
00626             }
00627 
00628             template <typename T>
00629             inline T root_impl(const T v0, const T v1, int_type_tag)
00630             {
00631                return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
00632             }
00633 
00634             template <typename T>
00635             inline T round_impl(const T v, real_type_tag)
00636             {
00637                return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
00638             }
00639 
00640             template <typename T>
00641             inline T roundn_impl(const T v0, const T v1, real_type_tag)
00642             {
00643                const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
00644                const T p10 = T(pow10[index]);
00645                if (v0 < T(0))
00646                   return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
00647                else
00648                   return T(std::floor((v0 * p10) + T(0.5)) / p10);
00649             }
00650 
00651             template <typename T>
00652             inline T roundn_impl(const T v0, const T, int_type_tag)
00653             {
00654                return v0;
00655             }
00656 
00657             template <typename T>
00658             inline T hypot_impl(const T v0, const T v1, real_type_tag)
00659             {
00660                return std::sqrt((v0 * v0) + (v1 * v1));
00661             }
00662 
00663             template <typename T>
00664             inline T hypot_impl(const T v0, const T v1, int_type_tag)
00665             {
00666                return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
00667             }
00668 
00669             template <typename T>
00670             inline T atan2_impl(const T v0, const T v1, real_type_tag)
00671             {
00672                return std::atan2(v0,v1);
00673             }
00674 
00675             template <typename T>
00676             inline T atan2_impl(const T, const T, int_type_tag)
00677             {
00678                return 0;
00679             }
00680 
00681             template <typename T>
00682             inline T shr_impl(const T v0, const T v1, real_type_tag)
00683             {
00684                return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
00685             }
00686 
00687             template <typename T>
00688             inline T shr_impl(const T v0, const T v1, int_type_tag)
00689             {
00690                return v0 >> v1;
00691             }
00692 
00693             template <typename T>
00694             inline T shl_impl(const T v0, const T v1, real_type_tag)
00695             {
00696                return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
00697             }
00698 
00699             template <typename T>
00700             inline T shl_impl(const T v0, const T v1, int_type_tag)
00701             {
00702                return v0 << v1;
00703             }
00704 
00705             template <typename T>
00706             inline T sgn_impl(const T v, real_type_tag)
00707             {
00708                     if (v > T(0)) return T(+1);
00709                else if (v < T(0)) return T(-1);
00710                else               return T( 0);
00711             }
00712 
00713             template <typename T>
00714             inline T sgn_impl(const T v, int_type_tag)
00715             {
00716                     if (v > T(0)) return T(+1);
00717                else if (v < T(0)) return T(-1);
00718                else               return T( 0);
00719             }
00720 
00721             template <typename T>
00722             inline T and_impl(const T v0, const T& v1, real_type_tag)
00723             {
00724                return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
00725             }
00726 
00727             template <typename T>
00728             inline T and_impl(const T v0, const T& v1, int_type_tag)
00729             {
00730                return v0 && v1;
00731             }
00732 
00733             template <typename T>
00734             inline T nand_impl(const T v0, const T& v1, real_type_tag)
00735             {
00736                return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
00737             }
00738 
00739             template <typename T>
00740             inline T nand_impl(const T v0, const T& v1, int_type_tag)
00741             {
00742                return !(v0 && v1);
00743             }
00744 
00745             template <typename T>
00746             inline T or_impl(const T v0, const T& v1, real_type_tag)
00747             {
00748                return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
00749             }
00750 
00751             template <typename T>
00752             inline T or_impl(const T v0, const T& v1, int_type_tag)
00753             {
00754                return (v0 || v1);
00755             }
00756 
00757             template <typename T>
00758             inline T nor_impl(const T v0, const T& v1, real_type_tag)
00759             {
00760                return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
00761             }
00762 
00763             template <typename T>
00764             inline T nor_impl(const T v0, const T& v1, int_type_tag)
00765             {
00766                return !(v0 || v1);
00767             }
00768 
00769             template <typename T>
00770             inline T xor_impl(const T v0, const T& v1, real_type_tag)
00771             {
00772                return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
00773             }
00774 
00775             template <typename T>
00776             inline T xor_impl(const T v0, const T& v1, int_type_tag)
00777             {
00778                return v0 ^ v1;
00779             }
00780 
00781             template <typename T>
00782             inline T xnor_impl(const T v0, const T& v1, real_type_tag)
00783             {
00784                const bool v0_true = is_true_impl(v0);
00785                const bool v1_true = is_true_impl(v1);
00786                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
00787                   return T(1);
00788                else
00789                   return T(0);
00790             }
00791 
00792             template <typename T>
00793             inline T xnor_impl(const T v0, const T& v1, int_type_tag)
00794             {
00795                const bool v0_true = is_true_impl(v0);
00796                const bool v1_true = is_true_impl(v1);
00797                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
00798                   return T(1);
00799                else
00800                   return T(0);
00801             }
00802 
00803             template <typename T>
00804             inline T erf_impl(T v, real_type_tag)
00805             {
00806                #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00807                // Credits: Abramowitz & Stegun Equations 7.1.25-28
00808                const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
00809                static const T c[] = {
00810                                       T( 1.26551223), T(1.00002368),
00811                                       T( 0.37409196), T(0.09678418),
00812                                       T(-0.18628806), T(0.27886807),
00813                                       T(-1.13520398), T(1.48851587),
00814                                       T(-0.82215223), T(0.17087277)
00815                                     };
00816                T result = T(1) - t * std::exp((-v * v) -
00817                                       c[0] + t * (c[1] + t *
00818                                      (c[2] + t * (c[3] + t *
00819                                      (c[4] + t * (c[5] + t *
00820                                      (c[6] + t * (c[7] + t *
00821                                      (c[8] + t * (c[9]))))))))));
00822                return (v >= T(0)) ? result : -result;
00823                #else
00824                return ::erf(v);
00825                #endif
00826             }
00827 
00828             template <typename T>
00829             inline T erf_impl(T v, int_type_tag)
00830             {
00831                return erf_impl(static_cast<double>(v),real_type_tag());
00832             }
00833 
00834             template <typename T>
00835             inline T erfc_impl(T v, real_type_tag)
00836             {
00837                #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00838                return T(1) - erf_impl(v,real_type_tag());
00839                #else
00840                return ::erfc(v);
00841                #endif
00842             }
00843 
00844             template <typename T>
00845             inline T erfc_impl(T v, int_type_tag)
00846             {
00847                return erfc_impl(static_cast<double>(v),real_type_tag());
00848             }
00849 
00850             template <typename T>
00851             inline T sinc_impl(T v, real_type_tag)
00852             {
00853                if(std::abs(v) >= std::numeric_limits<T>::epsilon())
00854                    return(std::sin(v) / v);
00855                else
00856                   return T(1);
00857             }
00858 
00859             template <typename T>
00860             inline T sinc_impl(T v, int_type_tag)
00861             {
00862                return erfc_impl(static_cast<double>(v),real_type_tag());
00863             }
00864 
00865             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
00866             template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
00867             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
00868             template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
00869             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
00870             template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); }
00871             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
00872             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
00873             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
00874             template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
00875             template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
00876             template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
00877             template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
00878             template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
00879             template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
00880             template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
00881             template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
00882             template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
00883             template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
00884             template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
00885             template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
00886             template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
00887             template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
00888             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
00889             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
00890             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
00891             template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
00892             template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
00893             template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); }
00894             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
00895             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
00896 
00897             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
00898             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
00899             template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
00900             template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
00901             template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
00902             template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
00903             template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
00904             template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
00905             template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
00906             template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
00907             template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
00908             template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
00909             template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
00910             template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
00911             template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00912             template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00913             template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00914             template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00915             template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00916             template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00917             template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00918             template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00919             template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00920             template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00921             template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00922             template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00923             template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00924             template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00925             template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00926 
00927             template <typename T>
00928             inline bool is_integer_impl(const T& v, real_type_tag)
00929             {
00930                return (T(0) == std::fmod(v,T(1)));
00931             }
00932 
00933             template <typename T>
00934             inline bool is_integer_impl(const T&, int_type_tag)
00935             {
00936                return true;
00937             }
00938 
00939          }
00940 
00941          template <typename Type>
00942          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
00943 
00944          template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length =  9}; };
00945          template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
00946          template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
00947          template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
00948 
00949          template <typename T>
00950          inline T equal(const T v0, const T v1)
00951          {
00952             typename details::number_type<T>::type num_type;
00953             return details::equal_impl(v0,v1,num_type);
00954          }
00955 
00956          template <typename T>
00957          inline T nequal(const T v0, const T v1)
00958          {
00959             typename details::number_type<T>::type num_type;
00960             return details::nequal_impl(v0,v1,num_type);
00961          }
00962 
00963          template <typename T>
00964          inline T modulus(const T v0, const T v1)
00965          {
00966             typename details::number_type<T>::type num_type;
00967             return details::modulus_impl(v0,v1,num_type);
00968          }
00969 
00970          template <typename T>
00971          inline T pow(const T v0, const T v1)
00972          {
00973             typename details::number_type<T>::type num_type;
00974             return details::pow_impl(v0,v1,num_type);
00975          }
00976 
00977          template <typename T>
00978          inline T logn(const T v0, const T v1)
00979          {
00980             typename details::number_type<T>::type num_type;
00981             return details::logn_impl(v0,v1,num_type);
00982          }
00983 
00984          template <typename T>
00985          inline T root(const T v0, const T v1)
00986          {
00987             typename details::number_type<T>::type num_type;
00988             return details::root_impl(v0,v1,num_type);
00989          }
00990 
00991          template <typename T>
00992          inline T roundn(const T v0, const T v1)
00993          {
00994             typename details::number_type<T>::type num_type;
00995             return details::roundn_impl(v0,v1,num_type);
00996          }
00997 
00998          template <typename T>
00999          inline T hypot(const T v0, const T v1)
01000          {
01001             typename details::number_type<T>::type num_type;
01002             return details::hypot_impl(v0,v1,num_type);
01003          }
01004 
01005          template <typename T>
01006          inline T atan2(const T v0, const T v1)
01007          {
01008             typename details::number_type<T>::type num_type;
01009             return details::atan2_impl(v0,v1,num_type);
01010          }
01011 
01012          template <typename T>
01013          inline T shr(const T v0, const T v1)
01014          {
01015             typename details::number_type<T>::type num_type;
01016             return details::shr_impl(v0,v1,num_type);
01017          }
01018 
01019          template <typename T>
01020          inline T shl(const T v0, const T v1)
01021          {
01022             typename details::number_type<T>::type num_type;
01023             return details::shl_impl(v0,v1,num_type);
01024          }
01025 
01026          template <typename T>
01027          inline T and_opr(const T v0, const T v1)
01028          {
01029             typename details::number_type<T>::type num_type;
01030             return details::and_impl(v0,v1,num_type);
01031          }
01032 
01033          template <typename T>
01034          inline T nand_opr(const T v0, const T v1)
01035          {
01036             typename details::number_type<T>::type num_type;
01037             return details::nand_impl(v0,v1,num_type);
01038          }
01039 
01040          template <typename T>
01041          inline T or_opr(const T v0, const T v1)
01042          {
01043             typename details::number_type<T>::type num_type;
01044             return details::or_impl(v0,v1,num_type);
01045          }
01046 
01047          template <typename T>
01048          inline T nor_opr(const T v0, const T v1)
01049          {
01050             typename details::number_type<T>::type num_type;
01051             return details::nor_impl(v0,v1,num_type);
01052          }
01053 
01054          template <typename T>
01055          inline T xor_opr(const T v0, const T v1)
01056          {
01057             typename details::number_type<T>::type num_type;
01058             return details::xor_impl(v0,v1,num_type);
01059          }
01060 
01061          template <typename T>
01062          inline T xnor_opr(const T v0, const T v1)
01063          {
01064             typename details::number_type<T>::type num_type;
01065             return details::xnor_impl(v0,v1,num_type);
01066          }
01067 
01068          template <typename T>
01069          inline bool is_integer(const T v)
01070          {
01071             typename details::number_type<T>::type num_type;
01072             return details::is_integer_impl(v,num_type);
01073          }
01074 
01075          template <typename T, unsigned int N>
01076          struct fast_exp
01077          {
01078             static inline T result(T v)
01079             {
01080                unsigned int k = N;
01081                T l = T(1);
01082                while (k)
01083                {
01084                   if (k & 1)
01085                   {
01086                      l *= v;
01087                      --k;
01088                   }
01089                   v *= v;
01090                   k >>= 1;
01091                }
01092                return l;
01093             }
01094          };
01095 
01096          template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
01097          template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
01098          template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
01099          template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
01100          template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
01101          template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
01102          template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
01103          template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
01104          template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
01105          template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
01106          template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
01107 
01108          #define exprtk_define_unary_function(FunctionName)   \
01109          template <typename T>                                \
01110          inline T FunctionName (const T v)                    \
01111          {                                                    \
01112             typename details::number_type<T>::type num_type;  \
01113             return details:: FunctionName##_impl(v,num_type); \
01114          }                                                    \
01115 
01116          exprtk_define_unary_function(abs  )
01117          exprtk_define_unary_function(acos )
01118          exprtk_define_unary_function(acosh)
01119          exprtk_define_unary_function(asin )
01120          exprtk_define_unary_function(asinh)
01121          exprtk_define_unary_function(atan )
01122          exprtk_define_unary_function(atanh)
01123          exprtk_define_unary_function(ceil )
01124          exprtk_define_unary_function(cos  )
01125          exprtk_define_unary_function(cosh )
01126          exprtk_define_unary_function(exp  )
01127          exprtk_define_unary_function(expm1)
01128          exprtk_define_unary_function(floor)
01129          exprtk_define_unary_function(log  )
01130          exprtk_define_unary_function(log10)
01131          exprtk_define_unary_function(log2 )
01132          exprtk_define_unary_function(log1p)
01133          exprtk_define_unary_function(neg  )
01134          exprtk_define_unary_function(pos  )
01135          exprtk_define_unary_function(round)
01136          exprtk_define_unary_function(sin  )
01137          exprtk_define_unary_function(sinc )
01138          exprtk_define_unary_function(sinh )
01139          exprtk_define_unary_function(sqrt )
01140          exprtk_define_unary_function(tan  )
01141          exprtk_define_unary_function(tanh )
01142          exprtk_define_unary_function(cot  )
01143          exprtk_define_unary_function(sec  )
01144          exprtk_define_unary_function(csc  )
01145          exprtk_define_unary_function(r2d  )
01146          exprtk_define_unary_function(d2r  )
01147          exprtk_define_unary_function(d2g  )
01148          exprtk_define_unary_function(g2d  )
01149          exprtk_define_unary_function(notl )
01150          exprtk_define_unary_function(sgn  )
01151          exprtk_define_unary_function(erf  )
01152          exprtk_define_unary_function(erfc )
01153          exprtk_define_unary_function(frac )
01154          exprtk_define_unary_function(trunc)
01155          #undef exprtk_define_unary_function
01156       }
01157 
01158       template <typename Iterator, typename Type>
01159       static inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, Type& result)
01160       {
01161          if (end == itr) return false;
01162 
01163          Type t = 0;
01164          bool negative = false;
01165 
01166          if ('+' == (*itr))
01167             ++itr;
01168          else if ('-' == (*itr))
01169          {
01170             ++itr;
01171             negative = true;
01172          }
01173 
01174          if (end == itr)
01175             return false;
01176 
01177          unsigned int digit_count = 0;
01178          while ((end != itr) && ('0' == (*itr))) ++itr;
01179 
01180          bool return_result = true;
01181 
01182          while (end != itr)
01183          {
01184             const unsigned char digit = (*itr - '0');
01185             if (digit > 9)
01186             {
01187                return_result = false;
01188                break;
01189             }
01190             if ((++digit_count) <= numeric::numeric_info<Type>::bound_length)
01191             {
01192                t *= 10;
01193                t += digit;
01194             }
01195             else
01196             {
01197                typedef unsigned long long int base_type;
01198                static const base_type max_limit = +std::numeric_limits<Type>::max();
01199                static const base_type min_limit = -std::numeric_limits<Type>::min();
01200                base_type tmp = static_cast<base_type>(t) * 10 + digit;
01201                if (negative && static_cast<base_type>(tmp) > min_limit)
01202                   return_result = false;
01203                else if (static_cast<base_type>(tmp) > max_limit)
01204                   return_result = false;
01205                t = static_cast<Type>(tmp);
01206             }
01207             ++itr;
01208          }
01209          result = static_cast<Type>((negative) ? -t : t);
01210          return return_result;
01211       }
01212 
01213       template <typename Iterator, typename T>
01214       static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
01215       {
01216          typedef typename std::iterator_traits<Iterator>::value_type type;
01217          static const std::size_t nan_length = 3;
01218          if (std::distance(itr,end) != static_cast<int>(nan_length))
01219             return false;
01220          if (static_cast<type>('n') == (*itr))
01221          {
01222             if ((static_cast<type>('a') != *(itr + 1)) || (static_cast<type>('n') != *(itr + 2)))
01223             {
01224                return false;
01225             }
01226          }
01227          else if ((static_cast<type>('A') != *(itr + 1)) || (static_cast<type>('N') != *(itr + 2)))
01228          {
01229             return false;
01230          }
01231          t = std::numeric_limits<T>::quiet_NaN();
01232          return true;
01233       }
01234 
01235       template <typename Iterator, typename T>
01236       static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
01237       {
01238          static const char inf_uc[] = "INFINITY";
01239          static const char inf_lc[] = "infinity";
01240          static const std::size_t inf_length = 8;
01241          const std::size_t length = std::distance(itr,end);
01242          if ((3 != length) && (inf_length != length))
01243             return false;
01244          const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
01245          while (end != itr)
01246          {
01247             if (*inf_itr == static_cast<char>(*itr))
01248             {
01249                ++itr;
01250                ++inf_itr;
01251                continue;
01252             }
01253             else
01254                return false;
01255          }
01256          if (negative)
01257             t = -std::numeric_limits<T>::infinity();
01258          else
01259             t =  std::numeric_limits<T>::infinity();
01260          return true;
01261       }
01262 
01263       template <typename Iterator, typename T>
01264       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t)
01265       {
01266          if (end == itr_external)
01267             return false;
01268 
01269          Iterator itr = itr_external;
01270          double d = 0.0;
01271          bool negative = false;
01272 
01273          if ('+' == (*itr))
01274             ++itr;
01275          else if ('-' == (*itr))
01276          {
01277             ++itr;
01278             negative = true;
01279          }
01280 
01281          if (end == itr)
01282             return false;
01283 
01284          if (('I' <= (*itr)) && ((*itr) <= 'n'))
01285          {
01286             if (('i' == (*itr)) || ('I' == (*itr)))
01287             {
01288                return parse_inf(itr,end,t,negative);
01289             }
01290             else if (('n' == (*itr)) || ('N' == (*itr)))
01291             {
01292                return parse_nan(itr,end,t);
01293             }
01294             else
01295                return false;
01296          }
01297 
01298          bool instate = false;
01299          int pre_decimal = 0;
01300 
01301          if ('.' != (*itr))
01302          {
01303             const Iterator curr = itr;
01304             while ((end != itr) && ('0' == (*itr))) ++itr;
01305             const Iterator post_zero_cull_itr = itr;
01306             unsigned char digit = 0;
01307 
01308             #define parse_digit_1 \
01309             if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; if (end == ++itr) break; \
01310 
01311             #define parse_digit_2 \
01312             if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; ++itr;\
01313 
01314             while (end != itr)
01315             {
01316                parse_digit_1
01317                parse_digit_1
01318                parse_digit_1
01319                parse_digit_1
01320                parse_digit_1
01321                parse_digit_1
01322                parse_digit_1
01323                parse_digit_2
01324             }
01325             #undef parse_digit_1
01326             #undef parse_digit_2
01327             if (curr != itr) instate = true;
01328             pre_decimal = static_cast<int>(std::distance(post_zero_cull_itr,itr));
01329          }
01330 
01331          int exponent = 0;
01332 
01333          if (end != itr)
01334          {
01335             if ('.' == (*itr))
01336             {
01337                ++itr;
01338                const Iterator curr = itr;
01339                unsigned char digit = 0;
01340 
01341                #define parse_digit_1 \
01342                if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; if (end == ++itr) break; \
01343 
01344                #define parse_digit_2 \
01345                if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; ++itr;\
01346 
01347                while (end != itr)
01348                {
01349                   parse_digit_1
01350                   parse_digit_1
01351                   parse_digit_1
01352                   parse_digit_1
01353                   parse_digit_1
01354                   parse_digit_1
01355                   parse_digit_1
01356                   parse_digit_2
01357                }
01358                #undef parse_digit_1
01359                #undef parse_digit_2
01360                if (curr != itr) instate = true;
01361                exponent -= static_cast<int>(std::distance(curr,itr));
01362             }
01363 
01364             if (end != itr)
01365             {
01366                typename std::iterator_traits<Iterator>::value_type c = (*itr);
01367 
01368                if (('e' == c) || ('E' == c))
01369                {
01370                   ++itr;
01371                   int exp = 0;
01372                   if (!string_to_type_converter_impl_ref(itr,end,exp))
01373                   {
01374                      if (end == itr)
01375                         return false;
01376                      else
01377                         c = (*itr);
01378                   }
01379 
01380                   if (
01381                        (exp < numeric::numeric_info<T>::min_exp) ||
01382                        (numeric::numeric_info<T>::max_exp < exp)
01383                      )
01384                   {
01385                      return false;
01386                   }
01387 
01388                   exponent += exp;
01389                }
01390 
01391                if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
01392                   ++itr;
01393                else if ('#' == c)
01394                {
01395                   ++itr;
01396                   if (end == itr)
01397                      return false;
01398                   if ((10.0 != d) || (exponent != -1))
01399                      return false;
01400                   if (('I' <= (*itr)) && ((*itr) <= 'n'))
01401                   {
01402                      if (('i' == (*itr)) || ('I' == (*itr)))
01403                      {
01404                         return parse_inf(itr,end,t,negative);
01405                      }
01406                      else if (('n' == (*itr)) || ('N' == (*itr)))
01407                      {
01408                         return parse_nan(itr,end,t);
01409                      }
01410                      else
01411                         return false;
01412                   }
01413                   return false;
01414                }
01415             }
01416          }
01417 
01418          if ((end != itr) || (!instate))
01419             return false;
01420          if (0 != exponent)
01421          {
01422             if (
01423                  (std::numeric_limits<T>::max_exponent10 < (exponent + pre_decimal)) ||
01424                  (std::numeric_limits<T>::min_exponent10 > (exponent + pre_decimal))
01425                )
01426             {
01427                return false;
01428             }
01429 
01430             const int e = std::abs(exponent);
01431 
01432             static const double fract10[] =
01433                         {
01434                            0.0,
01435                            1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
01436                            1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
01437                            1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
01438                            1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
01439                            1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
01440                            1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
01441                            1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
01442                            1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
01443                            1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
01444                            1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
01445                            1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
01446                            1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
01447                            1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
01448                            1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
01449                            1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
01450                            1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
01451                            1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
01452                            1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
01453                            1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
01454                            1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
01455                            1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
01456                            1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
01457                            1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
01458                            1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
01459                            1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
01460                            1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
01461                            1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
01462                            1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
01463                            1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
01464                         };
01465 
01466             static const std::size_t fract10_size = sizeof(fract10) / sizeof(double);
01467 
01468             if (d != 0.0)
01469             {
01470                if (static_cast<std::size_t>(e) < fract10_size)
01471                {
01472                   if (exponent > 0)
01473                      d *= fract10[e];
01474                   else
01475                      d /= fract10[e];
01476                }
01477                else
01478                   d *= std::pow(10.0, 1.0 * exponent);
01479             }
01480          }
01481          t = static_cast<T>((negative) ? -d : d);
01482          return true;
01483       }
01484 
01485       template <typename T>
01486       inline bool string_to_real(const std::string& s, T& t)
01487       {
01488          const char* begin = s.data();
01489          const char* end   = s.data() + s.size();
01490          return string_to_real(begin,end,t);
01491       }
01492 
01493       template <typename T>
01494       struct functor_t
01495       {
01496          /*
01497             Note: The following definitions for Type, may require tweaking
01498                   based on the compiler and target architecture. The benchmark
01499                   should provide enough information to make the right choice.
01500          */
01501          //typedef T Type;
01502          //typedef const T Type;
01503          typedef const T& Type;
01504          typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
01505          typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
01506          typedef T (*bfunc_t)(Type t0, Type t1);
01507          typedef T (*ufunc_t)(Type t0);
01508       };
01509 
01510    } // namespace details
01511 
01512    namespace lexer
01513    {
01514       struct token
01515       {
01516          enum token_type
01517          {
01518             e_none        =   0, e_error       =   1, e_err_symbol  =   2,
01519             e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
01520             e_eof         =   6, e_number      =   7, e_symbol      =   8,
01521             e_string      =   9, e_assign      =  10, e_addass      =  11,
01522             e_subass      =  12, e_mulass      =  13, e_divass      =  14,
01523             e_shr         =  15, e_shl         =  16, e_lte         =  17,
01524             e_ne          =  18, e_gte         =  19, e_lt          = '<',
01525             e_gt          = '>', e_eq          = '=', e_rbracket    = ')',
01526             e_lbracket    = '(', e_rsqrbracket = ']', e_lsqrbracket = '[',
01527             e_rcrlbracket = '}', e_lcrlbracket = '{', e_comma       = ',',
01528             e_add         = '+', e_sub         = '-', e_div         = '/',
01529             e_mul         = '*', e_mod         = '%', e_pow         = '^',
01530             e_colon       = ':', e_ternary     = '?'
01531          };
01532 
01533          token()
01534          : type(e_none),
01535            value(""),
01536            position(std::numeric_limits<std::size_t>::max())
01537          {}
01538 
01539          void clear()
01540          {
01541             type     = e_none;
01542             value    = "";
01543             position = std::numeric_limits<std::size_t>::max();
01544          }
01545 
01546          template <typename Iterator>
01547          inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01548          {
01549             type = tt;
01550             value.assign(begin,end);
01551             if (base_begin)
01552                position = std::distance(base_begin,begin);
01553             return *this;
01554          }
01555 
01556          template <typename Iterator>
01557          inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01558          {
01559             type = e_symbol;
01560             value.assign(begin,end);
01561             if (base_begin)
01562                position = std::distance(base_begin,begin);
01563             return *this;
01564          }
01565 
01566          template <typename Iterator>
01567          inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01568          {
01569             type = e_number;
01570             value.assign(begin,end);
01571             if (base_begin)
01572                position = std::distance(base_begin,begin);
01573             return *this;
01574          }
01575 
01576          template <typename Iterator>
01577          inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01578          {
01579             type = e_string;
01580             value.assign(begin,end);
01581             if (base_begin)
01582                position = std::distance(base_begin,begin);
01583             return *this;
01584          }
01585 
01586          inline token& set_string(const std::string& s, const std::size_t p)
01587          {
01588             type     = e_string;
01589             value    = s;
01590             position = p;
01591             return *this;
01592          }
01593 
01594          template <typename Iterator>
01595          inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01596          {
01597             if (
01598                  (e_error      == et) ||
01599                  (e_err_symbol == et) ||
01600                  (e_err_number == et) ||
01601                  (e_err_string == et) ||
01602                  (e_err_sfunc  == et)
01603                )
01604             {
01605                type = et;
01606             }
01607             else
01608                type = e_error;
01609             value.assign(begin,end);
01610             if (base_begin)
01611                position = std::distance(base_begin,begin);
01612             return *this;
01613          }
01614 
01615          static inline std::string to_str(token_type t)
01616          {
01617             switch (t)
01618             {
01619                case e_none        : return "NONE";
01620                case e_error       : return "ERROR";
01621                case e_err_symbol  : return "ERROR_SYMBOL";
01622                case e_err_number  : return "ERROR_NUMBER";
01623                case e_err_string  : return "ERROR_STRING";
01624                case e_eof         : return "EOF";
01625                case e_number      : return "NUMBER";
01626                case e_symbol      : return "SYMBOL";
01627                case e_string      : return "STRING";
01628                case e_assign      : return ":=";
01629                case e_addass      : return "+=";
01630                case e_subass      : return "-=";
01631                case e_mulass      : return "*=";
01632                case e_divass      : return "/=";
01633                case e_shr         : return ">>";
01634                case e_shl         : return "<<";
01635                case e_lte         : return "<=";
01636                case e_ne          : return "!=";
01637                case e_gte         : return ">=";
01638                case e_lt          : return "<";
01639                case e_gt          : return ">";
01640                case e_eq          : return "=";
01641                case e_rbracket    : return ")";
01642                case e_lbracket    : return "(";
01643                case e_rsqrbracket : return "]";
01644                case e_lsqrbracket : return "[";
01645                case e_rcrlbracket : return "}";
01646                case e_lcrlbracket : return "{";
01647                case e_comma       : return ",";
01648                case e_add         : return "+";
01649                case e_sub         : return "-";
01650                case e_div         : return "/";
01651                case e_mul         : return "*";
01652                case e_mod         : return "%";
01653                case e_pow         : return "^";
01654                case e_colon       : return ":";
01655                case e_ternary     : return "?";
01656                default            : return "UNKNOWN";
01657             }
01658          }
01659 
01660          inline bool is_error() const
01661          {
01662             return (
01663                      (e_error      == type) ||
01664                      (e_err_symbol == type) ||
01665                      (e_err_number == type) ||
01666                      (e_err_string == type) ||
01667                      (e_err_sfunc  == type)
01668                    );
01669          }
01670 
01671          token_type type;
01672          std::string value;
01673          std::size_t position;
01674       };
01675 
01676       class generator
01677       {
01678       public:
01679 
01680          typedef token token_t;
01681          typedef std::deque<token_t> token_list_t;
01682          typedef std::deque<token_t>::iterator token_list_itr_t;
01683 
01684          generator()
01685          : base_itr_(0),
01686            s_itr_(0),
01687            s_end_(0)
01688          {
01689             clear();
01690          }
01691 
01692          inline void clear()
01693          {
01694             base_itr_ = 0;
01695             s_itr_    = 0;
01696             s_end_    = 0;
01697             token_list_.clear();
01698             token_itr_ = token_list_.end();
01699             store_token_itr_ = token_list_.end();
01700          }
01701 
01702          inline bool process(const std::string& str)
01703          {
01704             base_itr_ = str.data();
01705             s_itr_    = str.data();
01706             s_end_    = str.data() + str.size();
01707             eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
01708             token_list_.clear();
01709             while (!is_end(s_itr_))
01710             {
01711                scan_token();
01712                if (token_list_.empty())
01713                   return true;
01714                else if (token_list_.back().is_error())
01715                {
01716                   return false;
01717                }
01718             }
01719             return true;
01720          }
01721 
01722          inline bool empty() const
01723          {
01724             return token_list_.empty();
01725          }
01726 
01727          inline std::size_t size() const
01728          {
01729             return token_list_.size();
01730          }
01731 
01732          inline void begin()
01733          {
01734             token_itr_ = token_list_.begin();
01735             store_token_itr_ = token_list_.begin();
01736          }
01737 
01738          inline void store()
01739          {
01740             store_token_itr_ = token_itr_;
01741          }
01742 
01743          inline void restore()
01744          {
01745             token_itr_ = store_token_itr_;
01746          }
01747 
01748          inline token_t& next_token()
01749          {
01750             if (token_list_.end() != token_itr_)
01751             {
01752                return *token_itr_++;
01753             }
01754             else
01755                return eof_token_;
01756          }
01757 
01758          inline token_t& peek_next_token()
01759          {
01760             if (token_list_.end() != token_itr_)
01761             {
01762                return *token_itr_;
01763             }
01764             else
01765                return eof_token_;
01766          }
01767 
01768          inline token_t& operator[](const std::size_t& index)
01769          {
01770             if (index < token_list_.size())
01771                return token_list_[index];
01772             else
01773                return eof_token_;
01774          }
01775 
01776          inline token_t operator[](const std::size_t& index) const
01777          {
01778             if (index < token_list_.size())
01779                return token_list_[index];
01780             else
01781                return eof_token_;
01782          }
01783 
01784          inline bool finished() const
01785          {
01786             return (token_list_.end() == token_itr_);
01787          }
01788 
01789       private:
01790 
01791          inline bool is_end(const char* itr)
01792          {
01793             return (s_end_ == itr);
01794          }
01795 
01796          inline void skip_whitespace()
01797          {
01798             while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
01799             {
01800                ++s_itr_;
01801             }
01802          }
01803 
01804          inline void skip_comments()
01805          {
01806             #ifndef exprtk_disable_comments
01807             // The following comment styles are supported:
01808             // 1. // .... \n
01809             // 2. #  .... \n
01810             // 3. /* .... */
01811             struct test
01812             {
01813                static inline bool comment_start(const char c0, const char c1, int& mode, int& incr)
01814                {
01815                   mode = 0;
01816                        if ('#' == c0)    { mode = 1; incr = 1; }
01817                   else if ('/' == c0)
01818                   {
01819                           if ('/' == c1) { mode = 1; incr = 2; }
01820                      else if ('*' == c1) { mode = 2; incr = 2; }
01821                   }
01822                   return (0 != mode);
01823                }
01824 
01825                static inline bool comment_end(const char c0, const char c1, const int mode)
01826                {
01827                   return (
01828                            ((1 == mode) && ('\n' == c0)) ||
01829                            ((2 == mode) && ( '*' == c0) && ('/' == c1))
01830                          );
01831                }
01832             };
01833 
01834             int mode = 0;
01835             int increment = 0;
01836             if (is_end(s_itr_) || is_end((s_itr_ + 1)))
01837                return;
01838             else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment))
01839                return;
01840             s_itr_ += increment;
01841             while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode))
01842             {
01843                ++s_itr_;
01844             }
01845             if (!is_end(s_itr_))
01846             {
01847                s_itr_ += mode;
01848                skip_whitespace();
01849                skip_comments();
01850             }
01851             #endif
01852          }
01853 
01854          inline void scan_token()
01855          {
01856             skip_whitespace();
01857             skip_comments();
01858             if (is_end(s_itr_))
01859             {
01860                return;
01861             }
01862             else if (details::is_operator_char(*s_itr_))
01863             {
01864                scan_operator();
01865                return;
01866             }
01867             else if (details::is_letter(*s_itr_))
01868             {
01869                scan_symbol();
01870                return;
01871             }
01872             else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
01873             {
01874                scan_number();
01875                return;
01876             }
01877             else if ('$' == (*s_itr_))
01878             {
01879                scan_special_function();
01880                return;
01881             }
01882             #ifndef exprtk_disable_string_capabilities
01883             else if ('\'' == (*s_itr_))
01884             {
01885                scan_string();
01886                return;
01887             }
01888             #endif
01889             else if ('~' == (*s_itr_))
01890             {
01891                token_t t;
01892                t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01893                token_list_.push_back(t);
01894                ++s_itr_;
01895                return;
01896             }
01897             else
01898             {
01899                token_t t;
01900                t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_);
01901                token_list_.push_back(t);
01902                ++s_itr_;
01903             }
01904          }
01905 
01906          inline void scan_operator()
01907          {
01908             token_t t;
01909 
01910             if (!is_end(s_itr_ + 1))
01911             {
01912                token_t::token_type ttype = token_t::e_none;
01913                char c0 = s_itr_[0];
01914                char c1 = s_itr_[1];
01915                     if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
01916                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
01917                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
01918                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
01919                else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
01920                else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
01921                else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
01922                else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
01923                else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
01924                else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
01925                else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
01926                else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
01927 
01928                if (token_t::e_none != ttype)
01929                {
01930                   t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_);
01931                   token_list_.push_back(t);
01932                   s_itr_ += 2;
01933                   return;
01934                }
01935             }
01936             if ('<' == *s_itr_)
01937                t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_);
01938             else if ('>' == *s_itr_)
01939                t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_);
01940             else if (';' == *s_itr_)
01941                t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_);
01942             else if ('&' == *s_itr_)
01943                t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01944             else if ('|' == *s_itr_)
01945                t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01946             else
01947                t.set_operator(token_t::token_type(*s_itr_),s_itr_,s_itr_ + 1,base_itr_);
01948             token_list_.push_back(t);
01949             ++s_itr_;
01950          }
01951 
01952          inline void scan_symbol()
01953          {
01954             const char* begin = s_itr_;
01955             while (
01956                     (!is_end(s_itr_)) &&
01957                     (details::is_letter_or_digit(*s_itr_) || ((*s_itr_) == '_'))
01958                   )
01959             {
01960                ++s_itr_;
01961             }
01962             token_t t;
01963             t.set_symbol(begin,s_itr_,base_itr_);
01964             token_list_.push_back(t);
01965          }
01966 
01967          inline void scan_number()
01968          {
01969             /*
01970                Attempt to match a valid numeric value in one of the following formats:
01971                1. 123456
01972                2. 123.456
01973                3. 123.456e3
01974                4. 123.456E3
01975                5. 123.456e+3
01976                6. 123.456E+3
01977                7. 123.456e-3
01978                8. 123.456E-3
01979             */
01980             const char* begin      = s_itr_;
01981             bool dot_found         = false;
01982             bool e_found           = false;
01983             bool post_e_sign_found = false;
01984             token_t t;
01985 
01986             while (!is_end(s_itr_))
01987             {
01988                if ('.' == (*s_itr_))
01989                {
01990                   if (dot_found)
01991                   {
01992                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
01993                      token_list_.push_back(t);
01994                      return;
01995                   }
01996                   dot_found = true;
01997                   ++s_itr_;
01998                   continue;
01999                }
02000                else if (details::imatch('e',(*s_itr_)))
02001                {
02002                   const char& c = *(s_itr_ + 1);
02003 
02004                   if (is_end(s_itr_ + 1))
02005                   {
02006                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02007                      token_list_.push_back(t);
02008                      return;
02009                   }
02010                   else if (
02011                             ('+' != c) &&
02012                             ('-' != c) &&
02013                             !details::is_digit(c)
02014                           )
02015                   {
02016                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02017                      token_list_.push_back(t);
02018                      return;
02019                   }
02020 
02021                   e_found = true;
02022                   ++s_itr_;
02023                   continue;
02024                }
02025                else if (e_found && details::is_sign(*s_itr_))
02026                {
02027                   if (post_e_sign_found)
02028                   {
02029                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02030                      token_list_.push_back(t);
02031                      return;
02032                   }
02033 
02034                   post_e_sign_found = true;
02035                   ++s_itr_;
02036                   continue;
02037                }
02038                else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
02039                   break;
02040                else
02041                   ++s_itr_;
02042             }
02043 
02044             t.set_numeric(begin,s_itr_,base_itr_);
02045             token_list_.push_back(t);
02046             return;
02047          }
02048 
02049          inline void scan_special_function()
02050          {
02051             const char* begin = s_itr_;
02052             token_t t;
02053 
02054             // $fdd(x,x,x) = at least 11 chars
02055             if (std::distance(s_itr_,s_end_) < 11)
02056             {
02057                t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_);
02058                token_list_.push_back(t);
02059                return;
02060             }
02061 
02062             if (
02063                  !(('$' == *s_itr_)                       &&
02064                    (details::imatch  ('f',*(s_itr_ + 1))) &&
02065                    (details::is_digit(*(s_itr_ + 2)))     &&
02066                    (details::is_digit(*(s_itr_ + 3))))
02067                )
02068             {
02069                t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_);
02070                token_list_.push_back(t);
02071                return;
02072             }
02073 
02074             s_itr_ += 4; // $fdd = 4chars
02075 
02076             t.set_symbol(begin,s_itr_,base_itr_);
02077             token_list_.push_back(t);
02078 
02079             return;
02080          }
02081 
02082          #ifndef exprtk_disable_string_capabilities
02083          inline void scan_string()
02084          {
02085             const char* begin = s_itr_ + 1;
02086             token_t t;
02087             if (std::distance(s_itr_,s_end_) < 2)
02088             {
02089                t.set_error(token::e_err_string,s_itr_,s_end_,base_itr_);
02090                token_list_.push_back(t);
02091                return;
02092             }
02093             ++s_itr_;
02094 
02095             bool escaped_found = false;
02096             bool escaped = false;
02097 
02098             while (!is_end(s_itr_))
02099             {
02100                if ('\\' == *s_itr_)
02101                {
02102                   escaped_found = true;
02103                   escaped = true;
02104                   ++s_itr_;
02105                   continue;
02106                }
02107                else if (!escaped)
02108                {
02109                   if ('\'' == *s_itr_)
02110                      break;
02111                }
02112                else if (escaped)
02113                   escaped = false;
02114                ++s_itr_;
02115             }
02116 
02117             if (is_end(s_itr_))
02118             {
02119                t.set_error(token::e_err_string,begin,s_itr_,base_itr_);
02120                token_list_.push_back(t);
02121                return;
02122             }
02123 
02124             if (!escaped_found)
02125                t.set_string(begin,s_itr_,base_itr_);
02126             else
02127             {
02128                std::string parsed_string(begin,s_itr_);
02129                details::cleanup_escapes(parsed_string);
02130                t.set_string(parsed_string, std::distance(base_itr_,begin));
02131             }
02132 
02133             token_list_.push_back(t);
02134             ++s_itr_;
02135             return;
02136          }
02137          #endif
02138 
02139       private:
02140 
02141          token_list_t token_list_;
02142          token_list_itr_t token_itr_;
02143          token_list_itr_t store_token_itr_;
02144          token_t eof_token_;
02145          const char* base_itr_;
02146          const char* s_itr_;
02147          const char* s_end_;
02148 
02149          friend class token_scanner;
02150          friend class token_modifier;
02151          friend class token_inserter;
02152          friend class token_joiner;
02153       };
02154 
02155       class helper_interface
02156       {
02157       public:
02158 
02159          virtual void init()                     {              }
02160          virtual void reset()                    {              }
02161          virtual bool result()                   { return true; }
02162          virtual std::size_t process(generator&) { return 0;    }
02163          virtual ~helper_interface()             {              }
02164       };
02165 
02166       class token_scanner : public helper_interface
02167       {
02168       public:
02169 
02170          virtual ~token_scanner()
02171          {}
02172 
02173          explicit token_scanner(const std::size_t& stride)
02174          : stride_(stride)
02175          {
02176             if (stride > 4)
02177             {
02178                throw std::invalid_argument("token_scanner() - Invalid stride value");
02179             }
02180          }
02181 
02182          inline std::size_t process(generator& g)
02183          {
02184             if (!g.token_list_.empty())
02185             {
02186                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
02187                {
02188                   token t;
02189                   switch (stride_)
02190                   {
02191                      case 1 :
02192                               {
02193                                  const token& t0 = g.token_list_[i];
02194                                  if (!operator()(t0))
02195                                  {
02196                                     return i;
02197                                  }
02198                               }
02199                               break;
02200 
02201                      case 2 :
02202                               {
02203                                  const token& t0 = g.token_list_[i    ];
02204                                  const token& t1 = g.token_list_[i + 1];
02205                                  if (!operator()(t0,t1))
02206                                  {
02207                                     return i;
02208                                  }
02209                               }
02210                               break;
02211 
02212                      case 3 :
02213                               {
02214                                  const token& t0 = g.token_list_[i    ];
02215                                  const token& t1 = g.token_list_[i + 1];
02216                                  const token& t2 = g.token_list_[i + 2];
02217                                  if (!operator()(t0,t1,t2))
02218                                  {
02219                                     return i;
02220                                  }
02221                               }
02222                               break;
02223 
02224                      case 4 :
02225                               {
02226                                  const token& t0 = g.token_list_[i    ];
02227                                  const token& t1 = g.token_list_[i + 1];
02228                                  const token& t2 = g.token_list_[i + 2];
02229                                  const token& t3 = g.token_list_[i + 3];
02230                                  if (!operator()(t0,t1,t2,t3))
02231                                  {
02232                                     return i;
02233                                  }
02234                               }
02235                               break;
02236                   }
02237                }
02238             }
02239 
02240             return (g.token_list_.size() - stride_ + 1);
02241          }
02242 
02243          virtual bool operator()(const token&)
02244          {
02245             return false;
02246          }
02247 
02248          virtual bool operator()(const token&, const token&)
02249          {
02250             return false;
02251          }
02252 
02253          virtual bool operator()(const token&, const token&, const token&)
02254          {
02255             return false;
02256          }
02257 
02258          virtual bool operator()(const token&, const token&, const token&, const token&)
02259          {
02260             return false;
02261          }
02262 
02263       private:
02264 
02265          std::size_t stride_;
02266       };
02267 
02268       class token_modifier : public helper_interface
02269       {
02270       public:
02271 
02272          inline std::size_t process(generator& g)
02273          {
02274             std::size_t changes = 0;
02275             for (std::size_t i = 0; i < g.token_list_.size(); ++i)
02276             {
02277                if (modify(g.token_list_[i])) changes++;
02278             }
02279 
02280             return changes;
02281          }
02282 
02283          virtual bool modify(token& t) = 0;
02284       };
02285 
02286       class token_inserter : public helper_interface
02287       {
02288       public:
02289 
02290          explicit token_inserter(const std::size_t& stride)
02291          : stride_(stride)
02292          {
02293             if (stride > 5)
02294             {
02295                throw std::invalid_argument("token_inserter() - Invalid stride value");
02296             }
02297          }
02298 
02299          inline std::size_t process(generator& g)
02300          {
02301             if (g.token_list_.empty())
02302                return 0;
02303             std::size_t changes = 0;
02304             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
02305             {
02306                token t;
02307                int insert_index = -1;
02308                switch (stride_)
02309                {
02310                   case 1 : insert_index = insert(g.token_list_[i],t);
02311                            break;
02312 
02313                   case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t);
02314                            break;
02315 
02316                   case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t);
02317                            break;
02318 
02319                   case 4 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],t);
02320                            break;
02321 
02322                   case 5 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],g.token_list_[i + 4],t);
02323                            break;
02324                }
02325 
02326                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
02327                {
02328                   g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t);
02329                   changes++;
02330                }
02331             }
02332 
02333             return changes;
02334          }
02335 
02336          virtual inline int insert(const token&, token& )
02337          {
02338             return -1;
02339          }
02340 
02341          virtual inline int insert(const token&, const token&, token&)
02342          {
02343             return -1;
02344          }
02345 
02346          virtual inline int insert(const token&, const token&, const token&, token&)
02347          {
02348             return -1;
02349          }
02350 
02351          virtual inline int insert(const token&, const token&, const token&, const token&, token&)
02352          {
02353             return -1;
02354          }
02355 
02356          virtual inline int insert(const token&, const token&, const token&, const token&, const token&, token&)
02357          {
02358             return -1;
02359          }
02360 
02361       private:
02362 
02363          std::size_t stride_;
02364       };
02365 
02366       class token_joiner : public helper_interface
02367       {
02368       public:
02369 
02370          token_joiner(const std::size_t& stride)
02371          : stride_(stride)
02372          {}
02373 
02374          inline std::size_t process(generator& g)
02375          {
02376             if (g.token_list_.empty())
02377                return 0;
02378             switch (stride_)
02379             {
02380                case 2  : return process_stride_2(g);
02381                case 3  : return process_stride_3(g);
02382                default : return 0;
02383             }
02384          }
02385 
02386          virtual bool join(const token&, const token&, token&) { return false; }
02387          virtual bool join(const token&, const token&, const token&, token&) { return false; }
02388 
02389       private:
02390 
02391          inline std::size_t process_stride_2(generator& g)
02392          {
02393             if (g.token_list_.size() < 2)
02394                return 0;
02395             std::size_t changes = 0;
02396             for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i)
02397             {
02398                token t;
02399                if (join(g.token_list_[i],g.token_list_[i + 1],t))
02400                {
02401                   g.token_list_[i] = t;
02402                   g.token_list_.erase(g.token_list_.begin() + (i + 1));
02403                   ++changes;
02404                }
02405             }
02406 
02407             return changes;
02408          }
02409 
02410          inline std::size_t process_stride_3(generator& g)
02411          {
02412             if (g.token_list_.size() < 3)
02413                return 0;
02414             std::size_t changes = 0;
02415             for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i)
02416             {
02417                token t;
02418                if (join(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t))
02419                {
02420                   g.token_list_[i] = t;
02421                   g.token_list_.erase(g.token_list_.begin() + (i + 1),
02422                                       g.token_list_.begin() + (i + 3));
02423                   ++changes;
02424                }
02425             }
02426 
02427             return changes;
02428          }
02429 
02430          std::size_t stride_;
02431       };
02432 
02433       namespace helper
02434       {
02435 
02436          inline void dump(lexer::generator& generator)
02437          {
02438             for (std::size_t i = 0; i < generator.size(); ++i)
02439             {
02440                lexer::token t = generator[i];
02441                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
02442                       static_cast<unsigned int>(i),
02443                       static_cast<unsigned int>(t.position),
02444                       t.to_str(t.type).c_str(),
02445                       t.value.c_str());
02446             }
02447          }
02448 
02449          class commutative_inserter : public lexer::token_inserter
02450          {
02451          public:
02452 
02453             commutative_inserter()
02454             : lexer::token_inserter(2)
02455             {}
02456 
02457             inline void ignore_symbol(const std::string& symbol)
02458             {
02459                ignore_set_.insert(symbol);
02460             }
02461 
02462             inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
02463             {
02464                new_token.type     = lexer::token::e_mul;
02465                new_token.value    = "*";
02466                new_token.position = t1.position;
02467                bool match         = false;
02468 
02469                if (t0.type == lexer::token::e_symbol)
02470                {
02471                   if (ignore_set_.end() != ignore_set_.find(t0.value))
02472                   {
02473                      return -1;
02474                   }
02475                   else if (!t0.value.empty() && ('$' == t0.value[0]))
02476                   {
02477                      return -1;
02478                   }
02479                }
02480 
02481                if (t1.type == lexer::token::e_symbol)
02482                {
02483                   if (ignore_set_.end() != ignore_set_.find(t1.value))
02484                   {
02485                      return -1;
02486                   }
02487                }
02488                     if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
02489                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
02490                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
02491                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
02492                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
02493                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
02494                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
02495                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
02496                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
02497                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
02498                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
02499 
02500                return (match) ? 1 : -1;
02501             }
02502 
02503          private:
02504 
02505             std::set<std::string,details::ilesscompare> ignore_set_;
02506          };
02507 
02508          class operator_joiner : public token_joiner
02509          {
02510          public:
02511 
02512             operator_joiner(const std::size_t& stride)
02513             : token_joiner(stride)
02514             {}
02515 
02516             inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
02517             {
02518                // ': =' --> ':='
02519                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
02520                {
02521                   t.type = lexer::token::e_assign;
02522                   t.value = ":=";
02523                   t.position = t0.position;
02524                   return true;
02525                }
02526                // '+ =' --> '+='
02527                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
02528                {
02529                   t.type = lexer::token::e_addass;
02530                   t.value = "+=";
02531                   t.position = t0.position;
02532                   return true;
02533                }
02534                // '- =' --> '-='
02535                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
02536                {
02537                   t.type = lexer::token::e_subass;
02538                   t.value = "-=";
02539                   t.position = t0.position;
02540                   return true;
02541                }
02542                // '* =' --> '*='
02543                else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
02544                {
02545                   t.type = lexer::token::e_mulass;
02546                   t.value = "*=";
02547                   t.position = t0.position;
02548                   return true;
02549                }
02550                // '/ =' --> '/='
02551                else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
02552                {
02553                   t.type = lexer::token::e_divass;
02554                   t.value = "/=";
02555                   t.position = t0.position;
02556                   return true;
02557                }
02558                // '> =' --> '>='
02559                else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
02560                {
02561                   t.type = lexer::token::e_gte;
02562                   t.value = ">=";
02563                   t.position = t0.position;
02564                   return true;
02565                }
02566                // '< =' --> '<='
02567                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
02568                {
02569                   t.type = lexer::token::e_lte;
02570                   t.value = "<=";
02571                   t.position = t0.position;
02572                   return true;
02573                }
02574                // '= =' --> '=='
02575                else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
02576                {
02577                   t.type = lexer::token::e_eq;
02578                   t.value = "==";
02579                   t.position = t0.position;
02580                   return true;
02581                }
02582                // '! =' --> '!='
02583                else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
02584                {
02585                   t.type = lexer::token::e_ne;
02586                   t.value = "!=";
02587                   t.position = t0.position;
02588                   return true;
02589                }
02590                // '< >' --> '<>'
02591                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
02592                {
02593                   t.type = lexer::token::e_ne;
02594                   t.value = "<>";
02595                   t.position = t0.position;
02596                   return true;
02597                }
02598                else
02599                   return false;
02600             }
02601 
02602             inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
02603             {
02604                if (
02605                     (t0.type == lexer::token::e_lsqrbracket) &&
02606                     (t1.type == lexer::token::e_mul        ) &&
02607                     (t2.type == lexer::token::e_rsqrbracket)
02608                   )
02609                {
02610                   t.type = lexer::token::e_symbol;
02611                   t.value = "[*]";
02612                   t.position = t0.position;
02613                   return true;
02614                }
02615                else
02616                   return false;
02617             }
02618          };
02619 
02620          class bracket_checker : public lexer::token_scanner
02621          {
02622          public:
02623 
02624             bracket_checker()
02625             : token_scanner(1),
02626               state_(true)
02627             {}
02628 
02629             bool result()
02630             {
02631                if (!stack_.empty())
02632                {
02633                   lexer::token t;
02634                   t.value      = stack_.top().first;
02635                   t.position   = stack_.top().second;
02636                   error_token_ = t;
02637                   state_ = false;
02638                   return false;
02639                }
02640                else
02641                   return state_;
02642             }
02643 
02644             lexer::token error_token()
02645             {
02646                return error_token_;
02647             }
02648 
02649             void reset()
02650             {
02651                // Why? because msvc doesn't support swap properly.
02652                stack_ = std::stack<std::pair<char,std::size_t> >();
02653                state_ = true;
02654                error_token_.clear();
02655             }
02656 
02657             bool operator()(const lexer::token& t)
02658             {
02659                if (
02660                     !t.value.empty()                       &&
02661                     (lexer::token::e_string != t.type)     &&
02662                     (lexer::token::e_symbol != t.type)     &&
02663                     exprtk::details::is_bracket(t.value[0])
02664                   )
02665                {
02666                   char c = t.value[0];
02667                        if (t.type == lexer::token::e_lbracket)    stack_.push(std::make_pair(')',t.position));
02668                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
02669                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
02670                   else if (exprtk::details::is_right_bracket(c))
02671                   {
02672                      if (stack_.empty())
02673                      {
02674                         state_ = false;
02675                         error_token_ = t;
02676                         return false;
02677                      }
02678                      else if (c != stack_.top().first)
02679                      {
02680                         state_ = false;
02681                         error_token_ = t;
02682                         return false;
02683                      }
02684                      else
02685                         stack_.pop();
02686                   }
02687                }
02688 
02689                return true;
02690             }
02691 
02692          private:
02693 
02694             bool state_;
02695             std::stack<std::pair<char,std::size_t> > stack_;
02696             lexer::token error_token_;
02697          };
02698 
02699          class numeric_checker : public lexer::token_scanner
02700          {
02701          public:
02702 
02703             numeric_checker()
02704             : token_scanner(1),
02705               current_index_(0)
02706             {}
02707 
02708             bool result()
02709             {
02710                return error_list_.empty();
02711             }
02712 
02713             void reset()
02714             {
02715                error_list_.clear();
02716                current_index_ = 0;
02717             }
02718 
02719             bool operator()(const lexer::token& t)
02720             {
02721                if (token::e_number == t.type)
02722                {
02723                   double v;
02724                   if (!exprtk::details::string_to_real(t.value,v))
02725                   {
02726                      error_list_.push_back(current_index_);
02727                   }
02728                }
02729                ++current_index_;
02730                return true;
02731             }
02732 
02733             std::size_t error_count() const
02734             {
02735                return error_list_.size();
02736             }
02737 
02738             std::size_t error_index(const std::size_t& i)
02739             {
02740                if (i < error_list_.size())
02741                   return error_list_[i];
02742                else
02743                   return std::numeric_limits<std::size_t>::max();
02744             }
02745 
02746          private:
02747 
02748             std::size_t current_index_;
02749             std::deque<std::size_t> error_list_;
02750          };
02751 
02752          class symbol_replacer : public lexer::token_modifier
02753          {
02754          private:
02755 
02756             typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
02757 
02758          public:
02759 
02760             bool remove(const std::string& target_symbol)
02761             {
02762                replace_map_t::iterator itr = replace_map_.find(target_symbol);
02763                if (replace_map_.end() == itr)
02764                   return false;
02765                replace_map_.erase(itr);
02766                return true;
02767             }
02768 
02769             bool add_replace(const std::string& target_symbol,
02770                              const std::string& replace_symbol,
02771                              const lexer::token::token_type token_type = lexer::token::e_symbol)
02772             {
02773                replace_map_t::iterator itr = replace_map_.find(target_symbol);
02774                if (replace_map_.end() != itr)
02775                {
02776                   return false;
02777                }
02778                replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
02779                return true;
02780             }
02781 
02782             void clear()
02783             {
02784                replace_map_.clear();
02785             }
02786 
02787          private:
02788 
02789             bool modify(lexer::token& t)
02790             {
02791                if (lexer::token::e_symbol == t.type)
02792                {
02793                   if (replace_map_.empty())
02794                      return false;
02795                   replace_map_t::iterator itr = replace_map_.find(t.value);
02796                   if (replace_map_.end() != itr)
02797                   {
02798                      t.value = itr->second.first;
02799                      t.type  = itr->second.second;
02800                      return true;
02801                   }
02802                }
02803 
02804                return false;
02805             }
02806 
02807             replace_map_t replace_map_;
02808          };
02809 
02810          class sequence_validator : public lexer::token_scanner
02811          {
02812          private:
02813 
02814             typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
02815             typedef std::set<token_pair_t> set_t;
02816 
02817          public:
02818 
02819             sequence_validator()
02820             : lexer::token_scanner(2)
02821             {
02822                add_invalid(lexer::token::e_number ,lexer::token::e_number );
02823                add_invalid(lexer::token::e_string ,lexer::token::e_string );
02824                add_invalid(lexer::token::e_number ,lexer::token::e_string );
02825                add_invalid(lexer::token::e_string ,lexer::token::e_number );
02826                add_invalid(lexer::token::e_string ,lexer::token::e_colon  );
02827                add_invalid(lexer::token::e_string ,lexer::token::e_ternary);
02828                add_invalid(lexer::token::e_colon  ,lexer::token::e_string );
02829                add_invalid(lexer::token::e_ternary,lexer::token::e_string );
02830                add_invalid(lexer::token::e_assign ,lexer::token::e_string );
02831                add_invalid_set1(lexer::token::e_assign );
02832                add_invalid_set1(lexer::token::e_shr    );
02833                add_invalid_set1(lexer::token::e_shl    );
02834                add_invalid_set1(lexer::token::e_lte    );
02835                add_invalid_set1(lexer::token::e_ne     );
02836                add_invalid_set1(lexer::token::e_gte    );
02837                add_invalid_set1(lexer::token::e_lt     );
02838                add_invalid_set1(lexer::token::e_gt     );
02839                add_invalid_set1(lexer::token::e_eq     );
02840                add_invalid_set1(lexer::token::e_comma  );
02841                add_invalid_set1(lexer::token::e_add    );
02842                add_invalid_set1(lexer::token::e_sub    );
02843                add_invalid_set1(lexer::token::e_div    );
02844                add_invalid_set1(lexer::token::e_mul    );
02845                add_invalid_set1(lexer::token::e_mod    );
02846                add_invalid_set1(lexer::token::e_pow    );
02847                add_invalid_set1(lexer::token::e_colon  );
02848                add_invalid_set1(lexer::token::e_ternary);
02849             }
02850 
02851             bool result()
02852             {
02853                return error_list_.empty();
02854             }
02855 
02856             bool operator()(const lexer::token& t0, const lexer::token& t1)
02857             {
02858                set_t::value_type p = std::make_pair(t0.type,t1.type);
02859                if (invalid_bracket_check(t0.type,t1.type))
02860                {
02861                   error_list_.push_back(std::make_pair(t0,t1));
02862                }
02863                else if (invalid_comb_.find(p) != invalid_comb_.end())
02864                   error_list_.push_back(std::make_pair(t0,t1));
02865                return true;
02866             }
02867 
02868             std::size_t error_count()
02869             {
02870                return error_list_.size();
02871             }
02872 
02873             std::pair<lexer::token,lexer::token> error(const std::size_t index)
02874             {
02875                if (index < error_list_.size())
02876                {
02877                   return error_list_[index];
02878                }
02879                else
02880                {
02881                   static const lexer::token error_token;
02882                   return std::make_pair(error_token,error_token);
02883                }
02884             }
02885 
02886             void clear_errors()
02887             {
02888                error_list_.clear();
02889             }
02890 
02891          private:
02892 
02893             void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
02894             {
02895                invalid_comb_.insert(std::make_pair(base,t));
02896             }
02897 
02898             void add_invalid_set1(lexer::token::token_type t)
02899             {
02900                add_invalid(t,lexer::token::e_assign);
02901                add_invalid(t,lexer::token::e_shr   );
02902                add_invalid(t,lexer::token::e_shl   );
02903                add_invalid(t,lexer::token::e_lte   );
02904                add_invalid(t,lexer::token::e_ne    );
02905                add_invalid(t,lexer::token::e_gte   );
02906                add_invalid(t,lexer::token::e_lt    );
02907                add_invalid(t,lexer::token::e_gt    );
02908                add_invalid(t,lexer::token::e_eq    );
02909                add_invalid(t,lexer::token::e_comma );
02910                add_invalid(t,lexer::token::e_div   );
02911                add_invalid(t,lexer::token::e_mul   );
02912                add_invalid(t,lexer::token::e_mod   );
02913                add_invalid(t,lexer::token::e_pow   );
02914                add_invalid(t,lexer::token::e_colon );
02915             }
02916 
02917             bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
02918             {
02919                if (details::is_right_bracket(static_cast<char>(base)))
02920                {
02921                      switch (t)
02922                      {
02923                         case lexer::token::e_string : return true;
02924                         case lexer::token::e_assign : return (']' != base);
02925                         default                     : return false;
02926                      }
02927                }
02928                else if (details::is_left_bracket(static_cast<char>(base)))
02929                {
02930                   if (details::is_right_bracket(static_cast<char>(t)))
02931                      return false;
02932                   else if (details::is_left_bracket(static_cast<char>(t)))
02933                      return false;
02934                   else
02935                   {
02936                      switch (t)
02937                      {
02938                         case lexer::token::e_number  : return false;
02939                         case lexer::token::e_symbol  : return false;
02940                         case lexer::token::e_string  : return false;
02941                         case lexer::token::e_add     : return false;
02942                         case lexer::token::e_sub     : return false;
02943                         case lexer::token::e_colon   : return false;
02944                         case lexer::token::e_ternary : return false;
02945                         default                      : return true;
02946                      }
02947                   }
02948                }
02949                else if (details::is_right_bracket(static_cast<char>(t)))
02950                {
02951                   switch (base)
02952                   {
02953                      case lexer::token::e_number  : return false;
02954                      case lexer::token::e_symbol  : return false;
02955                      case lexer::token::e_string  : return false;
02956                      case lexer::token::e_eof     : return false;
02957                      case lexer::token::e_colon   : return false;
02958                      case lexer::token::e_ternary : return false;
02959                      default                      : return true;
02960                   }
02961                }
02962                else if (details::is_left_bracket(static_cast<char>(t)))
02963                {
02964                   switch (base)
02965                   {
02966                      case lexer::token::e_rbracket    : return true;
02967                      case lexer::token::e_rsqrbracket : return true;
02968                      case lexer::token::e_rcrlbracket : return true;
02969                      default                          : return false;
02970                   }
02971                }
02972 
02973                return false;
02974             }
02975 
02976             set_t invalid_comb_;
02977             std::deque<std::pair<lexer::token,lexer::token> > error_list_;
02978 
02979          };
02980 
02981          struct helper_assembly
02982          {
02983             inline bool register_scanner(lexer::token_scanner* scanner)
02984             {
02985                if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
02986                                                          token_scanner_list.end(),
02987                                                          scanner))
02988                {
02989                   return false;
02990                }
02991 
02992                token_scanner_list.push_back(scanner);
02993                return true;
02994             }
02995 
02996             inline bool register_modifier(lexer::token_modifier* modifier)
02997             {
02998                if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
02999                                                           token_modifier_list.end(),
03000                                                           modifier))
03001                {
03002                   return false;
03003                }
03004 
03005                token_modifier_list.push_back(modifier);
03006                return true;
03007             }
03008 
03009             inline bool register_joiner(lexer::token_joiner* joiner)
03010             {
03011                if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
03012                                                         token_joiner_list.end(),
03013                                                         joiner))
03014                {
03015                   return false;
03016                }
03017                token_joiner_list.push_back(joiner);
03018                return true;
03019             }
03020 
03021             inline bool register_inserter(lexer::token_inserter* inserter)
03022             {
03023                if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
03024                                                           token_inserter_list.end(),
03025                                                           inserter))
03026                {
03027                   return false;
03028                }
03029                token_inserter_list.push_back(inserter);
03030                return true;
03031             }
03032 
03033             inline bool run_modifiers(lexer::generator& g)
03034             {
03035                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
03036                bool result = true;
03037 
03038                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
03039                {
03040                   lexer::token_modifier& modifier = (*token_modifier_list[i]);
03041                   modifier.reset();
03042                   modifier.process(g);
03043                   if (!modifier.result())
03044                   {
03045                      error_token_modifier = token_modifier_list[i];
03046                      return false;
03047                   }
03048                }
03049 
03050                return result;
03051             }
03052 
03053             inline bool run_joiners(lexer::generator& g)
03054             {
03055                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
03056                bool result = true;
03057 
03058                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
03059                {
03060                   lexer::token_joiner& joiner = (*token_joiner_list[i]);
03061                   joiner.reset();
03062                   joiner.process(g);
03063                   if (!joiner.result())
03064                   {
03065                      error_token_joiner = token_joiner_list[i];
03066                      return false;
03067                   }
03068                }
03069 
03070                return result;
03071             }
03072 
03073             inline bool run_inserters(lexer::generator& g)
03074             {
03075                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
03076                bool result = true;
03077 
03078                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
03079                {
03080                   lexer::token_inserter& inserter = (*token_inserter_list[i]);
03081                   inserter.reset();
03082                   inserter.process(g);
03083                   if (!inserter.result())
03084                   {
03085                      error_token_inserter = token_inserter_list[i];
03086                      return false;
03087                   }
03088                }
03089 
03090                return result;
03091             }
03092 
03093             inline bool run_scanners(lexer::generator& g)
03094             {
03095                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
03096                bool result = true;
03097 
03098                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
03099                {
03100                   lexer::token_scanner& scanner = (*token_scanner_list[i]);
03101                   scanner.reset();
03102                   scanner.process(g);
03103                   if (!scanner.result())
03104                   {
03105                      error_token_scanner = token_scanner_list[i];
03106                      return false;
03107                   }
03108                }
03109 
03110                return result;
03111             }
03112 
03113             std::deque<lexer::token_scanner*>  token_scanner_list;
03114             std::deque<lexer::token_modifier*> token_modifier_list;
03115             std::deque<lexer::token_joiner*>   token_joiner_list;
03116             std::deque<lexer::token_inserter*> token_inserter_list;
03117 
03118             lexer::token_scanner*  error_token_scanner;
03119             lexer::token_modifier* error_token_modifier;
03120             lexer::token_joiner*   error_token_joiner;
03121             lexer::token_inserter* error_token_inserter;
03122          };
03123       }
03124    }
03125 
03126    namespace details
03127    {
03128       enum operator_type
03129       {
03130          e_default , e_null    , e_add     , e_sub     ,
03131          e_mul     , e_div     , e_mod     , e_pow     ,
03132          e_atan2   , e_min     , e_max     , e_avg     ,
03133          e_sum     , e_prod    , e_lt      , e_lte     ,
03134          e_eq      , e_equal   , e_ne      , e_nequal  ,
03135          e_gte     , e_gt      , e_and     , e_nand    ,
03136          e_or      , e_nor     , e_xor     , e_xnor    ,
03137          e_mand    , e_mor     , e_scand   , e_scor    ,
03138          e_shr     , e_shl     , e_abs     , e_acos    ,
03139          e_acosh   , e_asin    , e_asinh   , e_atan    ,
03140          e_atanh   , e_ceil    , e_cos     , e_cosh    ,
03141          e_exp     , e_expm1   , e_floor   , e_log     ,
03142          e_log10   , e_log2    , e_log1p   , e_logn    ,
03143          e_neg     , e_pos     , e_round   , e_roundn  ,
03144          e_root    , e_sqrt    , e_sin     , e_sinc    ,
03145          e_sinh    , e_sec     , e_csc     , e_tan     ,
03146          e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
03147          e_inrange , e_sgn     , e_r2d     , e_d2r     ,
03148          e_d2g     , e_g2d     , e_hypot   , e_notl    ,
03149          e_erf     , e_erfc    , e_frac    , e_trunc   ,
03150          e_assign  , e_addass  , e_subass  , e_mulass  ,
03151          e_divass  , e_in      , e_like    , e_ilike   ,
03152          e_multi   ,
03153 
03154          // Do not add new functions/operators after this point.
03155          e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
03156          e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
03157          e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
03158          e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
03159          e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
03160          e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
03161          e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
03162          e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
03163          e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
03164          e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
03165          e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
03166          e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
03167          e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
03168          e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
03169          e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
03170          e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
03171          e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
03172          e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
03173          e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
03174          e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
03175          e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
03176          e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
03177          e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
03178          e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
03179          e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
03180          e_sffinal = 1100,
03181          e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
03182          e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
03183          e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
03184          e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
03185          e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
03186          e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
03187          e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
03188          e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
03189          e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
03190          e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
03191          e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
03192          e_sf4ext44 = 2044, e_sf4ext45 = 2045
03193       };
03194 
03195       struct base_operation_t
03196       {
03197          base_operation_t(const operator_type t, const unsigned int& np)
03198          : type(t),
03199            num_params(np)
03200          {}
03201 
03202          operator_type type;
03203          unsigned int num_params;
03204       };
03205 
03206       namespace numeric
03207       {
03208          namespace details
03209          {
03210             template <typename T>
03211             inline T process_impl(const operator_type operation, const T& arg, real_type_tag)
03212             {
03213                switch (operation)
03214                {
03215                   case e_abs   : return numeric::abs  (arg);
03216                   case e_acos  : return numeric::acos (arg);
03217                   case e_acosh : return numeric::acosh(arg);
03218                   case e_asin  : return numeric::asin (arg);
03219                   case e_asinh : return numeric::asinh(arg);
03220                   case e_atan  : return numeric::atan (arg);
03221                   case e_atanh : return numeric::atanh(arg);
03222                   case e_ceil  : return numeric::ceil (arg);
03223                   case e_cos   : return numeric::cos  (arg);
03224                   case e_cosh  : return numeric::cosh (arg);
03225                   case e_exp   : return numeric::exp  (arg);
03226                   case e_expm1 : return numeric::expm1(arg);
03227                   case e_floor : return numeric::floor(arg);
03228                   case e_log   : return numeric::log  (arg);
03229                   case e_log10 : return numeric::log10(arg);
03230                   case e_log2  : return numeric::log2 (arg);
03231                   case e_log1p : return numeric::log1p(arg);
03232                   case e_neg   : return numeric::neg  (arg);
03233                   case e_pos   : return numeric::pos  (arg);
03234                   case e_round : return numeric::round(arg);
03235                   case e_sin   : return numeric::sin  (arg);
03236                   case e_sinc  : return numeric::sinc (arg);
03237                   case e_sinh  : return numeric::sinh (arg);
03238                   case e_sqrt  : return numeric::sqrt (arg);
03239                   case e_tan   : return numeric::tan  (arg);
03240                   case e_tanh  : return numeric::tanh (arg);
03241                   case e_cot   : return numeric::cot  (arg);
03242                   case e_sec   : return numeric::sec  (arg);
03243                   case e_csc   : return numeric::csc  (arg);
03244                   case e_r2d   : return numeric::r2d  (arg);
03245                   case e_d2r   : return numeric::d2r  (arg);
03246                   case e_d2g   : return numeric::d2g  (arg);
03247                   case e_g2d   : return numeric::g2d  (arg);
03248                   case e_notl  : return numeric::notl (arg);
03249                   case e_sgn   : return numeric::sgn  (arg);
03250                   case e_erf   : return numeric::erf  (arg);
03251                   case e_erfc  : return numeric::erfc (arg);
03252                   case e_frac  : return numeric::frac (arg);
03253                   case e_trunc : return numeric::trunc(arg);
03254                   default      : return std::numeric_limits<T>::quiet_NaN();
03255                }
03256             }
03257 
03258             template <typename T>
03259             inline T process_impl(const operator_type operation, const T& arg, int_type_tag)
03260             {
03261                switch (operation)
03262                {
03263                   case e_abs   : return numeric::abs  (arg);
03264                   case e_exp   : return numeric::exp  (arg);
03265                   case e_expm1 : return numeric::expm1(arg);
03266                   case e_log   : return numeric::log  (arg);
03267                   case e_log10 : return numeric::log10(arg);
03268                   case e_log2  : return numeric::log2 (arg);
03269                   case e_log1p : return numeric::log1p(arg);
03270                   case e_neg   : return numeric::neg  (arg);
03271                   case e_pos   : return numeric::pos  (arg);
03272                   case e_sqrt  : return numeric::sqrt (arg);
03273                   case e_notl  : return numeric::notl (arg);
03274                   case e_sgn   : return numeric::sgn  (arg);
03275                   default      : return std::numeric_limits<T>::quiet_NaN();
03276                }
03277             }
03278 
03279             template <typename T>
03280             inline T process_impl(const operator_type operation, const T& arg0, const T& arg1, real_type_tag)
03281             {
03282                switch (operation)
03283                {
03284                   case e_add    : return (arg0 + arg1);
03285                   case e_sub    : return (arg0 - arg1);
03286                   case e_mul    : return (arg0 * arg1);
03287                   case e_div    : return (arg0 / arg1);
03288                   case e_mod    : return modulus<T>(arg0,arg1);
03289                   case e_pow    : return pow<T>(arg0,arg1);
03290                   case e_atan2  : return atan2<T>(arg0,arg1);
03291                   case e_min    : return std::min<T>(arg0,arg1);
03292                   case e_max    : return std::max<T>(arg0,arg1);
03293                   case e_logn   : return logn<T>(arg0,arg1);
03294                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
03295                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
03296                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
03297                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
03298                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
03299                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
03300                   case e_and    : return and_opr<T> (arg0,arg1);
03301                   case e_nand   : return nand_opr<T>(arg0,arg1);
03302                   case e_or     : return or_opr<T>  (arg0,arg1);
03303                   case e_nor    : return nor_opr<T> (arg0,arg1);
03304                   case e_xor    : return xor_opr<T> (arg0,arg1);
03305                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
03306                   case e_root   : return root<T>    (arg0,arg1);
03307                   case e_roundn : return roundn<T>  (arg0,arg1);
03308                   case e_equal  : return equal<T>   (arg0,arg1);
03309                   case e_nequal : return nequal<T>  (arg0,arg1);
03310                   case e_hypot  : return hypot<T>   (arg0,arg1);
03311                   case e_shr    : return shr<T>     (arg0,arg1);
03312                   case e_shl    : return shl<T>     (arg0,arg1);
03313                   default       : return std::numeric_limits<T>::quiet_NaN();
03314                }
03315             }
03316 
03317             template <typename T>
03318             inline T process_impl(const operator_type operation, const T& arg0, const T& arg1, int_type_tag)
03319             {
03320                switch (operation)
03321                {
03322                   case e_add    : return (arg0 + arg1);
03323                   case e_sub    : return (arg0 - arg1);
03324                   case e_mul    : return (arg0 * arg1);
03325                   case e_div    : return (arg0 / arg1);
03326                   case e_mod    : return arg0 % arg1;
03327                   case e_pow    : return pow<T>(arg0,arg1);
03328                   case e_min    : return std::min<T>(arg0,arg1);
03329                   case e_max    : return std::max<T>(arg0,arg1);
03330                   case e_logn   : return logn<T>(arg0,arg1);
03331                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
03332                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
03333                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
03334                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
03335                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
03336                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
03337                   case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
03338                   case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
03339                   case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
03340                   case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
03341                   case e_xor    : return arg0 ^ arg1;
03342                   case e_xnor   : return !(arg0 ^ arg1);
03343                   case e_root   : return root<T>(arg0,arg1);
03344                   case e_equal  : return arg0 == arg1;
03345                   case e_nequal : return arg0 != arg1;
03346                   case e_hypot  : return hypot<T>(arg0,arg1);
03347                   case e_shr    : return arg0 >> arg1;
03348                   case e_shl    : return arg0 << arg1;
03349                   default       : return std::numeric_limits<T>::quiet_NaN();
03350                }
03351             }
03352          }
03353 
03354          template <typename T>
03355          inline T process(const operator_type operation, const T& arg)
03356          {
03357             typename details::number_type<T>::type num_type;
03358             return details::process_impl<T>(operation,arg,num_type);
03359          }
03360 
03361          template <typename T>
03362          inline T process(const operator_type operation, const T& arg0, const T& arg1)
03363          {
03364             typename details::number_type<T>::type num_type;
03365             return details::process_impl<T>(operation,arg0,arg1,num_type);
03366          }
03367       }
03368 
03369       template <typename T>
03370       class expression_node
03371       {
03372       public:
03373 
03374          enum node_type
03375          {
03376             e_none         , e_null         , e_constant     , e_unary        ,
03377             e_binary       , e_binary_ext   , e_trinary      , e_quaternary   ,
03378             e_quinary      , e_senary       , e_vararg       , e_conditional  ,
03379             e_while        , e_repeat       , e_for          , e_switch       ,
03380             e_mswitch      , e_variable     , e_stringvar    , e_stringconst  ,
03381             e_stringvarrng , e_cstringvarrng, e_function     , e_vafunction   ,
03382             e_add          , e_sub          , e_mul          , e_div          ,
03383             e_mod          , e_pow          , e_lt           , e_lte          ,
03384             e_gt           , e_gte          , e_eq           , e_ne           ,
03385             e_and          , e_nand         , e_or           , e_nor          ,
03386             e_xor          , e_xnor         , e_in           , e_like         ,
03387             e_ilike        , e_inranges     , e_ipow         , e_ipowinv      ,
03388             e_abs          , e_acos         , e_acosh        , e_asin         ,
03389             e_asinh        , e_atan         , e_atanh        , e_ceil         ,
03390             e_cos          , e_cosh         , e_exp          , e_expm1        ,
03391             e_floor        , e_log          , e_log10        , e_log2         ,
03392             e_log1p        , e_neg          , e_pos          , e_round        ,
03393             e_sin          , e_sinc         , e_sinh         , e_sqrt         ,
03394             e_tan          , e_tanh         , e_cot          , e_sec          ,
03395             e_csc          , e_r2d          , e_d2r          , e_d2g          ,
03396             e_g2d          , e_notl         , e_sgn          , e_erf          ,
03397             e_erfc         , e_frac         , e_trunc        , e_uvouv        ,
03398             e_vov          , e_cov          , e_voc          , e_vob          ,
03399             e_bov          , e_cob          , e_boc          , e_vovov        ,
03400             e_vovoc        , e_vocov        , e_covov        , e_covoc        ,
03401             e_vovovov      , e_vovovoc      , e_vovocov      , e_vocovov      ,
03402             e_covovov      , e_covocov      , e_vocovoc      , e_covovoc      ,
03403             e_vococov      , e_sf3ext       , e_sf4ext       , e_nulleq       ,
03404             e_vecelem      , e_break        , e_continue
03405          };
03406 
03407          typedef T value_type;
03408          typedef expression_node<T>* expression_ptr;
03409 
03410          virtual ~expression_node()
03411          {}
03412 
03413          virtual inline T value() const
03414          {
03415             return std::numeric_limits<T>::quiet_NaN();
03416          }
03417 
03418          virtual inline bool result() const
03419          {
03420             return (T(0) != value());
03421          }
03422 
03423          virtual inline expression_node<T>* branch(const std::size_t& index = 0) const
03424          {
03425             return reinterpret_cast<expression_ptr>(index * 0);
03426          }
03427 
03428          virtual inline node_type type() const
03429          {
03430             return e_none;
03431          }
03432       };
03433 
03434       inline bool is_true(const double v)
03435       {
03436          return (0.0 != v);
03437       }
03438 
03439       inline bool is_true(const long double v)
03440       {
03441          return (0.0 != v);
03442       }
03443 
03444       inline bool is_true(const float v)
03445       {
03446          return (0.0f != v);
03447       }
03448 
03449       template <typename T>
03450       inline bool is_true(const expression_node<T>* node)
03451       {
03452          return (T(0) != node->value());
03453       }
03454 
03455       template <typename T>
03456       inline bool is_false(const expression_node<T>* node)
03457       {
03458          return (T(0) == node->value());
03459       }
03460 
03461       template <typename T>
03462       inline bool is_unary_node(const expression_node<T>* node)
03463       {
03464          return node && (details::expression_node<T>::e_unary == node->type());
03465       }
03466 
03467       template <typename T>
03468       inline bool is_binary_node(const expression_node<T>* node)
03469       {
03470          return node && (details::expression_node<T>::e_binary == node->type());
03471       }
03472 
03473       template <typename T>
03474       inline bool is_variable_node(const expression_node<T>* node)
03475       {
03476          return node && (details::expression_node<T>::e_variable == node->type());
03477       }
03478 
03479       template <typename T>
03480       inline bool is_vector_node(const expression_node<T>* node)
03481       {
03482          return node && (details::expression_node<T>::e_vecelem == node->type());
03483       }
03484 
03485       template <typename T>
03486       inline bool is_constant_node(const expression_node<T>* node)
03487       {
03488          return node && (details::expression_node<T>::e_constant == node->type());
03489       }
03490 
03491       template <typename T>
03492       inline bool is_null_node(const expression_node<T>* node)
03493       {
03494          return node && (details::expression_node<T>::e_null == node->type());
03495       }
03496 
03497       template <typename T>
03498       inline bool is_break_node(const expression_node<T>* node)
03499       {
03500          return node && (details::expression_node<T>::e_break == node->type());
03501       }
03502 
03503       template <typename T>
03504       inline bool is_continue_node(const expression_node<T>* node)
03505       {
03506          return node && (details::expression_node<T>::e_continue == node->type());
03507       }
03508 
03509       template <typename T>
03510       inline bool is_function(const expression_node<T>* node)
03511       {
03512          return node && (details::expression_node<T>::e_function == node->type());
03513       }
03514 
03515       template <typename T>
03516       inline bool branch_deletable(expression_node<T>* node)
03517       {
03518          return !is_variable_node(node);
03519       }
03520 
03521       template <std::size_t N, typename T>
03522       inline bool all_nodes_valid(expression_node<T>* (&b)[N])
03523       {
03524          for (std::size_t i = 0; i < N; ++i)
03525          {
03526             if (0 == b[i]) return false;
03527          }
03528          return true;
03529       }
03530 
03531       template <typename T,
03532                 typename Allocator,
03533                 template <typename,typename> class Sequence>
03534       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
03535       {
03536          for (std::size_t i = 0; i < b.size(); ++i)
03537          {
03538             if (0 == b[i]) return false;
03539          }
03540          return true;
03541       }
03542 
03543       template <std::size_t N, typename T>
03544       inline bool all_nodes_variables(expression_node<T>* (&b)[N])
03545       {
03546          for (std::size_t i = 0; i < N; ++i)
03547          {
03548             if (0 == b[i])
03549                return false;
03550             else if (!is_variable_node(b[i]))
03551                return false;
03552          }
03553          return true;
03554       }
03555 
03556       template <typename T,
03557                 typename Allocator,
03558                 template <typename,typename> class Sequence>
03559       inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
03560       {
03561          for (std::size_t i = 0; i < b.size(); ++i)
03562          {
03563             if (0 == b[i])
03564                return false;
03565             else if (!is_variable_node(b[i]))
03566                return false;
03567          }
03568          return true;
03569       }
03570 
03571       template <typename NodeAllocator, typename T, std::size_t N>
03572       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
03573       {
03574          for (std::size_t i = 0; i < N; ++i)
03575          {
03576             free_node(node_allocator,b[i]);
03577          }
03578       }
03579 
03580       template <typename NodeAllocator,
03581                 typename T,
03582                 typename Allocator,
03583                 template <typename,typename> class Sequence>
03584       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
03585       {
03586          for (std::size_t i = 0; i < b.size(); ++i)
03587          {
03588             free_node(node_allocator,b[i]);
03589          }
03590          b.clear();
03591       }
03592 
03593       template <typename NodeAllocator, typename T>
03594       inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
03595       {
03596          if (0 != node)
03597          {
03598             if (is_variable_node(node) && !force_delete)
03599                return;
03600             node_allocator.free(node);
03601             node = 0;
03602          }
03603       }
03604 
03605       template <typename T>
03606       class null_node : public expression_node<T>
03607       {
03608       public:
03609 
03610          inline T value() const
03611          {
03612             return std::numeric_limits<T>::quiet_NaN();
03613          }
03614 
03615          inline typename expression_node<T>::node_type type() const
03616          {
03617             return expression_node<T>::e_null;
03618          }
03619       };
03620 
03621       template <typename T>
03622       class null_eq_node : public expression_node<T>
03623       {
03624       public:
03625 
03626          typedef expression_node<T>* expression_ptr;
03627 
03628          null_eq_node(expression_ptr branch, const bool equality = true)
03629          : branch_(branch),
03630            branch_deletable_(branch_deletable(branch_)),
03631            equality_(equality)
03632          {}
03633 
03634         ~null_eq_node()
03635          {
03636             if (branch_ && branch_deletable_)
03637             {
03638                delete branch_;
03639                branch_ = 0;
03640             }
03641          }
03642 
03643          inline T value() const
03644          {
03645             const T value = branch_->value();
03646             const bool result = (value != value);
03647             if (result)
03648                return (equality_) ? T(1) : T(0);
03649             else
03650                return (equality_) ? T(0) : T(1);
03651          }
03652 
03653          inline typename expression_node<T>::node_type type() const
03654          {
03655             return expression_node<T>::e_nulleq;
03656          }
03657 
03658          inline operator_type operation() const
03659          {
03660             return details::e_eq;
03661          }
03662 
03663          inline expression_node<T>* branch(const std::size_t&) const
03664          {
03665             return branch_;
03666          }
03667 
03668       private:
03669 
03670          operator_type operation_;
03671          expression_ptr branch_;
03672          bool branch_deletable_;
03673          bool equality_;
03674       };
03675 
03676       template <typename T>
03677       class literal_node : public expression_node<T>
03678       {
03679       public:
03680 
03681          explicit literal_node(const T& value)
03682          : value_(value)
03683          {}
03684 
03685          inline T value() const
03686          {
03687             return value_;
03688          }
03689 
03690          inline typename expression_node<T>::node_type type() const
03691          {
03692             return expression_node<T>::e_constant;
03693          }
03694 
03695          inline expression_node<T>* branch(const std::size_t&) const
03696          {
03697             return reinterpret_cast<expression_node<T>*>(0);
03698          }
03699 
03700       private:
03701 
03702          literal_node(literal_node<T>&) {}
03703          literal_node<T>& operator=(literal_node<T>&) { return *this; }
03704 
03705          const T value_;
03706       };
03707 
03708       template <typename T>
03709       class string_base_node : public expression_node<T>
03710       {
03711          virtual std::string str() const = 0;
03712       };
03713 
03714       template <typename T>
03715       class string_literal_node : public string_base_node<T>
03716       {
03717       public:
03718 
03719          explicit string_literal_node(const std::string& value)
03720          : value_(value)
03721          {}
03722 
03723          inline T value() const
03724          {
03725             return std::numeric_limits<T>::quiet_NaN();
03726          }
03727 
03728          inline typename expression_node<T>::node_type type() const
03729          {
03730             return expression_node<T>::e_stringconst;
03731          }
03732 
03733          inline expression_node<T>* branch(const std::size_t&) const
03734          {
03735             return reinterpret_cast<expression_node<T>*>(0);
03736          }
03737 
03738          std::string str() const
03739          {
03740             return value_;
03741          }
03742 
03743       private:
03744 
03745          string_literal_node(const string_literal_node<T>&);
03746          string_literal_node<T>& operator=(const string_literal_node<T>&);
03747 
03748          const std::string value_;
03749       };
03750 
03751       template <typename T>
03752       class unary_node : public expression_node<T>
03753       {
03754       public:
03755 
03756          typedef expression_node<T>* expression_ptr;
03757 
03758          unary_node(const operator_type& operation,
03759                     expression_ptr branch)
03760          : operation_(operation),
03761            branch_(branch),
03762            branch_deletable_(branch_deletable(branch_))
03763          {}
03764 
03765         ~unary_node()
03766          {
03767             if (branch_ && branch_deletable_)
03768             {
03769                delete branch_;
03770                branch_ = 0;
03771             }
03772          }
03773 
03774          inline T value() const
03775          {
03776             const T arg = branch_->value();
03777             return numeric::process<T>(operation_,arg);
03778          }
03779 
03780          inline typename expression_node<T>::node_type type() const
03781          {
03782             return expression_node<T>::e_unary;
03783          }
03784 
03785          inline operator_type operation() const
03786          {
03787             return operation_;
03788          }
03789 
03790          inline expression_node<T>* branch(const std::size_t&) const
03791          {
03792             return branch_;
03793          }
03794 
03795       private:
03796 
03797          operator_type operation_;
03798          expression_ptr branch_;
03799          bool branch_deletable_;
03800       };
03801 
03802       template <typename T, std::size_t D, bool B>
03803       struct construct_branch_pair
03804       {
03805          template <std::size_t N>
03806          static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
03807          {}
03808       };
03809 
03810       template <typename T, std::size_t D>
03811       struct construct_branch_pair<T,D,true>
03812       {
03813          template <std::size_t N>
03814          static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
03815          {
03816             if (b)
03817             {
03818                branch[D] = std::make_pair(b,branch_deletable(b));
03819             }
03820          }
03821       };
03822 
03823       template <std::size_t N, typename T>
03824       inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
03825                                 expression_node<T>* b0,
03826                                 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
03827                                 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
03828                                 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
03829                                 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
03830                                 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
03831                                 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
03832                                 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
03833                                 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
03834                                 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
03835       {
03836          construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
03837          construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
03838          construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
03839          construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
03840          construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
03841          construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
03842          construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
03843          construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
03844          construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
03845          construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
03846       }
03847 
03848       template <typename T, std::size_t N>
03849       struct cleanup_branches
03850       {
03851          static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
03852          {
03853             for (std::size_t i = 0; i < N; ++i)
03854             {
03855                if (branch[i].first && branch[i].second)
03856                {
03857                   delete branch[i].first;
03858                   branch[i].first = 0;
03859                }
03860             }
03861          }
03862       };
03863 
03864       template <typename T>
03865       class binary_node : public expression_node<T>
03866       {
03867       public:
03868 
03869          typedef expression_node<T>* expression_ptr;
03870          typedef std::pair<expression_ptr,bool> branch_t;
03871 
03872          binary_node(const operator_type& operation,
03873                      expression_ptr branch0,
03874                      expression_ptr branch1)
03875          : operation_(operation)
03876          {
03877             init_branches<2>(branch_,branch0,branch1);
03878          }
03879 
03880         ~binary_node()
03881          {
03882             cleanup_branches<T,2>::execute(branch_);
03883          }
03884 
03885          inline T value() const
03886          {
03887             const T arg0 = branch_[0].first->value();
03888             const T arg1 = branch_[1].first->value();
03889             return numeric::process<T>(operation_,arg0,arg1);
03890          }
03891 
03892          inline typename expression_node<T>::node_type type() const
03893          {
03894             return expression_node<T>::e_binary;
03895          }
03896 
03897          inline operator_type operation()
03898          {
03899             return operation_;
03900          }
03901 
03902          inline expression_node<T>* branch(const std::size_t& index = 0) const
03903          {
03904             if (0 == index)
03905                return branch_[0].first;
03906             else if (1 == index)
03907                return branch_[1].first;
03908             else
03909                return reinterpret_cast<expression_ptr>(0);
03910          }
03911 
03912       protected:
03913 
03914          operator_type operation_;
03915          branch_t branch_[2];
03916       };
03917 
03918       template <typename T, typename Operation>
03919       class binary_ext_node : public expression_node<T>
03920       {
03921       public:
03922 
03923          typedef expression_node<T>* expression_ptr;
03924          typedef std::pair<expression_ptr,bool> branch_t;
03925 
03926          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
03927          {
03928             init_branches<2>(branch_,branch0,branch1);
03929          }
03930 
03931         ~binary_ext_node()
03932          {
03933             cleanup_branches<T,2>::execute(branch_);
03934          }
03935 
03936          inline T value() const
03937          {
03938             const T arg0 = branch_[0].first->value();
03939             const T arg1 = branch_[1].first->value();
03940             return Operation::process(arg0,arg1);
03941          }
03942 
03943          inline typename expression_node<T>::node_type type() const
03944          {
03945             return expression_node<T>::e_binary_ext;
03946          }
03947 
03948          inline operator_type operation()
03949          {
03950             return Operation::operation();
03951          }
03952 
03953          inline expression_node<T>* branch(const std::size_t& index = 0) const
03954          {
03955             if (0 == index)
03956                return branch_[0].first;
03957             else if (1 == index)
03958                return branch_[1].first;
03959             else
03960                return reinterpret_cast<expression_ptr>(0);
03961          }
03962 
03963       protected:
03964 
03965          branch_t branch_[2];
03966       };
03967 
03968       template <typename T>
03969       class trinary_node : public expression_node<T>
03970       {
03971       public:
03972 
03973          typedef expression_node<T>* expression_ptr;
03974          typedef std::pair<expression_ptr,bool> branch_t;
03975 
03976          trinary_node(const operator_type& operation,
03977                       expression_ptr branch0,
03978                       expression_ptr branch1,
03979                       expression_ptr branch2)
03980          : operation_(operation)
03981          {
03982             init_branches<3>(branch_,branch0,branch1,branch2);
03983          }
03984 
03985         ~trinary_node()
03986          {
03987             cleanup_branches<T,3>::execute(branch_);
03988          }
03989 
03990          inline T value() const
03991          {
03992             const T arg0 = branch_[0].first->value();
03993             const T arg1 = branch_[1].first->value();
03994             const T arg2 = branch_[2].first->value();
03995             switch (operation_)
03996             {
03997                case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
03998                case e_min     : return std::min<T>(std::min<T>(arg0,arg1),arg2);
03999                case e_max     : return std::max<T>(std::max<T>(arg0,arg1),arg2);
04000                case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
04001                case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
04002                                    return arg1;
04003                                 else
04004                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
04005                default        : return std::numeric_limits<T>::quiet_NaN();
04006             }
04007          }
04008 
04009          inline typename expression_node<T>::node_type type() const
04010          {
04011             return expression_node<T>::e_trinary;
04012          }
04013 
04014       protected:
04015 
04016          operator_type operation_;
04017          branch_t branch_[3];
04018       };
04019 
04020       template <typename T>
04021       class quaternary_node : public expression_node<T>
04022       {
04023       public:
04024 
04025          typedef expression_node<T>* expression_ptr;
04026          typedef std::pair<expression_ptr,bool> branch_t;
04027 
04028          quaternary_node(const operator_type& operation,
04029                          expression_ptr branch0,
04030                          expression_ptr branch1,
04031                          expression_ptr branch2,
04032                          expression_ptr branch3)
04033          : operation_(operation)
04034          {
04035             init_branches<4>(branch_,branch0,branch1,branch2,branch3);
04036          }
04037 
04038         ~quaternary_node()
04039          {
04040             cleanup_branches<T,4>::execute(branch_);
04041          }
04042 
04043          inline T value() const
04044          {
04045             const T arg0 = branch_[0].first->value();
04046             const T arg1 = branch_[1].first->value();
04047             const T arg2 = branch_[2].first->value();
04048             const T arg3 = branch_[3].first->value();
04049             switch (operation_)
04050             {
04051                case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
04052                case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
04053                default    : return std::numeric_limits<T>::quiet_NaN();
04054             }
04055          }
04056 
04057          inline typename expression_node<T>::node_type type() const
04058          {
04059             return expression_node<T>::e_quaternary;
04060          }
04061 
04062       protected:
04063 
04064          operator_type operation_;
04065          branch_t branch_[4];
04066       };
04067 
04068       template <typename T>
04069       class quinary_node : public expression_node<T>
04070       {
04071       public:
04072 
04073          typedef expression_node<T>* expression_ptr;
04074          typedef std::pair<expression_ptr,bool> branch_t;
04075 
04076          quinary_node(const operator_type& operation,
04077                       expression_ptr branch0,
04078                       expression_ptr branch1,
04079                       expression_ptr branch2,
04080                       expression_ptr branch3,
04081                       expression_ptr branch4)
04082          : operation_(operation)
04083          {
04084             init_branches<5>(branch_,branch0,branch1,branch2,branch3,branch4);
04085          }
04086 
04087         ~quinary_node()
04088          {
04089             cleanup_branches<T,5>::execute(branch_);
04090          }
04091 
04092          inline T value() const
04093          {
04094             const T arg0 = branch_[0].first->value();
04095             const T arg1 = branch_[1].first->value();
04096             const T arg2 = branch_[2].first->value();
04097             const T arg3 = branch_[3].first->value();
04098             const T arg4 = branch_[4].first->value();
04099 
04100             switch (operation_)
04101             {
04102                case e_min  : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),arg4);
04103                case e_max  : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),arg4);
04104                default     : return std::numeric_limits<T>::quiet_NaN();
04105             }
04106          }
04107 
04108          inline typename expression_node<T>::node_type type() const
04109          {
04110             return expression_node<T>::e_quinary;
04111          }
04112 
04113       private:
04114 
04115          operator_type operation_;
04116          branch_t branch_[5];
04117       };
04118 
04119       template <typename T>
04120       class senary_node : public expression_node<T>
04121       {
04122       public:
04123 
04124          typedef expression_node<T>* expression_ptr;
04125          typedef std::pair<expression_ptr,bool> branch_t;
04126 
04127          senary_node(const operator_type& operation,
04128                      expression_ptr branch0,
04129                      expression_ptr branch1,
04130                      expression_ptr branch2,
04131                      expression_ptr branch3,
04132                      expression_ptr branch4,
04133                      expression_ptr branch5)
04134          : operation_(operation)
04135          {
04136             init_branches<6>(branch_,branch0,branch1,branch2,branch3,branch4,branch5);
04137          }
04138 
04139         ~senary_node()
04140          {
04141             cleanup_branches<T,6>::execute(branch_);
04142          }
04143 
04144          inline T value() const
04145          {
04146             const T arg0 = branch_[0].first->value();
04147             const T arg1 = branch_[1].first->value();
04148             const T arg2 = branch_[2].first->value();
04149             const T arg3 = branch_[3].first->value();
04150             const T arg4 = branch_[4].first->value();
04151             const T arg5 = branch_[5].first->value();
04152             switch (operation_)
04153             {
04154                case e_min     : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),std::min<T>(arg4,arg5));
04155                case e_max     : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),std::max<T>(arg4,arg5));
04156                case e_default :
04157                default        : return std::numeric_limits<T>::quiet_NaN();
04158             }
04159          }
04160 
04161          inline typename expression_node<T>::node_type type() const
04162          {
04163             return expression_node<T>::e_senary;
04164          }
04165 
04166       private:
04167 
04168          operator_type operation_;
04169          branch_t branch_[6];
04170       };
04171 
04172       template <typename T>
04173       class conditional_node : public expression_node<T>
04174       {
04175       public:
04176 
04177          typedef expression_node<T>* expression_ptr;
04178 
04179          conditional_node(expression_ptr test,
04180                           expression_ptr consequent,
04181                           expression_ptr alternative)
04182          : test_(test),
04183            consequent_(consequent),
04184            alternative_(alternative),
04185            test_deletable_(branch_deletable(test_)),
04186            consequent_deletable_(branch_deletable(consequent_)),
04187            alternative_deletable_(branch_deletable(alternative_))
04188          {}
04189 
04190         ~conditional_node()
04191          {
04192             if (test_        &&        test_deletable_) delete test_;
04193             if (consequent_  &&  consequent_deletable_) delete consequent_;
04194             if (alternative_ && alternative_deletable_) delete alternative_;
04195          }
04196 
04197          inline T value() const
04198          {
04199             if (is_true(test_))
04200                return consequent_->value();
04201             else
04202                return alternative_->value();
04203          }
04204 
04205          inline typename expression_node<T>::node_type type() const
04206          {
04207             return expression_node<T>::e_conditional;
04208          }
04209 
04210       private:
04211 
04212          expression_ptr test_;
04213          expression_ptr consequent_;
04214          expression_ptr alternative_;
04215          bool test_deletable_;
04216          bool consequent_deletable_;
04217          bool alternative_deletable_;
04218       };
04219 
04220       template <typename T>
04221       class cons_conditional_node : public expression_node<T>
04222       {
04223       public:
04224          // Consequent only conditional statement node
04225          typedef expression_node<T>* expression_ptr;
04226 
04227          cons_conditional_node(expression_ptr test,
04228                                expression_ptr consequent)
04229          : test_(test),
04230            consequent_(consequent),
04231            test_deletable_(branch_deletable(test_)),
04232            consequent_deletable_(branch_deletable(consequent_))
04233          {}
04234 
04235         ~cons_conditional_node()
04236          {
04237             if (test_        &&        test_deletable_) delete test_;
04238             if (consequent_  &&  consequent_deletable_) delete consequent_;
04239          }
04240 
04241          inline T value() const
04242          {
04243             if (is_true(test_))
04244                return consequent_->value();
04245             else
04246                return std::numeric_limits<T>::quiet_NaN();
04247          }
04248 
04249          inline typename expression_node<T>::node_type type() const
04250          {
04251             return expression_node<T>::e_conditional;
04252          }
04253 
04254       private:
04255 
04256          expression_ptr test_;
04257          expression_ptr consequent_;
04258          bool test_deletable_;
04259          bool consequent_deletable_;
04260       };
04261 
04262       #ifndef exprtk_disable_break_continue
04263       template <typename T>
04264       class break_exception : public std::exception
04265       {
04266       public:
04267 
04268          break_exception(const T& v)
04269          : value(v)
04270          {}
04271 
04272          T value;
04273       };
04274 
04275       class continue_exception : public std::exception
04276       {};
04277 
04278       template <typename T>
04279       class break_node : public expression_node<T>
04280       {
04281       public:
04282 
04283          typedef expression_node<T>* expression_ptr;
04284 
04285          break_node(expression_ptr ret = expression_ptr(0))
04286          : return_(ret),
04287            return_deletable_(branch_deletable(return_))
04288          {}
04289 
04290         ~break_node()
04291          {
04292             if (return_deletable_)
04293             {
04294                delete return_;
04295             }
04296          }
04297 
04298          inline T value() const
04299          {
04300             throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
04301             return std::numeric_limits<T>::quiet_NaN();
04302          }
04303 
04304          inline typename expression_node<T>::node_type type() const
04305          {
04306             return expression_node<T>::e_break;
04307          }
04308 
04309       private:
04310 
04311          expression_ptr return_;
04312          bool return_deletable_;
04313       };
04314 
04315       template <typename T>
04316       class continue_node : public expression_node<T>
04317       {
04318       public:
04319 
04320          inline T value() const
04321          {
04322             throw continue_exception();
04323             return std::numeric_limits<T>::quiet_NaN();
04324          }
04325 
04326          inline typename expression_node<T>::node_type type() const
04327          {
04328             return expression_node<T>::e_break;
04329          }
04330       };
04331       #endif
04332 
04333       template <typename T>
04334       class while_loop_node : public expression_node<T>
04335       {
04336       public:
04337 
04338          typedef expression_node<T>* expression_ptr;
04339 
04340          while_loop_node(expression_ptr condition, expression_ptr loop_body)
04341          : condition_(condition),
04342            loop_body_(loop_body),
04343            condition_deletable_(branch_deletable(condition_)),
04344            loop_body_deletable_(branch_deletable(loop_body_))
04345          {}
04346 
04347         ~while_loop_node()
04348          {
04349             if (condition_ && condition_deletable_)
04350             {
04351                delete condition_;
04352             }
04353 
04354             if (loop_body_ && loop_body_deletable_)
04355             {
04356                delete loop_body_;
04357             }
04358          }
04359 
04360          inline T value() const
04361          {
04362             T result = T(0);
04363             while (is_true(condition_))
04364             {
04365                result = loop_body_->value();
04366             }
04367             return result;
04368          }
04369 
04370          inline typename expression_node<T>::node_type type() const
04371          {
04372             return expression_node<T>::e_while;
04373          }
04374 
04375       private:
04376 
04377          expression_ptr condition_;
04378          expression_ptr loop_body_;
04379          bool condition_deletable_;
04380          bool loop_body_deletable_;
04381       };
04382 
04383       template <typename T>
04384       class repeat_until_loop_node : public expression_node<T>
04385       {
04386       public:
04387 
04388          typedef expression_node<T>* expression_ptr;
04389 
04390          repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
04391          : condition_(condition),
04392            loop_body_(loop_body),
04393            condition_deletable_(branch_deletable(condition_)),
04394            loop_body_deletable_(branch_deletable(loop_body_))
04395          {}
04396 
04397         ~repeat_until_loop_node()
04398          {
04399             if (condition_ && condition_deletable_)
04400             {
04401                delete condition_;
04402             }
04403 
04404             if (loop_body_ && loop_body_deletable_)
04405             {
04406                delete loop_body_;
04407             }
04408          }
04409 
04410          inline T value() const
04411          {
04412             T result = T(0);
04413             do
04414             {
04415                result = loop_body_->value();
04416             }
04417             while (is_false(condition_));
04418             return result;
04419          }
04420 
04421          inline typename expression_node<T>::node_type type() const
04422          {
04423             return expression_node<T>::e_repeat;
04424          }
04425 
04426       private:
04427 
04428          expression_ptr condition_;
04429          expression_ptr loop_body_;
04430          bool condition_deletable_;
04431          bool loop_body_deletable_;
04432       };
04433 
04434       template <typename T>
04435       class for_loop_node : public expression_node<T>
04436       {
04437       public:
04438 
04439          typedef expression_node<T>* expression_ptr;
04440 
04441          for_loop_node(expression_ptr initializer,
04442                        expression_ptr condition,
04443                        expression_ptr incrementor,
04444                        expression_ptr loop_body,
04445                        expression_ptr loop_var,
04446                        T* loop_counter_var = 0)
04447          : initializer_(initializer),
04448            condition_  (condition),
04449            incrementor_(incrementor),
04450            loop_body_  (loop_body),
04451            loop_var_   (loop_var),
04452            initializer_deletable_(branch_deletable(initializer_)),
04453            condition_deletable_  (branch_deletable(condition_  )),
04454            incrementor_deletable_(branch_deletable(incrementor_)),
04455            loop_body_deletable_  (branch_deletable(loop_body_  )),
04456            loop_counter_var_(loop_counter_var)
04457          {}
04458 
04459         ~for_loop_node()
04460          {
04461             if (initializer_ && initializer_deletable_)
04462             {
04463                delete initializer_;
04464             }
04465 
04466             if (condition_ && condition_deletable_)
04467             {
04468                delete condition_;
04469             }
04470 
04471             if (incrementor_ && incrementor_deletable_)
04472             {
04473                delete incrementor_;
04474             }
04475 
04476             if (loop_body_ && loop_body_deletable_)
04477             {
04478                delete loop_body_;
04479             }
04480 
04481             if (loop_var_)
04482             {
04483                delete loop_var_;
04484             }
04485 
04486             if (loop_counter_var_)
04487             {
04488                delete loop_counter_var_;
04489             }
04490          }
04491 
04492          inline T value() const
04493          {
04494             T result = T(0);
04495 
04496             if (initializer_)
04497                initializer_->value();
04498 
04499             if (incrementor_)
04500             {
04501                while (is_true(condition_))
04502                {
04503                   result = loop_body_->value();
04504                   incrementor_->value();
04505                }
04506             }
04507             else
04508             {
04509                while (is_true(condition_))
04510                {
04511                   result = loop_body_->value();
04512                }
04513             }
04514 
04515             return result;
04516          }
04517 
04518          inline typename expression_node<T>::node_type type() const
04519          {
04520             return expression_node<T>::e_for;
04521          }
04522 
04523       private:
04524 
04525          expression_ptr initializer_;
04526          expression_ptr condition_  ;
04527          expression_ptr incrementor_;
04528          expression_ptr loop_body_  ;
04529          expression_ptr loop_var_   ;
04530          bool initializer_deletable_;
04531          bool condition_deletable_  ;
04532          bool incrementor_deletable_;
04533          bool loop_body_deletable_  ;
04534          T* loop_counter_var_;
04535       };
04536 
04537       #ifndef exprtk_disable_break_continue
04538       template <typename T>
04539       class while_loop_bc_node : public expression_node<T>
04540       {
04541       public:
04542 
04543          typedef expression_node<T>* expression_ptr;
04544 
04545          while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
04546          : condition_(condition),
04547            loop_body_(loop_body),
04548            condition_deletable_(branch_deletable(condition_)),
04549            loop_body_deletable_(branch_deletable(loop_body_))
04550          {}
04551 
04552         ~while_loop_bc_node()
04553          {
04554             if (condition_ && condition_deletable_)
04555             {
04556                delete condition_;
04557             }
04558 
04559             if (loop_body_ && loop_body_deletable_)
04560             {
04561                delete loop_body_;
04562             }
04563          }
04564 
04565          inline T value() const
04566          {
04567             T result = T(0);
04568             while (is_true(condition_))
04569             {
04570                try
04571                {
04572                   result = loop_body_->value();
04573                }
04574                catch(const break_exception<T>& e)
04575                {
04576                   return e.value;
04577                }
04578                catch(const continue_exception&)
04579                {}
04580             }
04581             return result;
04582          }
04583 
04584          inline typename expression_node<T>::node_type type() const
04585          {
04586             return expression_node<T>::e_while;
04587          }
04588 
04589       private:
04590 
04591          expression_ptr condition_;
04592          expression_ptr loop_body_;
04593          bool condition_deletable_;
04594          bool loop_body_deletable_;
04595       };
04596 
04597       template <typename T>
04598       class repeat_until_loop_bc_node : public expression_node<T>
04599       {
04600       public:
04601 
04602          typedef expression_node<T>* expression_ptr;
04603 
04604          repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
04605          : condition_(condition),
04606            loop_body_(loop_body),
04607            condition_deletable_(branch_deletable(condition_)),
04608            loop_body_deletable_(branch_deletable(loop_body_))
04609          {}
04610 
04611         ~repeat_until_loop_bc_node()
04612          {
04613             if (condition_ && condition_deletable_)
04614             {
04615                delete condition_;
04616             }
04617 
04618             if (loop_body_ && loop_body_deletable_)
04619             {
04620                delete loop_body_;
04621             }
04622          }
04623 
04624          inline T value() const
04625          {
04626             T result = T(0);
04627             do
04628             {
04629                try
04630                {
04631                   result = loop_body_->value();
04632                }
04633                catch(const break_exception<T>& e)
04634                {
04635                   return e.value;
04636                }
04637                catch(const continue_exception&)
04638                {}
04639             }
04640             while (is_false(condition_));
04641             return result;
04642          }
04643 
04644          inline typename expression_node<T>::node_type type() const
04645          {
04646             return expression_node<T>::e_repeat;
04647          }
04648 
04649       private:
04650 
04651          expression_ptr condition_;
04652          expression_ptr loop_body_;
04653          bool condition_deletable_;
04654          bool loop_body_deletable_;
04655       };
04656 
04657       template <typename T>
04658       class for_loop_bc_node : public expression_node<T>
04659       {
04660       public:
04661 
04662          typedef expression_node<T>* expression_ptr;
04663 
04664          for_loop_bc_node(expression_ptr initializer,
04665                        expression_ptr condition,
04666                        expression_ptr incrementor,
04667                        expression_ptr loop_body,
04668                        expression_ptr loop_var,
04669                        T* loop_counter_var = 0)
04670          : initializer_(initializer),
04671            condition_  (condition),
04672            incrementor_(incrementor),
04673            loop_body_  (loop_body),
04674            loop_var_   (loop_var),
04675            initializer_deletable_(branch_deletable(initializer_)),
04676            condition_deletable_  (branch_deletable(condition_  )),
04677            incrementor_deletable_(branch_deletable(incrementor_)),
04678            loop_body_deletable_  (branch_deletable(loop_body_  )),
04679            loop_counter_var_(loop_counter_var)
04680          {}
04681 
04682         ~for_loop_bc_node()
04683          {
04684             if (initializer_ && initializer_deletable_)
04685             {
04686                delete initializer_;
04687             }
04688 
04689             if (condition_ && condition_deletable_)
04690             {
04691                delete condition_;
04692             }
04693 
04694             if (incrementor_ && incrementor_deletable_)
04695             {
04696                delete incrementor_;
04697             }
04698 
04699             if (loop_body_ && loop_body_deletable_)
04700             {
04701                delete loop_body_;
04702             }
04703 
04704             if (loop_var_)
04705             {
04706                delete loop_var_;
04707             }
04708 
04709             if (loop_counter_var_)
04710             {
04711                delete loop_counter_var_;
04712             }
04713          }
04714 
04715          inline T value() const
04716          {
04717             T result = T(0);
04718 
04719             if (initializer_)
04720                initializer_->value();
04721 
04722             if (incrementor_)
04723             {
04724                while (is_true(condition_))
04725                {
04726                   try
04727                   {
04728                      result = loop_body_->value();
04729                   }
04730                   catch(const break_exception<T>& e)
04731                   {
04732                      return e.value;
04733                   }
04734                   catch(const continue_exception&)
04735                   {}
04736                   incrementor_->value();
04737                }
04738             }
04739             else
04740             {
04741                while (is_true(condition_))
04742                {
04743                   try
04744                   {
04745                      result = loop_body_->value();
04746                   }
04747                   catch(const break_exception<T>& e)
04748                   {
04749                      return e.value;
04750                   }
04751                   catch(const continue_exception&)
04752                   {}
04753                }
04754             }
04755 
04756             return result;
04757          }
04758 
04759          inline typename expression_node<T>::node_type type() const
04760          {
04761             return expression_node<T>::e_for;
04762          }
04763 
04764       private:
04765 
04766          expression_ptr initializer_;
04767          expression_ptr condition_  ;
04768          expression_ptr incrementor_;
04769          expression_ptr loop_body_  ;
04770          expression_ptr loop_var_   ;
04771          bool initializer_deletable_;
04772          bool condition_deletable_  ;
04773          bool incrementor_deletable_;
04774          bool loop_body_deletable_  ;
04775          T* loop_counter_var_;
04776       };
04777       #endif
04778 
04779       template <typename T>
04780       class switch_node : public expression_node<T>
04781       {
04782       public:
04783 
04784          typedef expression_node<T>* expression_ptr;
04785 
04786          template <typename Allocator,
04787                    template <typename,typename> class Sequence>
04788          switch_node(const Sequence<expression_ptr,Allocator>& arglist)
04789          {
04790             if (1 != (arglist.size() & 1))
04791                return;
04792             arg_list_.resize(arglist.size());
04793             delete_branch_.resize(arglist.size());
04794             for (std::size_t i = 0; i < arglist.size(); ++i)
04795             {
04796                if (arglist[i])
04797                {
04798                        arg_list_[i] = arglist[i];
04799                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
04800                }
04801                else
04802                {
04803                   arg_list_.clear();
04804                   delete_branch_.clear();
04805                   return;
04806                }
04807             }
04808          }
04809 
04810         ~switch_node()
04811          {
04812             for (std::size_t i = 0; i < arg_list_.size(); ++i)
04813             {
04814                if (arg_list_[i] && delete_branch_[i])
04815                {
04816                   delete arg_list_[i];
04817                   arg_list_[i] = 0;
04818                }
04819             }
04820          }
04821 
04822          inline T value() const
04823          {
04824             if (!arg_list_.empty())
04825             {
04826                if (1 != (arg_list_.size() & 1))
04827                {
04828                   return std::numeric_limits<T>::quiet_NaN();
04829                }
04830 
04831                for (std::size_t i = 0; i < arg_list_.size() / 2; ++i)
04832                {
04833                   expression_ptr condition  = arg_list_[(2 * i)    ];
04834                   expression_ptr consequent = arg_list_[(2 * i) + 1];
04835                   if (is_true(condition))
04836                   {
04837                      return consequent->value();
04838                   }
04839                }
04840 
04841                return arg_list_.back()->value();
04842             }
04843             else
04844                return std::numeric_limits<T>::quiet_NaN();
04845          }
04846 
04847          inline typename expression_node<T>::node_type type() const
04848          {
04849             return expression_node<T>::e_switch;
04850          }
04851 
04852       private:
04853 
04854          std::vector<expression_ptr> arg_list_;
04855          std::vector<unsigned char> delete_branch_;
04856       };
04857 
04858       template <typename T>
04859       class multi_switch_node : public expression_node<T>
04860       {
04861       public:
04862 
04863          typedef expression_node<T>* expression_ptr;
04864 
04865          template <typename Allocator,
04866                    template <typename,typename> class Sequence>
04867          multi_switch_node(const Sequence<expression_ptr,Allocator>& arglist)
04868          {
04869             if (0 != (arglist.size() & 1))
04870                return;
04871             arg_list_.resize(arglist.size());
04872             delete_branch_.resize(arglist.size());
04873             for (std::size_t i = 0; i < arglist.size(); ++i)
04874             {
04875                if (arglist[i])
04876                {
04877                        arg_list_[i] = arglist[i];
04878                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
04879                }
04880                else
04881                {
04882                   arg_list_.clear();
04883                   delete_branch_.clear();
04884                   return;
04885                }
04886             }
04887          }
04888 
04889         ~multi_switch_node()
04890          {
04891             for (std::size_t i = 0; i < arg_list_.size(); ++i)
04892             {
04893                if (arg_list_[i] && delete_branch_[i])
04894                {
04895                   delete arg_list_[i];
04896                   arg_list_[i] = 0;
04897                }
04898             }
04899          }
04900 
04901          inline T value() const
04902          {
04903             T result = T(0);
04904             if (!arg_list_.empty())
04905             {
04906                if (0 != (arg_list_.size() & 1))
04907                {
04908                   return std::numeric_limits<T>::quiet_NaN();
04909                }
04910 
04911                for (std::size_t i = 0; i < arg_list_.size() / 2; ++i)
04912                {
04913                   expression_ptr condition  = arg_list_[(2 * i)    ];
04914                   expression_ptr consequent = arg_list_[(2 * i) + 1];
04915 
04916                   if (is_true(condition))
04917                   {
04918                      result = consequent->value();
04919                   }
04920                }
04921             }
04922 
04923             return result;
04924          }
04925 
04926          inline typename expression_node<T>::node_type type() const
04927          {
04928             return expression_node<T>::e_mswitch;
04929          }
04930 
04931       private:
04932 
04933          std::vector<expression_ptr> arg_list_;
04934          std::vector<unsigned char> delete_branch_;
04935       };
04936 
04937       template <typename T>
04938       class variable_node : public expression_node<T>
04939       {
04940       public:
04941 
04942          static T null_value;
04943 
04944          explicit variable_node()
04945          : value_(&null_value)
04946          {}
04947 
04948          explicit variable_node(T& value)
04949          : value_(&value)
04950          {}
04951 
04952          inline bool operator <(const variable_node<T>& v) const
04953          {
04954             return this < (&v);
04955          }
04956 
04957          inline T value() const
04958          {
04959             return (*value_);
04960          }
04961 
04962          inline T& ref()
04963          {
04964             return (*value_);
04965          }
04966 
04967          inline const T& ref() const
04968          {
04969             return (*value_);
04970          }
04971 
04972          inline typename expression_node<T>::node_type type() const
04973          {
04974             return expression_node<T>::e_variable;
04975          }
04976 
04977       private:
04978 
04979          T* value_;
04980       };
04981 
04982       template <typename T>
04983       class vector_node : public expression_node<T>
04984       {
04985       public:
04986 
04987          typedef expression_node<T>* expression_ptr;
04988 
04989          vector_node(expression_ptr index, T* vector_base)
04990          : index_(index),
04991            vector_base_(vector_base)
04992          {}
04993 
04994         ~vector_node()
04995          {
04996             if (index_ && !details::is_variable_node(index_))
04997             {
04998                delete index_;
04999             }
05000          }
05001 
05002          inline T value() const
05003          {
05004            return *(vector_base_ + static_cast<std::size_t>(index_->value()));
05005          }
05006 
05007          inline T& ref()
05008          {
05009             return *(vector_base_ + static_cast<std::size_t>(index_->value()));
05010          }
05011 
05012          inline const T& ref() const
05013          {
05014             return *(vector_base_ + static_cast<std::size_t>(index_->value()));
05015          }
05016 
05017          inline typename expression_node<T>::node_type type() const
05018          {
05019             return expression_node<T>::e_vecelem;
05020          }
05021 
05022       private:
05023 
05024          expression_ptr index_;
05025          T* vector_base_;
05026       };
05027 
05028       template <typename T>
05029       T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
05030 
05031       #ifndef exprtk_disable_string_capabilities
05032       template <typename T>
05033       class stringvar_node : public string_base_node<T>
05034       {
05035       public:
05036 
05037          static std::string null_value;
05038 
05039          explicit stringvar_node()
05040          : value_(&null_value)
05041          {}
05042 
05043          explicit stringvar_node(std::string& value)
05044          : value_(&value)
05045          {}
05046 
05047          inline bool operator <(const stringvar_node<T>& v) const
05048          {
05049             return this < (&v);
05050          }
05051 
05052          inline T value() const
05053          {
05054             return std::numeric_limits<T>::quiet_NaN();
05055          }
05056 
05057          inline std::string str() const
05058          {
05059             return (*value_);
05060          }
05061 
05062          inline virtual std::string& ref()
05063          {
05064             return (*value_);
05065          }
05066 
05067          inline virtual const std::string& ref() const
05068          {
05069             return (*value_);
05070          }
05071 
05072          inline typename expression_node<T>::node_type type() const
05073          {
05074             return expression_node<T>::e_stringvar;
05075          }
05076 
05077       private:
05078 
05079          std::string* value_;
05080       };
05081 
05082       template <typename T>
05083       std::string stringvar_node<T>::null_value = std::string("");
05084 
05085       template <typename T, typename RangePack>
05086       class string_range_node : public string_base_node<T>
05087       {
05088       public:
05089 
05090          static std::string null_value;
05091 
05092          explicit string_range_node(std::string& value, RangePack rp)
05093          : value_(&value),
05094            rp_(rp)
05095          {}
05096 
05097         ~string_range_node()
05098          {
05099             rp_.free();
05100          }
05101 
05102          inline bool operator <(const string_range_node<T,RangePack>& v) const
05103          {
05104             return this < (&v);
05105          }
05106 
05107          inline T value() const
05108          {
05109             return std::numeric_limits<T>::quiet_NaN();
05110          }
05111 
05112          inline std::string str() const
05113          {
05114             return (*value_);
05115          }
05116 
05117          inline RangePack range() const
05118          {
05119             return rp_;
05120          }
05121 
05122          inline virtual std::string& ref()
05123          {
05124             return (*value_);
05125          }
05126 
05127          inline virtual const std::string& ref() const
05128          {
05129             return (*value_);
05130          }
05131 
05132          inline virtual RangePack& range_ref()
05133          {
05134             return rp_;
05135          }
05136 
05137          inline virtual const RangePack& range_ref() const
05138          {
05139             return rp_;
05140          }
05141 
05142          inline typename expression_node<T>::node_type type() const
05143          {
05144             return expression_node<T>::e_stringvarrng;
05145          }
05146 
05147       private:
05148 
05149          std::string* value_;
05150          RangePack    rp_;
05151       };
05152 
05153       template <typename T, typename RangePack>
05154       std::string string_range_node<T,RangePack>::null_value = std::string("");
05155 
05156       template <typename T, typename RangePack>
05157       class const_string_range_node : public string_base_node<T>
05158       {
05159       public:
05160 
05161          explicit const_string_range_node(const std::string& value, RangePack rp)
05162          : value_(value),
05163            rp_(rp)
05164          {}
05165 
05166         ~const_string_range_node()
05167          {
05168             rp_.free();
05169          }
05170 
05171          inline T value() const
05172          {
05173             return std::numeric_limits<T>::quiet_NaN();
05174          }
05175 
05176          inline std::string str() const
05177          {
05178             return value_;
05179          }
05180 
05181          inline RangePack range() const
05182          {
05183             return rp_;
05184          }
05185 
05186          inline virtual RangePack& range_ref()
05187          {
05188             return rp_;
05189          }
05190 
05191          inline virtual const RangePack& range_ref() const
05192          {
05193             return rp_;
05194          }
05195 
05196          inline typename expression_node<T>::node_type type() const
05197          {
05198             return expression_node<T>::e_cstringvarrng;
05199          }
05200 
05201       private:
05202 
05203          const_string_range_node<T,RangePack>& operator=(const const_string_range_node<T,RangePack>&);
05204 
05205          const std::string value_;
05206          RangePack    rp_;
05207       };
05208       #endif
05209 
05210       template <typename T, std::size_t N> inline T axn(T a, T x)       { return a * exprtk::details::numeric::fast_exp<T,N>::result(x); } // a*x^n
05211       template <typename T, std::size_t N> inline T axnb(T a, T x, T b) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; } // a*x^n+b
05212 
05213       template<typename T>
05214       struct sf_base
05215       {
05216          typedef typename details::functor_t<T>::Type Type;
05217          typedef typename details::functor_t<T> functor_t;
05218          typedef typename functor_t::qfunc_t quaternary_functor_t;
05219          typedef typename functor_t::tfunc_t trinary_functor_t;
05220          typedef typename functor_t::bfunc_t binary_functor_t;
05221          typedef typename functor_t::ufunc_t unary_functor_t;
05222       };
05223 
05224       template <typename T> struct sf00_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) / z; } static inline std::string id() { return "(t+t)/t";} };
05225       template <typename T> struct sf01_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) * z; } static inline std::string id() { return "(t+t)*t";} };
05226       template <typename T> struct sf02_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) - z; } static inline std::string id() { return "(t+t)-t";} };
05227       template <typename T> struct sf03_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) + z; } static inline std::string id() { return "(t+t)+t";} };
05228       template <typename T> struct sf04_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) + z; } static inline std::string id() { return "(t-t)+t";} };
05229       template <typename T> struct sf05_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) / z; } static inline std::string id() { return "(t-t)/t";} };
05230       template <typename T> struct sf06_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) * z; } static inline std::string id() { return "(t-t)*t";} };
05231       template <typename T> struct sf07_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) + z; } static inline std::string id() { return "(t*t)+t";} };
05232       template <typename T> struct sf08_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) - z; } static inline std::string id() { return "(t*t)-t";} };
05233       template <typename T> struct sf09_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) / z; } static inline std::string id() { return "(t*t)/t";} };
05234       template <typename T> struct sf10_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) * z; } static inline std::string id() { return "(t*t)*t";} };
05235       template <typename T> struct sf11_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) + z; } static inline std::string id() { return "(t/t)+t";} };
05236       template <typename T> struct sf12_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) - z; } static inline std::string id() { return "(t/t)-t";} };
05237       template <typename T> struct sf13_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) / z; } static inline std::string id() { return "(t/t)/t";} };
05238       template <typename T> struct sf14_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) * z; } static inline std::string id() { return "(t/t)*t";} };
05239       template <typename T> struct sf15_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y + z); } static inline std::string id() { return "t/(t+t)";} };
05240       template <typename T> struct sf16_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y - z); } static inline std::string id() { return "t/(t-t)";} };
05241       template <typename T> struct sf17_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y * z); } static inline std::string id() { return "t/(t*t)";} };
05242       template <typename T> struct sf18_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y / z); } static inline std::string id() { return "t/(t/t)";} };
05243       template <typename T> struct sf19_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y + z); } static inline std::string id() { return "t*(t+t)";} };
05244       template <typename T> struct sf20_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y - z); } static inline std::string id() { return "t*(t-t)";} };
05245       template <typename T> struct sf21_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y * z); } static inline std::string id() { return "t*(t*t)";} };
05246       template <typename T> struct sf22_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y / z); } static inline std::string id() { return "t*(t/t)";} };
05247       template <typename T> struct sf23_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y + z); } static inline std::string id() { return "t-(t+t)";} };
05248       template <typename T> struct sf24_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y - z); } static inline std::string id() { return "t-(t-t)";} };
05249       template <typename T> struct sf25_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y / z); } static inline std::string id() { return "t-(t/t)";} };
05250       template <typename T> struct sf26_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y * z); } static inline std::string id() { return "t-(t*t)";} };
05251       template <typename T> struct sf27_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y * z); } static inline std::string id() { return "t+(t*t)";} };
05252       template <typename T> struct sf28_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y / z); } static inline std::string id() { return "t+(t/t)";} };
05253       template <typename T> struct sf29_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y + z); } static inline std::string id() { return "t+(t+t)";} };
05254       template <typename T> struct sf30_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y - z); } static inline std::string id() { return "t+(t-t)";} };
05255       template <typename T> struct sf31_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,2>(x,y,z); } }; //x * y^2 + z
05256       template <typename T> struct sf32_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,3>(x,y,z); } }; //x * y^3 + z
05257       template <typename T> struct sf33_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,4>(x,y,z); } }; //x * y^4 + z
05258       template <typename T> struct sf34_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,5>(x,y,z); } }; //x * y^5 + z
05259       template <typename T> struct sf35_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,6>(x,y,z); } }; //x * y^6 + z
05260       template <typename T> struct sf36_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,7>(x,y,z); } }; //x * y^7 + z
05261       template <typename T> struct sf37_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,8>(x,y,z); } }; //x * y^8 + z
05262       template <typename T> struct sf38_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,9>(x,y,z); } }; //x * y^9 + z
05263       template <typename T> struct sf39_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log(y)   + z; } };
05264       template <typename T> struct sf40_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log(y)   - z; } };
05265       template <typename T> struct sf41_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log10(y) + z; } };
05266       template <typename T> struct sf42_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log10(y) - z; } };
05267       template <typename T> struct sf43_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::sin(y) + z; } };
05268       template <typename T> struct sf44_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::sin(y) - z; } };
05269       template <typename T> struct sf45_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::cos(y) + z; } };
05270       template <typename T> struct sf46_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::cos(y) - z; } };
05271       template <typename T> struct sf47_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return is_true(x) ? y : z;      } };
05272       template <typename T> struct sf48_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y + z) / w); } static inline std::string id() { return "t+((t+t)/t)";} };
05273       template <typename T> struct sf49_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y + z) * w); } static inline std::string id() { return "t+((t+t)*t)";} };
05274       template <typename T> struct sf50_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y - z) / w); } static inline std::string id() { return "t+((t-t)/t)";} };
05275       template <typename T> struct sf51_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y - z) * w); } static inline std::string id() { return "t+((t-t)*t)";} };
05276       template <typename T> struct sf52_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y * z) / w); } static inline std::string id() { return "t+((t*t)/t)";} };
05277       template <typename T> struct sf53_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y * z) * w); } static inline std::string id() { return "t+((t*t)*t)";} };
05278       template <typename T> struct sf54_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) + w); } static inline std::string id() { return "t+((t/t)+t)";} };
05279       template <typename T> struct sf55_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) / w); } static inline std::string id() { return "t+((t/t)/t)";} };
05280       template <typename T> struct sf56_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) * w); } static inline std::string id() { return "t+((t/t)*t)";} };
05281       template <typename T> struct sf57_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y + z) / w); } static inline std::string id() { return "t-((t+t)/t)";} };
05282       template <typename T> struct sf58_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y + z) * w); } static inline std::string id() { return "t-((t+t)*t)";} };
05283       template <typename T> struct sf59_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y - z) / w); } static inline std::string id() { return "t-((t-t)/t)";} };
05284       template <typename T> struct sf60_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y - z) * w); } static inline std::string id() { return "t-((t-t)*t)";} };
05285       template <typename T> struct sf61_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y * z) / w); } static inline std::string id() { return "t-((t*t)/t)";} };
05286       template <typename T> struct sf62_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y * z) * w); } static inline std::string id() { return "t-((t*t)*t)";} };
05287       template <typename T> struct sf63_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y / z) / w); } static inline std::string id() { return "t-((t/t)/t)";} };
05288       template <typename T> struct sf64_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y / z) * w); } static inline std::string id() { return "t-((t/t)*t)";} };
05289       template <typename T> struct sf65_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x + y) * z) - w; } static inline std::string id() { return "((t+t)*t)-t";} };
05290       template <typename T> struct sf66_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x - y) * z) - w; } static inline std::string id() { return "((t-t)*t)-t";} };
05291       template <typename T> struct sf67_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x * y) * z) - w; } static inline std::string id() { return "((t*t)*t)-t";} };
05292       template <typename T> struct sf68_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x / y) * z) - w; } static inline std::string id() { return "((t/t)*t)-t";} };
05293       template <typename T> struct sf69_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x + y) / z) - w; } static inline std::string id() { return "((t+t)/t)-t";} };
05294       template <typename T> struct sf70_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x - y) / z) - w; } static inline std::string id() { return "((t-t)/t)-t";} };
05295       template <typename T> struct sf71_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x * y) / z) - w; } static inline std::string id() { return "((t*t)/t)-t";} };
05296       template <typename T> struct sf72_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x / y) / z) - w; } static inline std::string id() { return "((t/t)/t)-t";} };
05297       template <typename T> struct sf73_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z * w); } static inline std::string id() { return "(t*t)+(t*t)";} };
05298       template <typename T> struct sf74_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z * w); } static inline std::string id() { return "(t*t)-(t*t)";} };
05299       template <typename T> struct sf75_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z / w); } static inline std::string id() { return "(t*t)+(t/t)";} };
05300       template <typename T> struct sf76_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z / w); } static inline std::string id() { return "(t*t)-(t/t)";} };
05301       template <typename T> struct sf77_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z / w); } static inline std::string id() { return "(t/t)+(t/t)";} };
05302       template <typename T> struct sf78_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z / w); } static inline std::string id() { return "(t/t)-(t/t)";} };
05303       template <typename T> struct sf79_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z * w); } static inline std::string id() { return "(t/t)-(t*t)";} };
05304       template <typename T> struct sf80_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x / (y + (z * w)); } static inline std::string id() { return "t/(t+(t*t))";} };
05305       template <typename T> struct sf81_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x / (y - (z * w)); } static inline std::string id() { return "t/(t-(t*t))";} };
05306       template <typename T> struct sf82_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * (y + (z * w)); } static inline std::string id() { return "t*(t+(t*t))";} };
05307       template <typename T> struct sf83_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * (y - (z * w)); } static inline std::string id() { return "t*(t-(t*t))";} };
05308       template <typename T> struct sf84_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,2>(x,y) + axn<T,2>(z,w); } }; //x*y^2+z*w^2
05309       template <typename T> struct sf85_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,3>(x,y) + axn<T,3>(z,w); } }; //x*y^3+z*w^3
05310       template <typename T> struct sf86_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,4>(x,y) + axn<T,4>(z,w); } }; //x*y^4+z*w^4
05311       template <typename T> struct sf87_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,5>(x,y) + axn<T,5>(z,w); } }; //x*y^5+z*w^5
05312       template <typename T> struct sf88_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,6>(x,y) + axn<T,6>(z,w); } }; //x*y^6+z*w^6
05313       template <typename T> struct sf89_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,7>(x,y) + axn<T,7>(z,w); } }; //x*y^7+z*w^7
05314       template <typename T> struct sf90_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,8>(x,y) + axn<T,8>(z,w); } }; //x*y^8+z*w^8
05315       template <typename T> struct sf91_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,9>(x,y) + axn<T,9>(z,w); } }; //x*y^9+z*w^9
05316       template <typename T> struct sf92_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (is_true(x) && is_true(y)) ? z : w; } };
05317       template <typename T> struct sf93_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (is_true(x) || is_true(y)) ? z : w; } };
05318       template <typename T> struct sf94_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x <  y) ? z : w; } };
05319       template <typename T> struct sf95_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x <= y) ? z : w; } };
05320       template <typename T> struct sf96_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x >  y) ? z : w; } };
05321       template <typename T> struct sf97_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x >= y) ? z : w; } };
05322       template <typename T> struct sf98_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return numeric::equal(x,y) ? z : w; } };
05323       template <typename T> struct sf99_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * numeric::sin(y) + z * numeric::cos(w); } };
05324 
05325       template <typename T> struct sfext00_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z * w); } static inline std::string id() { return "(t+t)-(t*t)";} };
05326       template <typename T> struct sfext01_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z / w); } static inline std::string id() { return "(t+t)-(t/t)";} };
05327       template <typename T> struct sfext02_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z * w); } static inline std::string id() { return "(t+t)+(t*t)";} };
05328       template <typename T> struct sfext03_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z / w); } static inline std::string id() { return "(t+t)+(t/t)";} };
05329       template <typename T> struct sfext04_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z * w); } static inline std::string id() { return "(t-t)+(t*t)";} };
05330       template <typename T> struct sfext05_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z / w); } static inline std::string id() { return "(t-t)+(t/t)";} };
05331       template <typename T> struct sfext06_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z * w); } static inline std::string id() { return "(t-t)-(t*t)";} };
05332       template <typename T> struct sfext07_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z / w); } static inline std::string id() { return "(t-t)-(t/t)";} };
05333       template <typename T> struct sfext08_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z - w); } static inline std::string id() { return "(t+t)-(t-t)";} };
05334       template <typename T> struct sfext09_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z - w); } static inline std::string id() { return "(t+t)+(t-t)";} };
05335       template <typename T> struct sfext10_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z - w); } static inline std::string id() { return "(t+t)*(t-t)";} };
05336       template <typename T> struct sfext11_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z - w); } static inline std::string id() { return "(t+t)/(t-t)";} };
05337       template <typename T> struct sfext12_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z + w); } static inline std::string id() { return "(t-t)-(t+t)";} };
05338       template <typename T> struct sfext13_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z + w); } static inline std::string id() { return "(t-t)+(t+t)";} };
05339       template <typename T> struct sfext14_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z + w); } static inline std::string id() { return "(t-t)*(t+t)";} };
05340       template <typename T> struct sfext15_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z + w); } static inline std::string id() { return "(t-t)/(t+t)";} };
05341       template <typename T> struct sfext16_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z + w); } static inline std::string id() { return "(t*t)-(t+t)";} };
05342       template <typename T> struct sfext17_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z + w); } static inline std::string id() { return "(t/t)-(t+t)";} };
05343       template <typename T> struct sfext18_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z + w); } static inline std::string id() { return "(t*t)+(t+t)";} };
05344       template <typename T> struct sfext19_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z + w); } static inline std::string id() { return "(t/t)+(t+t)";} };
05345       template <typename T> struct sfext20_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z - w); } static inline std::string id() { return "(t*t)+(t-t)";} };
05346       template <typename T> struct sfext21_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z - w); } static inline std::string id() { return "(t/t)+(t-t)";} };
05347       template <typename T> struct sfext22_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z - w); } static inline std::string id() { return "(t*t)-(t-t)";} };
05348       template <typename T> struct sfext23_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z - w); } static inline std::string id() { return "(t/t)-(t-t)";} };
05349       template <typename T> struct sfext24_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z * w); } static inline std::string id() { return "(t+t)*(t*t)";} };
05350       template <typename T> struct sfext25_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z / w); } static inline std::string id() { return "(t+t)*(t/t)";} };
05351       template <typename T> struct sfext26_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z * w); } static inline std::string id() { return "(t+t)/(t*t)";} };
05352       template <typename T> struct sfext27_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z / w); } static inline std::string id() { return "(t+t)/(t/t)";} };
05353       template <typename T> struct sfext28_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z * w); } static inline std::string id() { return "(t-t)/(t*t)";} };
05354       template <typename T> struct sfext29_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z / w); } static inline std::string id() { return "(t-t)/(t/t)";} };
05355       template <typename T> struct sfext30_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z * w); } static inline std::string id() { return "(t-t)*(t*t)";} };
05356       template <typename T> struct sfext31_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z / w); } static inline std::string id() { return "(t-t)*(t/t)";} };
05357       template <typename T> struct sfext32_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z + w); } static inline std::string id() { return "(t*t)*(t+t)";} };
05358       template <typename T> struct sfext33_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) * (z + w); } static inline std::string id() { return "(t/t)*(t+t)";} };
05359       template <typename T> struct sfext34_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z + w); } static inline std::string id() { return "(t*t)/(t+t)";} };
05360       template <typename T> struct sfext35_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) / (z + w); } static inline std::string id() { return "(t/t)/(t+t)";} };
05361       template <typename T> struct sfext36_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z - w); } static inline std::string id() { return "(t*t)/(t-t)";} };
05362       template <typename T> struct sfext37_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) / (z - w); } static inline std::string id() { return "(t/t)/(t-t)";} };
05363       template <typename T> struct sfext38_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z - w); } static inline std::string id() { return "(t*t)*(t-t)";} };
05364       template <typename T> struct sfext39_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z * w); } static inline std::string id() { return "(t*t)/(t*t)";} };
05365       template <typename T> struct sfext40_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) * (z - w); } static inline std::string id() { return "(t/t)*(t-t)";} };
05366       template <typename T> struct sfext41_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z * w); } static inline std::string id() { return "(t*t)*(t*t)";} };
05367       template <typename T> struct sfext42_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + (y * (z / w)); } static inline std::string id() { return "t+(t*(t/t))";} };
05368       template <typename T> struct sfext43_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - (y * (z / w)); } static inline std::string id() { return "t-(t*(t/t))";} };
05369       template <typename T> struct sfext44_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + (y / (z * w)); } static inline std::string id() { return "t+(t/(t*t))";} };
05370       template <typename T> struct sfext45_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - (y / (z * w)); } static inline std::string id() { return "t-(t/(t*t))";} };
05371 
05372       template <typename T, typename SpecialFunction>
05373       class sf3_node : public trinary_node<T>
05374       {
05375       public:
05376 
05377          typedef expression_node<T>* expression_ptr;
05378 
05379          sf3_node(const operator_type& operation,
05380                   expression_ptr branch0,
05381                   expression_ptr branch1,
05382                   expression_ptr branch2)
05383          : trinary_node<T>(operation,branch0,branch1,branch2)
05384          {}
05385 
05386          inline T value() const
05387          {
05388             const T x = trinary_node<T>::branch_[0].first->value();
05389             const T y = trinary_node<T>::branch_[1].first->value();
05390             const T z = trinary_node<T>::branch_[2].first->value();
05391             return SpecialFunction::process(x,y,z);
05392          }
05393       };
05394 
05395       template <typename T, typename SpecialFunction>
05396       class sf4_node : public quaternary_node<T>
05397       {
05398       public:
05399 
05400          typedef expression_node<T>* expression_ptr;
05401 
05402          sf4_node(const operator_type& operation,
05403                   expression_ptr branch0,
05404                   expression_ptr branch1,
05405                   expression_ptr branch2,
05406                   expression_ptr branch3)
05407          : quaternary_node<T>(operation,branch0,branch1,branch2,branch3)
05408          {}
05409 
05410          inline T value() const
05411          {
05412             const T x = quaternary_node<T>::branch_[0].first->value();
05413             const T y = quaternary_node<T>::branch_[1].first->value();
05414             const T z = quaternary_node<T>::branch_[2].first->value();
05415             const T w = quaternary_node<T>::branch_[3].first->value();
05416             return SpecialFunction::process(x,y,z,w);
05417          }
05418       };
05419 
05420       template <typename T, typename SpecialFunction>
05421       class sf3_var_node : public expression_node<T>
05422       {
05423       public:
05424 
05425          typedef expression_node<T>* expression_ptr;
05426 
05427          sf3_var_node(const T& v0, const T& v1, const T& v2)
05428          : v0_(v0),
05429            v1_(v1),
05430            v2_(v2)
05431          {}
05432 
05433          inline T value() const
05434          {
05435             return SpecialFunction::process(v0_,v1_,v2_);
05436          }
05437 
05438          inline typename expression_node<T>::node_type type() const
05439          {
05440             return expression_node<T>::e_trinary;
05441          }
05442 
05443       private:
05444 
05445          sf3_var_node(sf3_var_node<T,SpecialFunction>&);
05446          sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
05447 
05448          const T& v0_;
05449          const T& v1_;
05450          const T& v2_;
05451       };
05452 
05453       template <typename T, typename SpecialFunction>
05454       class sf4_var_node : public expression_node<T>
05455       {
05456       public:
05457 
05458          typedef expression_node<T>* expression_ptr;
05459 
05460          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
05461          : v0_(v0),
05462            v1_(v1),
05463            v2_(v2),
05464            v3_(v3)
05465          {}
05466 
05467          inline T value() const
05468          {
05469             return SpecialFunction::process(v0_,v1_,v2_,v3_);
05470          }
05471 
05472          inline typename expression_node<T>::node_type type() const
05473          {
05474             return expression_node<T>::e_trinary;
05475          }
05476 
05477       private:
05478 
05479          sf4_var_node(sf4_var_node<T,SpecialFunction>&);
05480          sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
05481 
05482          const T& v0_;
05483          const T& v1_;
05484          const T& v2_;
05485          const T& v3_;
05486       };
05487 
05488       template <typename T, typename VarArgFunction>
05489       class vararg_node : public expression_node<T>
05490       {
05491       public:
05492 
05493          typedef expression_node<T>* expression_ptr;
05494 
05495          template <typename Allocator,
05496                    template <typename,typename> class Sequence>
05497          vararg_node(const Sequence<expression_ptr,Allocator>& arglist)
05498          {
05499             arg_list_.resize(arglist.size());
05500             delete_branch_.resize(arglist.size());
05501             for (std::size_t i = 0; i < arglist.size(); ++i)
05502             {
05503                if (arglist[i])
05504                {
05505                        arg_list_[i] = arglist[i];
05506                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
05507                }
05508                else
05509                {
05510                   arg_list_.clear();
05511                   delete_branch_.clear();
05512                   return;
05513                }
05514             }
05515          }
05516 
05517         ~vararg_node()
05518          {
05519             for (std::size_t i = 0; i < arg_list_.size(); ++i)
05520             {
05521                if (arg_list_[i] && delete_branch_[i])
05522                {
05523                   delete arg_list_[i];
05524                   arg_list_[i] = 0;
05525                }
05526             }
05527          }
05528 
05529          inline T value() const
05530          {
05531             if (!arg_list_.empty())
05532                return VarArgFunction::process(arg_list_);
05533             else
05534                return std::numeric_limits<T>::quiet_NaN();
05535          }
05536 
05537          inline typename expression_node<T>::node_type type() const
05538          {
05539             return expression_node<T>::e_vararg;
05540          }
05541 
05542       private:
05543 
05544          std::vector<expression_ptr> arg_list_;
05545          std::vector<unsigned char> delete_branch_;
05546       };
05547 
05548       template <typename T, typename VarArgFunction>
05549       class vararg_varnode : public expression_node<T>
05550       {
05551       public:
05552 
05553          typedef expression_node<T>* expression_ptr;
05554 
05555          template <typename Allocator,
05556                    template <typename,typename> class Sequence>
05557          vararg_varnode(const Sequence<expression_ptr,Allocator>& arglist)
05558          {
05559             arg_list_.resize(arglist.size());
05560             for (std::size_t i = 0; i < arglist.size(); ++i)
05561             {
05562                if (arglist[i] && is_variable_node(arglist[i]))
05563                {
05564                   variable_node<T>* var_node_ptr = dynamic_cast<variable_node<T>*>(arglist[i]);
05565                   arg_list_[i] = (&var_node_ptr->ref());
05566                }
05567                else
05568                {
05569                   arg_list_.clear();
05570                   return;
05571                }
05572             }
05573          }
05574 
05575          inline T value() const
05576          {
05577             if (!arg_list_.empty())
05578                return VarArgFunction::process(arg_list_);
05579             else
05580                return std::numeric_limits<T>::quiet_NaN();
05581          }
05582 
05583          inline typename expression_node<T>::node_type type() const
05584          {
05585             return expression_node<T>::e_vararg;
05586          }
05587 
05588       private:
05589 
05590          std::vector<const T*> arg_list_;
05591       };
05592 
05593       template <typename T>
05594       class assignment_node : public binary_node<T>
05595       {
05596       public:
05597 
05598          typedef expression_node<T>* expression_ptr;
05599 
05600          assignment_node(const operator_type& operation,
05601                          expression_ptr branch0,
05602                          expression_ptr branch1)
05603          : binary_node<T>(operation,branch0,branch1),
05604            var_node_ptr_(0)
05605          {
05606             if (is_variable_node(binary_node<T>::branch_[0].first))
05607             {
05608                var_node_ptr_ = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
05609             }
05610          }
05611 
05612          inline T value() const
05613          {
05614             if (var_node_ptr_)
05615             {
05616                T& result = var_node_ptr_->ref();
05617                result = binary_node<T>::branch_[1].first->value();
05618                return result;
05619             }
05620             else
05621                return std::numeric_limits<T>::quiet_NaN();
05622          }
05623 
05624       private:
05625 
05626          variable_node<T>* var_node_ptr_;
05627       };
05628 
05629       template <typename T>
05630       class assignment_vec_node : public binary_node<T>
05631       {
05632       public:
05633 
05634          typedef expression_node<T>* expression_ptr;
05635 
05636          assignment_vec_node(const operator_type& operation,
05637                              expression_ptr branch0,
05638                              expression_ptr branch1)
05639          : binary_node<T>(operation,branch0,branch1),
05640            vec_node_ptr_(0)
05641          {
05642             if (is_vector_node(binary_node<T>::branch_[0].first))
05643             {
05644                vec_node_ptr_ = dynamic_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
05645             }
05646          }
05647 
05648          inline T value() const
05649          {
05650             if (vec_node_ptr_)
05651             {
05652                T& result = vec_node_ptr_->ref();
05653                result = binary_node<T>::branch_[1].first->value();
05654                return result;
05655             }
05656             else
05657                return std::numeric_limits<T>::quiet_NaN();
05658          }
05659 
05660       private:
05661 
05662          vector_node<T>* vec_node_ptr_;
05663       };
05664 
05665       template <typename T, typename Operation>
05666       class assignment_op_node : public binary_node<T>
05667       {
05668       public:
05669 
05670          typedef expression_node<T>* expression_ptr;
05671 
05672          assignment_op_node(const operator_type& operation,
05673                             expression_ptr branch0,
05674                             expression_ptr branch1)
05675          : binary_node<T>(operation,branch0,branch1),
05676            var_node_ptr_(0)
05677          {
05678             if (is_variable_node(binary_node<T>::branch_[0].first))
05679             {
05680                var_node_ptr_ = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
05681             }
05682          }
05683 
05684          inline T value() const
05685          {
05686             if (var_node_ptr_)
05687             {
05688                T& v = var_node_ptr_->ref();
05689                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
05690                return v;
05691             }
05692             else
05693                return std::numeric_limits<T>::quiet_NaN();
05694          }
05695 
05696       private:
05697 
05698          variable_node<T>* var_node_ptr_;
05699       };
05700 
05701       template <typename T, typename Operation>
05702       class assignment_vec_op_node : public binary_node<T>
05703       {
05704       public:
05705 
05706          typedef expression_node<T>* expression_ptr;
05707 
05708          assignment_vec_op_node(const operator_type& operation,
05709                                 expression_ptr branch0,
05710                                 expression_ptr branch1)
05711          : binary_node<T>(operation,branch0,branch1),
05712            vec_node_ptr_(0)
05713          {
05714             if (is_vector_node(binary_node<T>::branch_[0].first))
05715             {
05716                vec_node_ptr_ = dynamic_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
05717             }
05718          }
05719 
05720          inline T value() const
05721          {
05722             if (vec_node_ptr_)
05723             {
05724                T& v = vec_node_ptr_->ref();
05725                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
05726                return v;
05727             }
05728             else
05729                return std::numeric_limits<T>::quiet_NaN();
05730          }
05731 
05732       private:
05733 
05734          vector_node<T>* vec_node_ptr_;
05735       };
05736 
05737       template <typename T>
05738       class scand_node : public binary_node<T>
05739       {
05740       public:
05741 
05742          typedef expression_node<T>* expression_ptr;
05743 
05744          scand_node(const operator_type& operation,
05745                     expression_ptr branch0,
05746                     expression_ptr branch1)
05747          : binary_node<T>(operation,branch0,branch1)
05748          {}
05749 
05750          inline T value() const
05751          {
05752             return (
05753                      (T(0) != binary_node<T>::branch_[0].first->value()) &&
05754                      (T(0) != binary_node<T>::branch_[1].first->value())
05755                    ) ? T(1) : T(0);
05756          }
05757       };
05758 
05759       template <typename T>
05760       class scor_node : public binary_node<T>
05761       {
05762       public:
05763 
05764          typedef expression_node<T>* expression_ptr;
05765 
05766          scor_node(const operator_type& operation,
05767                    expression_ptr branch0,
05768                    expression_ptr branch1)
05769          : binary_node<T>(operation,branch0,branch1)
05770          {}
05771 
05772          inline T value() const
05773          {
05774             return (
05775                      (T(0) != binary_node<T>::branch_[0].first->value()) ||
05776                      (T(0) != binary_node<T>::branch_[1].first->value())
05777                    ) ? T(1) : T(0);
05778          }
05779       };
05780 
05781       template <typename T, typename IFunction, std::size_t N>
05782       class function_N_node : public expression_node<T>
05783       {
05784       public:
05785 
05786          // Function of N paramters.
05787          typedef expression_node<T>* expression_ptr;
05788          typedef std::pair<expression_ptr,bool> branch_t;
05789          typedef IFunction ifunction;
05790 
05791          function_N_node(ifunction* func)
05792          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
05793            parameter_count_(func->param_count)
05794          {}
05795 
05796         ~function_N_node()
05797          {
05798             cleanup_branches<T,N>::execute(branch_);
05799          }
05800 
05801          template <std::size_t NumBranches>
05802          bool init_branches(expression_ptr (&b)[NumBranches])
05803          {
05804             // Needed for incompetent and broken msvc compiler versions
05805             #ifdef _MSC_VER
05806              #pragma warning(push)
05807              #pragma warning(disable: 4127)
05808             #endif
05809             if (N != NumBranches)
05810                return false;
05811             else
05812             {
05813                for (std::size_t i = 0; i < NumBranches; ++i)
05814                {
05815                   if (b[i])
05816                      branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
05817                   else
05818                      return false;
05819                }
05820                return true;
05821             }
05822             #ifdef _MSC_VER
05823              #pragma warning(pop)
05824             #endif
05825          }
05826 
05827          inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
05828          {
05829             return this < (&fn);
05830          }
05831 
05832          inline T value() const
05833          {
05834             // Needed for incompetent and broken msvc compiler versions
05835             #ifdef _MSC_VER
05836              #pragma warning(push)
05837              #pragma warning(disable: 4127)
05838             #endif
05839             if ((0 == function_) || (0 == N))
05840                return std::numeric_limits<T>::quiet_NaN();
05841             else
05842             {
05843                T v[N];
05844                evaluate_branches<T,N>::execute(v,branch_);
05845                return invoke<T,N>::execute(*function_,v);
05846             }
05847             #ifdef _MSC_VER
05848              #pragma warning(pop)
05849             #endif
05850          }
05851 
05852          template <typename T_, std::size_t BranchCount>
05853          struct evaluate_branches
05854          {
05855             static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
05856             {
05857                for (std::size_t i = 0; i < BranchCount; ++i)
05858                {
05859                   v[i] = b[i].first->value();
05860                }
05861             }
05862          };
05863 
05864          template <typename T_>
05865          struct evaluate_branches <T_,5>
05866          {
05867             static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
05868             {
05869                v[0] = b[0].first->value();
05870                v[1] = b[1].first->value();
05871                v[2] = b[2].first->value();
05872                v[3] = b[3].first->value();
05873                v[4] = b[4].first->value();
05874             }
05875          };
05876 
05877          template <typename T_>
05878          struct evaluate_branches <T_,4>
05879          {
05880             static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
05881             {
05882                v[0] = b[0].first->value();
05883                v[1] = b[1].first->value();
05884                v[2] = b[2].first->value();
05885                v[3] = b[3].first->value();
05886             }
05887          };
05888 
05889          template <typename T_>
05890          struct evaluate_branches <T_,3>
05891          {
05892             static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
05893             {
05894                v[0] = b[0].first->value();
05895                v[1] = b[1].first->value();
05896                v[2] = b[2].first->value();
05897             }
05898          };
05899 
05900          template <typename T_>
05901          struct evaluate_branches <T_,2>
05902          {
05903             static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
05904             {
05905                v[0] = b[0].first->value();
05906                v[1] = b[1].first->value();
05907             }
05908          };
05909 
05910          template <typename T_>
05911          struct evaluate_branches <T_,1>
05912          {
05913             static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
05914             {
05915                v[0] = b[0].first->value();
05916             }
05917          };
05918 
05919          template <typename T_, std::size_t ParamCount>
05920          struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
05921 
05922          template <typename T_>
05923          struct invoke<T_,20>
05924          {
05925             static inline T_ execute(ifunction& f, T_ (&v)[20])
05926             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
05927          };
05928 
05929          template <typename T_>
05930          struct invoke<T_,19>
05931          {
05932             static inline T_ execute(ifunction& f, T_ (&v)[19])
05933             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
05934          };
05935 
05936          template <typename T_>
05937          struct invoke<T_,18>
05938          {
05939             static inline T_ execute(ifunction& f, T_ (&v)[18])
05940             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
05941          };
05942 
05943          template <typename T_>
05944          struct invoke<T_,17>
05945          {
05946             static inline T_ execute(ifunction& f, T_ (&v)[17])
05947             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
05948          };
05949 
05950          template <typename T_>
05951          struct invoke<T_,16>
05952          {
05953             static inline T_ execute(ifunction& f, T_ (&v)[16])
05954             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
05955          };
05956 
05957          template <typename T_>
05958          struct invoke<T_,15>
05959          {
05960             static inline T_ execute(ifunction& f, T_ (&v)[15])
05961             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
05962          };
05963 
05964          template <typename T_>
05965          struct invoke<T_,14>
05966          {
05967             static inline T_ execute(ifunction& f, T_ (&v)[14])
05968             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
05969          };
05970 
05971          template <typename T_>
05972          struct invoke<T_,13>
05973          {
05974             static inline T_ execute(ifunction& f, T_ (&v)[13])
05975             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
05976          };
05977 
05978          template <typename T_>
05979          struct invoke<T_,12>
05980          {
05981             static inline T_ execute(ifunction& f, T_ (&v)[12])
05982             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
05983          };
05984 
05985          template <typename T_>
05986          struct invoke<T_,11>
05987          {
05988             static inline T_ execute(ifunction& f, T_ (&v)[11])
05989             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
05990          };
05991 
05992          template <typename T_>
05993          struct invoke<T_,10>
05994          {
05995             static inline T_ execute(ifunction& f, T_ (&v)[10])
05996             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
05997          };
05998 
05999          template <typename T_>
06000          struct invoke<T_,9>
06001          {
06002             static inline T_ execute(ifunction& f, T_ (&v)[9])
06003             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
06004          };
06005 
06006          template <typename T_>
06007          struct invoke<T_,8>
06008          {
06009             static inline T_ execute(ifunction& f, T_ (&v)[8])
06010             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
06011          };
06012 
06013          template <typename T_>
06014          struct invoke<T_,7>
06015          {
06016             static inline T_ execute(ifunction& f, T_ (&v)[7])
06017             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
06018          };
06019 
06020          template <typename T_>
06021          struct invoke<T_,6>
06022          {
06023             static inline T_ execute(ifunction& f, T_ (&v)[6])
06024             { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
06025          };
06026 
06027          template <typename T_>
06028          struct invoke<T_,5>
06029          {
06030             static inline T_ execute(ifunction& f, T_ (&v)[5])
06031             { return f(v[0],v[1],v[2],v[3],v[4]); }
06032          };
06033 
06034          template <typename T_>
06035          struct invoke<T_,4>
06036          {
06037             static inline T_ execute(ifunction& f, T_ (&v)[4])
06038             { return f(v[0],v[1],v[2],v[3]); }
06039          };
06040 
06041          template <typename T_>
06042          struct invoke<T_,3>
06043          {
06044             static inline T_ execute(ifunction& f, T_ (&v)[3])
06045             { return f(v[0],v[1],v[2]); }
06046          };
06047 
06048          template <typename T_>
06049          struct invoke<T_,2>
06050          {
06051             static inline T_ execute(ifunction& f, T_ (&v)[2])
06052             { return f(v[0],v[1]); }
06053          };
06054 
06055          template <typename T_>
06056          struct invoke<T_,1>
06057          {
06058             static inline T_ execute(ifunction& f, T_ (&v)[1])
06059             { return f(v[0]); }
06060          };
06061 
06062          inline typename expression_node<T>::node_type type() const
06063          {
06064             return expression_node<T>::e_function;
06065          }
06066 
06067       private:
06068 
06069          ifunction* function_;
06070          std::size_t parameter_count_;
06071          branch_t branch_[N];
06072       };
06073 
06074       template <typename T, typename IFunction>
06075       class function_N_node<T,IFunction,0> : public expression_node<T>
06076       {
06077       public:
06078 
06079          typedef expression_node<T>* expression_ptr;
06080          typedef IFunction ifunction;
06081 
06082          function_N_node(ifunction* func)
06083          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
06084          {}
06085 
06086          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
06087          {
06088             return this < (&fn);
06089          }
06090 
06091          inline T value() const
06092          {
06093             if (function_)
06094                return (*function_)();
06095             else
06096                return std::numeric_limits<T>::quiet_NaN();
06097          }
06098 
06099          inline typename expression_node<T>::node_type type() const
06100          {
06101             return expression_node<T>::e_function;
06102          }
06103 
06104       private:
06105 
06106          ifunction* function_;
06107          std::size_t parameter_count_;
06108       };
06109 
06110       template <typename T, typename VarArgFunction>
06111       class vararg_function_node : public expression_node<T>
06112       {
06113       public:
06114 
06115          typedef expression_node<T>* expression_ptr;
06116 
06117          vararg_function_node(VarArgFunction*  func,
06118                               const std::vector<expression_ptr>& arg_list)
06119          : function_(func),
06120            arg_list_(arg_list)
06121          {
06122             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
06123          }
06124 
06125         ~vararg_function_node()
06126          {
06127             for (std::size_t i = 0; i < arg_list_.size(); ++i)
06128             {
06129                if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
06130                {
06131                   delete arg_list_[i];
06132                   arg_list_[i] = 0;
06133                }
06134             }
06135          }
06136 
06137          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
06138          {
06139             return this < (&fn);
06140          }
06141 
06142          inline T value() const
06143          {
06144             if (function_)
06145             {
06146                populate_value_list();
06147                return (*function_)(value_list_);
06148             }
06149             else
06150                return std::numeric_limits<T>::quiet_NaN();
06151          }
06152 
06153          inline typename expression_node<T>::node_type type() const
06154          {
06155             return expression_node<T>::e_vafunction;
06156          }
06157 
06158       private:
06159 
06160          inline void populate_value_list() const
06161          {
06162             for (std::size_t i = 0; i < arg_list_.size(); ++i)
06163             {
06164                value_list_[i] = arg_list_[i]->value();
06165             }
06166          }
06167 
06168          VarArgFunction* function_;
06169          std::vector<expression_ptr> arg_list_;
06170          mutable std::vector<T> value_list_;
06171       };
06172 
06173       #define exprtk_define_unary_op(OpName)                                                                    \
06174       template <typename T>                                                                                     \
06175       struct OpName##_op                                                                                        \
06176       {                                                                                                         \
06177          typedef typename functor_t<T>::Type Type;                                                              \
06178          static inline T process(Type v) { return numeric:: OpName (v); }                                       \
06179          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_##OpName; } \
06180          static inline details::operator_type operation() { return details::e_##OpName; }                       \
06181       };                                                                                                        \
06182 
06183       exprtk_define_unary_op(abs  )
06184       exprtk_define_unary_op(acos )
06185       exprtk_define_unary_op(acosh)
06186       exprtk_define_unary_op(asin )
06187       exprtk_define_unary_op(asinh)
06188       exprtk_define_unary_op(atan )
06189       exprtk_define_unary_op(atanh)
06190       exprtk_define_unary_op(ceil )
06191       exprtk_define_unary_op(cos  )
06192       exprtk_define_unary_op(cosh )
06193       exprtk_define_unary_op(cot  )
06194       exprtk_define_unary_op(csc  )
06195       exprtk_define_unary_op(d2g  )
06196       exprtk_define_unary_op(d2r  )
06197       exprtk_define_unary_op(erf  )
06198       exprtk_define_unary_op(erfc )
06199       exprtk_define_unary_op(exp  )
06200       exprtk_define_unary_op(expm1)
06201       exprtk_define_unary_op(floor)
06202       exprtk_define_unary_op(frac )
06203       exprtk_define_unary_op(g2d  )
06204       exprtk_define_unary_op(log  )
06205       exprtk_define_unary_op(log10)
06206       exprtk_define_unary_op(log2 )
06207       exprtk_define_unary_op(log1p)
06208       exprtk_define_unary_op(neg  )
06209       exprtk_define_unary_op(notl )
06210       exprtk_define_unary_op(pos  )
06211       exprtk_define_unary_op(r2d  )
06212       exprtk_define_unary_op(round)
06213       exprtk_define_unary_op(sec  )
06214       exprtk_define_unary_op(sgn  )
06215       exprtk_define_unary_op(sin  )
06216       exprtk_define_unary_op(sinc )
06217       exprtk_define_unary_op(sinh )
06218       exprtk_define_unary_op(sqrt )
06219       exprtk_define_unary_op(tan  )
06220       exprtk_define_unary_op(tanh )
06221       exprtk_define_unary_op(trunc)
06222       #undef exprtk_define_unary_op
06223 
06224       template<typename T>
06225       struct opr_base
06226       {
06227          typedef typename details::functor_t<T>::Type Type;
06228          typedef typename details::functor_t<T> functor_t;
06229          typedef typename functor_t::qfunc_t quaternary_functor_t;
06230          typedef typename functor_t::tfunc_t trinary_functor_t;
06231          typedef typename functor_t::bfunc_t binary_functor_t;
06232          typedef typename functor_t::ufunc_t unary_functor_t;
06233       };
06234 
06235       template <typename T>
06236       struct add_op : public opr_base<T>
06237       {
06238          typedef typename opr_base<T>::Type Type;
06239          static inline T process(Type t1, Type t2) { return t1 + t2; }
06240          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
06241          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
06242          static inline details::operator_type operation() { return details::e_add; }
06243       };
06244 
06245       template <typename T>
06246       struct mul_op : public opr_base<T>
06247       {
06248          typedef typename opr_base<T>::Type Type;
06249          static inline T process(Type t1, Type t2) { return t1 * t2; }
06250          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
06251          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
06252          static inline details::operator_type operation() { return details::e_mul; }
06253       };
06254 
06255       template <typename T>
06256       struct sub_op : public opr_base<T>
06257       {
06258          typedef typename opr_base<T>::Type Type;
06259          static inline T process(Type t1, Type t2) { return t1 - t2; }
06260          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
06261          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
06262          static inline details::operator_type operation() { return details::e_sub; }
06263       };
06264 
06265       template <typename T>
06266       struct div_op : public opr_base<T>
06267       {
06268          typedef typename opr_base<T>::Type Type;
06269          static inline T process(Type t1, Type t2) { return t1 / t2; }
06270          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
06271          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
06272          static inline details::operator_type operation() { return details::e_div; }
06273       };
06274 
06275       template <typename T>
06276       struct mod_op : public opr_base<T>
06277       {
06278          typedef typename opr_base<T>::Type Type;
06279          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
06280          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
06281          static inline details::operator_type operation() { return details::e_mod; }
06282       };
06283 
06284       template <typename T>
06285       struct pow_op : public opr_base<T>
06286       {
06287          typedef typename opr_base<T>::Type Type;
06288          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
06289          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
06290          static inline details::operator_type operation() { return details::e_pow; }
06291       };
06292 
06293       template <typename T>
06294       struct lt_op : public opr_base<T>
06295       {
06296          typedef typename opr_base<T>::Type Type;
06297          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
06298          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
06299          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
06300          static inline details::operator_type operation() { return details::e_lt; }
06301       };
06302 
06303       template <typename T>
06304       struct lte_op : public opr_base<T>
06305       {
06306          typedef typename opr_base<T>::Type Type;
06307          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
06308          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
06309          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
06310          static inline details::operator_type operation() { return details::e_lte; }
06311       };
06312 
06313       template <typename T>
06314       struct gt_op : public opr_base<T>
06315       {
06316          typedef typename opr_base<T>::Type Type;
06317          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
06318          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
06319          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
06320          static inline details::operator_type operation() { return details::e_gt; }
06321       };
06322 
06323       template <typename T>
06324       struct gte_op : public opr_base<T>
06325       {
06326          typedef typename opr_base<T>::Type Type;
06327          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
06328          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
06329          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
06330          static inline details::operator_type operation() { return details::e_gte; }
06331       };
06332 
06333       template <typename T>
06334       struct eq_op : public opr_base<T>
06335       {
06336          typedef typename opr_base<T>::Type Type;
06337          static inline T process(Type t1, Type t2) { return ((t1 == t2) ? T(1) : T(0)); }
06338          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
06339          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
06340          static inline details::operator_type operation() { return details::e_eq; }
06341       };
06342 
06343       template <typename T>
06344       struct ne_op : public opr_base<T>
06345       {
06346          typedef typename opr_base<T>::Type Type;
06347          static inline T process(Type t1, Type t2) { return ((t1 != t2) ? T(1) : T(0)); }
06348          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
06349          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
06350          static inline details::operator_type operation() { return details::e_ne; }
06351       };
06352 
06353       template <typename T>
06354       struct and_op : public opr_base<T>
06355       {
06356          typedef typename opr_base<T>::Type Type;
06357          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
06358          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
06359          static inline details::operator_type operation() { return details::e_and; }
06360       };
06361 
06362       template <typename T>
06363       struct nand_op : public opr_base<T>
06364       {
06365          typedef typename opr_base<T>::Type Type;
06366          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
06367          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
06368          static inline details::operator_type operation() { return details::e_nand; }
06369       };
06370 
06371       template <typename T>
06372       struct or_op : public opr_base<T>
06373       {
06374          typedef typename opr_base<T>::Type Type;
06375          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
06376          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
06377          static inline details::operator_type operation() { return details::e_or; }
06378       };
06379 
06380       template <typename T>
06381       struct nor_op : public opr_base<T>
06382       {
06383          typedef typename opr_base<T>::Type Type;
06384          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
06385          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
06386          static inline details::operator_type operation() { return details::e_nor; }
06387       };
06388 
06389       template <typename T>
06390       struct xor_op : public opr_base<T>
06391       {
06392          typedef typename opr_base<T>::Type Type;
06393          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
06394          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
06395          static inline details::operator_type operation() { return details::e_xor; }
06396       };
06397 
06398       template <typename T>
06399       struct xnor_op : public opr_base<T>
06400       {
06401          typedef typename opr_base<T>::Type Type;
06402          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
06403          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
06404          static inline details::operator_type operation() { return details::e_xnor; }
06405       };
06406 
06407       template <typename T>
06408       struct in_op : public opr_base<T>
06409       {
06410          typedef typename opr_base<T>::Type Type;
06411          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
06412          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
06413          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
06414          static inline details::operator_type operation() { return details::e_in; }
06415       };
06416 
06417       template <typename T>
06418       struct like_op : public opr_base<T>
06419       {
06420          typedef typename opr_base<T>::Type Type;
06421          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
06422          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
06423          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
06424          static inline details::operator_type operation() { return details::e_like; }
06425       };
06426 
06427       template <typename T>
06428       struct ilike_op : public opr_base<T>
06429       {
06430          typedef typename opr_base<T>::Type Type;
06431          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
06432          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
06433          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
06434          static inline details::operator_type operation() { return details::e_ilike; }
06435       };
06436 
06437       template <typename T>
06438       struct inrange_op : public opr_base<T>
06439       {
06440          typedef typename opr_base<T>::Type Type;
06441          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
06442          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
06443          {
06444             return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
06445          }
06446          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
06447          static inline details::operator_type operation() { return details::e_inrange; }
06448       };
06449 
06450       template <typename T>
06451       inline T value(details::expression_node<T>* n)
06452       {
06453          return n->value();
06454       }
06455 
06456       template <typename T>
06457       inline T value(T* t)
06458       {
06459          return (*t);
06460       }
06461 
06462       template <typename T>
06463       struct vararg_add_op : public opr_base<T>
06464       {
06465          typedef typename opr_base<T>::Type Type;
06466 
06467          template <typename Type,
06468                    typename Allocator,
06469                    template <typename,typename> class Sequence>
06470          static inline T process(const Sequence<Type,Allocator>& arglist)
06471          {
06472             switch (arglist.size())
06473             {
06474                case 0  : return T(0);
06475                case 1  : return process_1(arglist);
06476                case 2  : return process_2(arglist);
06477                case 3  : return process_3(arglist);
06478                case 4  : return process_4(arglist);
06479                case 5  : return process_5(arglist);
06480                default :
06481                          {
06482                             T result = T(0);
06483                             for (std::size_t i = 0; i < arglist.size(); ++i)
06484                             {
06485                               result += value(arglist[i]);
06486                             }
06487                             return result;
06488                          }
06489             }
06490          }
06491 
06492          template <typename Sequence>
06493          static inline T process_1(const Sequence& arglist)
06494          {
06495             return value(arglist[0]);
06496          }
06497 
06498          template <typename Sequence>
06499          static inline T process_2(const Sequence& arglist)
06500          {
06501             return value(arglist[0]) + value(arglist[1]);
06502          }
06503 
06504          template <typename Sequence>
06505          static inline T process_3(const Sequence& arglist)
06506          {
06507             return value(arglist[0]) + value(arglist[1]) +
06508                    value(arglist[2]);
06509          }
06510 
06511          template <typename Sequence>
06512          static inline T process_4(const Sequence& arglist)
06513          {
06514             return value(arglist[0]) + value(arglist[1]) +
06515                    value(arglist[2]) + value(arglist[3]);
06516          }
06517 
06518          template <typename Sequence>
06519          static inline T process_5(const Sequence& arglist)
06520          {
06521             return value(arglist[0]) + value(arglist[1]) +
06522                    value(arglist[2]) + value(arglist[3]) +
06523                    value(arglist[4]);
06524          }
06525       };
06526 
06527       template <typename T>
06528       struct vararg_mul_op : public opr_base<T>
06529       {
06530          typedef typename opr_base<T>::Type Type;
06531 
06532          template <typename Type,
06533                    typename Allocator,
06534                    template <typename,typename> class Sequence>
06535          static inline T process(const Sequence<Type,Allocator>& arglist)
06536          {
06537             switch (arglist.size())
06538             {
06539                case 0  : return T(0);
06540                case 1  : return process_1(arglist);
06541                case 2  : return process_2(arglist);
06542                case 3  : return process_3(arglist);
06543                case 4  : return process_4(arglist);
06544                case 5  : return process_5(arglist);
06545                default :
06546                          {
06547                             T result = T(value(arglist[0]));
06548                             for (std::size_t i = 1; i < arglist.size(); ++i)
06549                             {
06550                                result *= value(arglist[i]);
06551                             }
06552                             return result;
06553                          }
06554             }
06555          }
06556 
06557          template <typename Sequence>
06558          static inline T process_1(const Sequence& arglist)
06559          {
06560             return value(arglist[0]);
06561          }
06562 
06563          template <typename Sequence>
06564          static inline T process_2(const Sequence& arglist)
06565          {
06566             return value(arglist[0]) * value(arglist[1]);
06567          }
06568 
06569          template <typename Sequence>
06570          static inline T process_3(const Sequence& arglist)
06571          {
06572             return value(arglist[0]) * value(arglist[1]) *
06573                    value(arglist[2]);
06574          }
06575 
06576          template <typename Sequence>
06577          static inline T process_4(const Sequence& arglist)
06578          {
06579             return value(arglist[0]) * value(arglist[1]) *
06580                    value(arglist[2]) * value(arglist[3]);
06581          }
06582 
06583          template <typename Sequence>
06584          static inline T process_5(const Sequence& arglist)
06585          {
06586             return value(arglist[0]) * value(arglist[1]) *
06587                    value(arglist[2]) * value(arglist[3]) *
06588                    value(arglist[4]);
06589          }
06590       };
06591 
06592       template <typename T>
06593       struct vararg_avg_op : public opr_base<T>
06594       {
06595          typedef typename opr_base<T>::Type Type;
06596 
06597          template <typename Type,
06598                    typename Allocator,
06599                    template <typename,typename> class Sequence>
06600          static inline T process(const Sequence<Type,Allocator>& arglist)
06601          {
06602             switch (arglist.size())
06603             {
06604                case 0  : return T(0);
06605                case 1  : return process_1(arglist);
06606                case 2  : return process_2(arglist);
06607                case 3  : return process_3(arglist);
06608                case 4  : return process_4(arglist);
06609                case 5  : return process_5(arglist);
06610                default : return vararg_add_op<T>::process(arglist) / arglist.size();
06611             }
06612          }
06613 
06614          template <typename Sequence>
06615          static inline T process_1(const Sequence& arglist)
06616          {
06617             return value(arglist[0]);
06618          }
06619 
06620          template <typename Sequence>
06621          static inline T process_2(const Sequence& arglist)
06622          {
06623             return (value(arglist[0]) + value(arglist[1])) / T(2);
06624          }
06625 
06626          template <typename Sequence>
06627          static inline T process_3(const Sequence& arglist)
06628          {
06629             return (value(arglist[0]) + value(arglist[1]) + value(arglist[2])) / T(3);
06630          }
06631 
06632          template <typename Sequence>
06633          static inline T process_4(const Sequence& arglist)
06634          {
06635             return (value(arglist[0]) + value(arglist[1]) +
06636                     value(arglist[2]) + value(arglist[3])) / T(4);
06637          }
06638 
06639          template <typename Sequence>
06640          static inline T process_5(const Sequence& arglist)
06641          {
06642             return (value(arglist[0]) + value(arglist[1]) +
06643                     value(arglist[2]) + value(arglist[3]) +
06644                     value(arglist[4])) / T(5);
06645          }
06646       };
06647 
06648       template <typename T>
06649       struct vararg_min_op : public opr_base<T>
06650       {
06651          typedef typename opr_base<T>::Type Type;
06652 
06653          template <typename Type,
06654                    typename Allocator,
06655                    template <typename,typename> class Sequence>
06656          static inline T process(const Sequence<Type,Allocator>& arglist)
06657          {
06658             switch (arglist.size())
06659             {
06660                case 0  : return T(0);
06661                case 1  : return process_1(arglist);
06662                case 2  : return process_2(arglist);
06663                case 3  : return process_3(arglist);
06664                case 4  : return process_4(arglist);
06665                case 5  : return process_5(arglist);
06666                default :
06667                          {
06668                             T result = T(value(arglist[0]));
06669                             for (std::size_t i = 1; i < arglist.size(); ++i)
06670                             {
06671                                const T v = value(arglist[i]);
06672                                if (v < result)
06673                                   result = v;
06674                             }
06675                             return result;
06676                          }
06677             }
06678          }
06679 
06680          template <typename Sequence>
06681          static inline T process_1(const Sequence& arglist)
06682          {
06683             return value(arglist[0]);
06684          }
06685 
06686          template <typename Sequence>
06687          static inline T process_2(const Sequence& arglist)
06688          {
06689             return std::min<T>(value(arglist[0]),value(arglist[1]));
06690          }
06691 
06692          template <typename Sequence>
06693          static inline T process_3(const Sequence& arglist)
06694          {
06695             return std::min<T>(std::min<T>(value(arglist[0]),value(arglist[1])),value(arglist[2]));
06696          }
06697 
06698          template <typename Sequence>
06699          static inline T process_4(const Sequence& arglist)
06700          {
06701             return std::min<T>(
06702                         std::min<T>(value(arglist[0]),value(arglist[1])),
06703                         std::min<T>(value(arglist[2]),value(arglist[3])));
06704          }
06705 
06706          template <typename Sequence>
06707          static inline T process_5(const Sequence& arglist)
06708          {
06709             return std::min<T>(
06710                    std::min<T>(std::min<T>(value(arglist[0]),value(arglist[1])),
06711                                std::min<T>(value(arglist[2]),value(arglist[3]))),
06712                                value(arglist[4]));
06713          }
06714       };
06715 
06716       template <typename T>
06717       struct vararg_max_op : public opr_base<T>
06718       {
06719          typedef typename opr_base<T>::Type Type;
06720 
06721          template <typename Type,
06722                    typename Allocator,
06723                    template <typename,typename> class Sequence>
06724          static inline T process(const Sequence<Type,Allocator>& arglist)
06725          {
06726             switch (arglist.size())
06727             {
06728                case 0  : return T(0);
06729                case 1  : return process_1(arglist);
06730                case 2  : return process_2(arglist);
06731                case 3  : return process_3(arglist);
06732                case 4  : return process_4(arglist);
06733                case 5  : return process_5(arglist);
06734                default :
06735                          {
06736                             T result = T(value(arglist[0]));
06737                             for (std::size_t i = 1; i < arglist.size(); ++i)
06738                             {
06739                                const T v = value(arglist[i]);
06740                                if (v > result)
06741                                   result = v;
06742                             }
06743                             return result;
06744                          }
06745             }
06746          }
06747 
06748          template <typename Sequence>
06749          static inline T process_1(const Sequence& arglist)
06750          {
06751             return value(arglist[0]);
06752          }
06753 
06754          template <typename Sequence>
06755          static inline T process_2(const Sequence& arglist)
06756          {
06757             return std::max<T>(value(arglist[0]),value(arglist[1]));
06758          }
06759 
06760          template <typename Sequence>
06761          static inline T process_3(const Sequence& arglist)
06762          {
06763             return std::max<T>(std::max<T>(value(arglist[0]),value(arglist[1])),value(arglist[2]));
06764          }
06765 
06766          template <typename Sequence>
06767          static inline T process_4(const Sequence& arglist)
06768          {
06769             return std::max<T>(
06770                         std::max<T>(value(arglist[0]),value(arglist[1])),
06771                         std::max<T>(value(arglist[2]),value(arglist[3])));
06772          }
06773 
06774          template <typename Sequence>
06775          static inline T process_5(const Sequence& arglist)
06776          {
06777             return std::max<T>(
06778                    std::max<T>(std::max<T>(value(arglist[0]),value(arglist[1])),
06779                                std::max<T>(value(arglist[2]),value(arglist[3]))),
06780                                value(arglist[4]));
06781          }
06782       };
06783 
06784       template <typename T>
06785       struct vararg_mand_op : public opr_base<T>
06786       {
06787          typedef typename opr_base<T>::Type Type;
06788 
06789          template <typename Type,
06790                    typename Allocator,
06791                    template <typename,typename> class Sequence>
06792          static inline T process(const Sequence<Type,Allocator>& arglist)
06793          {
06794             switch (arglist.size())
06795             {
06796                case 1  : return process_1(arglist);
06797                case 2  : return process_2(arglist);
06798                case 3  : return process_3(arglist);
06799                case 4  : return process_4(arglist);
06800                case 5  : return process_5(arglist);
06801                default :
06802                          {
06803                             for (std::size_t i = 0; i < arglist.size(); ++i)
06804                             {
06805                                if (T(0) == value(arglist[i]))
06806                                   return T(0);
06807                             }
06808                             return T(1);
06809                          }
06810             }
06811          }
06812 
06813          template <typename Sequence>
06814          static inline T process_1(const Sequence& arglist)
06815          {
06816             return (T(0) != value(arglist[0])) ? T(1) : T(0);
06817          }
06818 
06819          template <typename Sequence>
06820          static inline T process_2(const Sequence& arglist)
06821          {
06822             return (
06823                      (T(0) != value(arglist[0])) &&
06824                      (T(0) != value(arglist[1]))
06825                    ) ? T(1) : T(0);
06826          }
06827 
06828          template <typename Sequence>
06829          static inline T process_3(const Sequence& arglist)
06830          {
06831             return (
06832                      (T(0) != value(arglist[0])) &&
06833                      (T(0) != value(arglist[1])) &&
06834                      (T(0) != value(arglist[2]))
06835                    ) ? T(1) : T(0);
06836          }
06837 
06838          template <typename Sequence>
06839          static inline T process_4(const Sequence& arglist)
06840          {
06841             return (
06842                      (T(0) != value(arglist[0])) &&
06843                      (T(0) != value(arglist[1])) &&
06844                      (T(0) != value(arglist[2])) &&
06845                      (T(0) != value(arglist[3]))
06846                    ) ? T(1) : T(0);
06847          }
06848 
06849          template <typename Sequence>
06850          static inline T process_5(const Sequence& arglist)
06851          {
06852             return (
06853                      (T(0) != value(arglist[0])) &&
06854                      (T(0) != value(arglist[1])) &&
06855                      (T(0) != value(arglist[2])) &&
06856                      (T(0) != value(arglist[3])) &&
06857                      (T(0) != value(arglist[4]))
06858                    ) ? T(1) : T(0);
06859          }
06860       };
06861 
06862       template <typename T>
06863       struct vararg_mor_op : public opr_base<T>
06864       {
06865          typedef typename opr_base<T>::Type Type;
06866 
06867          template <typename Type,
06868                    typename Allocator,
06869                    template <typename,typename> class Sequence>
06870          static inline T process(const Sequence<Type,Allocator>& arglist)
06871          {
06872             switch (arglist.size())
06873             {
06874                case 1  : return process_1(arglist);
06875                case 2  : return process_2(arglist);
06876                case 3  : return process_3(arglist);
06877                case 4  : return process_4(arglist);
06878                case 5  : return process_5(arglist);
06879                default :
06880                          {
06881                             for (std::size_t i = 0; i < arglist.size(); ++i)
06882                             {
06883                                if (T(0) != value(arglist[i]))
06884                                   return T(1);
06885                             }
06886                             return T(0);
06887                          }
06888             }
06889          }
06890 
06891          template <typename Sequence>
06892          static inline T process_1(const Sequence& arglist)
06893          {
06894             return (T(0) != value(arglist[0])) ? T(1) : T(0);
06895          }
06896 
06897          template <typename Sequence>
06898          static inline T process_2(const Sequence& arglist)
06899          {
06900             return (
06901                      (T(0) != value(arglist[0])) ||
06902                      (T(0) != value(arglist[1]))
06903                    ) ? T(1) : T(0);
06904          }
06905 
06906          template <typename Sequence>
06907          static inline T process_3(const Sequence& arglist)
06908          {
06909             return (
06910                      (T(0) != value(arglist[0])) ||
06911                      (T(0) != value(arglist[1])) ||
06912                      (T(0) != value(arglist[2]))
06913                    ) ? T(1) : T(0);
06914          }
06915 
06916          template <typename Sequence>
06917          static inline T process_4(const Sequence& arglist)
06918          {
06919             return (
06920                      (T(0) != value(arglist[0])) ||
06921                      (T(0) != value(arglist[1])) ||
06922                      (T(0) != value(arglist[2])) ||
06923                      (T(0) != value(arglist[3]))
06924                    ) ? T(1) : T(0);
06925          }
06926 
06927          template <typename Sequence>
06928          static inline T process_5(const Sequence& arglist)
06929          {
06930             return (
06931                      (T(0) != value(arglist[0])) ||
06932                      (T(0) != value(arglist[1])) ||
06933                      (T(0) != value(arglist[2])) ||
06934                      (T(0) != value(arglist[3])) ||
06935                      (T(0) != value(arglist[4]))
06936                    ) ? T(1) : T(0);
06937          }
06938       };
06939 
06940       template <typename T>
06941       struct vararg_multi_op : public opr_base<T>
06942       {
06943          typedef typename opr_base<T>::Type Type;
06944 
06945          template <typename Type,
06946                    typename Allocator,
06947                    template <typename,typename> class Sequence>
06948          static inline T process(const Sequence<Type,Allocator>& arglist)
06949          {
06950             switch (arglist.size())
06951             {
06952                case 0  : return std::numeric_limits<T>::quiet_NaN();
06953                case 1  : return process_1(arglist);
06954                case 2  : return process_2(arglist);
06955                case 3  : return process_3(arglist);
06956                case 4  : return process_4(arglist);
06957                case 5  : return process_5(arglist);
06958                case 6  : return process_6(arglist);
06959                case 7  : return process_7(arglist);
06960                case 8  : return process_8(arglist);
06961                default :
06962                          {
06963                             for (std::size_t i = 0; i < (arglist.size() - 1); ++i)
06964                             {
06965                                value(arglist[i]);
06966                             }
06967                             return value(arglist.back());
06968                          }
06969             }
06970          }
06971 
06972          template <typename Sequence>
06973          static inline T process_1(const Sequence& arglist)
06974          {
06975             return value(arglist[0]);
06976          }
06977 
06978          template <typename Sequence>
06979          static inline T process_2(const Sequence& arglist)
06980          {
06981                    value(arglist[0]);
06982             return value(arglist[1]);
06983          }
06984 
06985          template <typename Sequence>
06986          static inline T process_3(const Sequence& arglist)
06987          {
06988                    value(arglist[0]);
06989                    value(arglist[1]);
06990             return value(arglist[2]);
06991          }
06992 
06993          template <typename Sequence>
06994          static inline T process_4(const Sequence& arglist)
06995          {
06996                    value(arglist[0]);
06997                    value(arglist[1]);
06998                    value(arglist[2]);
06999             return value(arglist[3]);
07000          }
07001 
07002          template <typename Sequence>
07003          static inline T process_5(const Sequence& arglist)
07004          {
07005                    value(arglist[0]);
07006                    value(arglist[1]);
07007                    value(arglist[2]);
07008                    value(arglist[3]);
07009             return value(arglist[4]);
07010          }
07011 
07012          template <typename Sequence>
07013          static inline T process_6(const Sequence& arglist)
07014          {
07015                    value(arglist[0]);
07016                    value(arglist[1]);
07017                    value(arglist[2]);
07018                    value(arglist[3]);
07019                    value(arglist[4]);
07020             return value(arglist[5]);
07021          }
07022 
07023          template <typename Sequence>
07024          static inline T process_7(const Sequence& arglist)
07025          {
07026                    value(arglist[0]);
07027                    value(arglist[1]);
07028                    value(arglist[2]);
07029                    value(arglist[3]);
07030                    value(arglist[4]);
07031                    value(arglist[5]);
07032             return value(arglist[6]);
07033          }
07034 
07035          template <typename Sequence>
07036          static inline T process_8(const Sequence& arglist)
07037          {
07038                    value(arglist[0]);
07039                    value(arglist[1]);
07040                    value(arglist[2]);
07041                    value(arglist[3]);
07042                    value(arglist[4]);
07043                    value(arglist[5]);
07044                    value(arglist[6]);
07045             return value(arglist[7]);
07046          }
07047       };
07048 
07049       template <typename T>
07050       class vov_base_node : public expression_node<T>
07051       {
07052       public:
07053 
07054          inline virtual operator_type operation() const
07055          {
07056             return details::e_default;
07057          }
07058 
07059          virtual const T& v0() const = 0;
07060 
07061          virtual const T& v1() const = 0;
07062       };
07063 
07064       template <typename T>
07065       class cov_base_node : public expression_node<T>
07066       {
07067       public:
07068 
07069          inline virtual operator_type operation() const
07070          {
07071             return details::e_default;
07072          }
07073 
07074          virtual const T c() const = 0;
07075 
07076          virtual const T& v() const = 0;
07077       };
07078 
07079       template <typename T>
07080       class voc_base_node : public expression_node<T>
07081       {
07082       public:
07083 
07084          inline virtual operator_type operation() const
07085          {
07086             return details::e_default;
07087          }
07088 
07089          virtual const T c() const = 0;
07090 
07091          virtual const T& v() const = 0;
07092       };
07093 
07094       template <typename T>
07095       class vob_base_node : public expression_node<T>
07096       {
07097       public:
07098 
07099          virtual const T& v() const = 0;
07100       };
07101 
07102       template <typename T>
07103       class bov_base_node : public expression_node<T>
07104       {
07105       public:
07106 
07107          virtual const T& v() const = 0;
07108       };
07109 
07110       template <typename T>
07111       class cob_base_node : public expression_node<T>
07112       {
07113       public:
07114 
07115          inline virtual operator_type operation() const
07116          {
07117             return details::e_default;
07118          }
07119 
07120          virtual const T c() const = 0;
07121 
07122          virtual void set_c(const T) = 0;
07123 
07124          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
07125       };
07126 
07127       template <typename T>
07128       class boc_base_node : public expression_node<T>
07129       {
07130       public:
07131 
07132          inline virtual operator_type operation() const
07133          {
07134             return details::e_default;
07135          }
07136 
07137          virtual const T c() const = 0;
07138 
07139          virtual void set_c(const T) = 0;
07140       };
07141 
07142       template <typename T>
07143       class uv_base_node : public expression_node<T>
07144       {
07145       public:
07146 
07147          inline virtual operator_type operation() const
07148          {
07149             return details::e_default;
07150          }
07151 
07152          virtual const T& v() const = 0;
07153       };
07154 
07155       template <typename T>
07156       class sos_base_node : public expression_node<T>
07157       {
07158       public:
07159 
07160          inline virtual operator_type operation() const
07161          {
07162             return details::e_default;
07163          }
07164       };
07165 
07166       template <typename T>
07167       class sosos_base_node : public expression_node<T>
07168       {
07169       public:
07170 
07171          inline virtual operator_type operation() const
07172          {
07173             return details::e_default;
07174          }
07175       };
07176 
07177       template <typename T>
07178       class T0oT1oT2_base_node : public expression_node<T>
07179       {
07180       public:
07181 
07182          virtual std::string type_id() const = 0;
07183       };
07184 
07185       template <typename T>
07186       class T0oT1oT2oT3_base_node : public expression_node<T>
07187       {
07188       public:
07189 
07190          virtual std::string type_id() const = 0;
07191       };
07192 
07193       template <typename T, typename Operation>
07194       class unary_variable_node : public uv_base_node<T>
07195       {
07196       public:
07197 
07198          typedef expression_node<T>* expression_ptr;
07199          typedef Operation operation_t;
07200 
07201          explicit unary_variable_node(const T& v)
07202          : v_(v)
07203          {}
07204 
07205          inline T value() const
07206          {
07207             return Operation::process(v_);
07208          }
07209 
07210          inline typename expression_node<T>::node_type type() const
07211          {
07212             return Operation::type();
07213          }
07214 
07215          inline operator_type operation() const
07216          {
07217             return Operation::operation();
07218          }
07219 
07220          inline const T& v() const
07221          {
07222             return v_;
07223          }
07224 
07225       private:
07226 
07227          unary_variable_node(unary_variable_node<T,Operation>&);
07228          unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
07229 
07230          const T& v_;
07231       };
07232 
07233       template <typename T>
07234       class uvouv_node : public expression_node<T>
07235       {
07236       public:
07237 
07238          // UOpr1(v0) Op UOpr2(v1)
07239 
07240          typedef expression_node<T>* expression_ptr;
07241          typedef typename details::functor_t<T> functor_t;
07242          typedef typename functor_t::bfunc_t bfunc_t;
07243          typedef typename functor_t::ufunc_t ufunc_t;
07244 
07245          explicit uvouv_node(const T& v0,const T& v1, ufunc_t u0, ufunc_t u1, bfunc_t f)
07246          : v0_(v0),
07247            v1_(v1),
07248            u0_(u0),
07249            u1_(u1),
07250            f_ (f )
07251          {}
07252 
07253          inline T value() const
07254          {
07255             return f_(u0_(v0_),u1_(v1_));
07256          }
07257 
07258          inline typename expression_node<T>::node_type type() const
07259          {
07260             return expression_node<T>::e_uvouv;
07261          }
07262 
07263          inline operator_type operation() const
07264          {
07265             return details::e_default;
07266          }
07267 
07268          inline const T& v0()
07269          {
07270             return v0_;
07271          }
07272 
07273          inline const T& v1()
07274          {
07275             return v1_;
07276          }
07277 
07278          inline ufunc_t u0()
07279          {
07280             return u0_;
07281          }
07282 
07283          inline ufunc_t u1()
07284          {
07285             return u1_;
07286          }
07287 
07288          inline ufunc_t f()
07289          {
07290             return f_;
07291          }
07292 
07293       private:
07294 
07295          uvouv_node(uvouv_node<T>&);
07296          uvouv_node<T>& operator=(uvouv_node<T>&);
07297 
07298          const T& v0_;
07299          const T& v1_;
07300          const ufunc_t u0_;
07301          const ufunc_t u1_;
07302          const bfunc_t f_;
07303       };
07304 
07305       template <typename T, typename Operation>
07306       class unary_branch_node : public expression_node<T>
07307       {
07308       public:
07309 
07310          typedef expression_node<T>* expression_ptr;
07311          typedef Operation operation_t;
07312 
07313          explicit unary_branch_node(expression_ptr branch)
07314          : branch_(branch),
07315            branch_deletable_(branch_deletable(branch_))
07316          {}
07317 
07318         ~unary_branch_node()
07319          {
07320             if (branch_ && branch_deletable_)
07321             {
07322                delete branch_;
07323                branch_ = 0;
07324             }
07325          }
07326 
07327          inline T value() const
07328          {
07329             return Operation::process(branch_->value());
07330          }
07331 
07332          inline typename expression_node<T>::node_type type() const
07333          {
07334             return Operation::type();
07335          }
07336 
07337          inline operator_type operation() const
07338          {
07339             return Operation::operation();
07340          }
07341 
07342       private:
07343 
07344          unary_branch_node(unary_branch_node<T,Operation>&);
07345          unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
07346 
07347          expression_ptr branch_;
07348          bool           branch_deletable_;
07349       };
07350 
07351       template <typename T> struct is_const                { enum {result = 0}; };
07352       template <typename T> struct is_const <const T>      { enum {result = 1}; };
07353       template <typename T> struct is_const_ref            { enum {result = 0}; };
07354       template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
07355       template <typename T> struct is_ref                  { enum {result = 0}; };
07356       template <typename T> struct is_ref<T&>              { enum {result = 1}; };
07357       template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
07358 
07359       template <std::size_t State>
07360       struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
07361 
07362       template <>
07363       struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
07364 
07365       template <typename T>
07366       struct T0oT1oT2process
07367       {
07368          typedef typename details::functor_t<T> functor_t;
07369          typedef typename functor_t::bfunc_t bfunc_t;
07370 
07371          struct mode0
07372          {
07373             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
07374             {
07375                // (T0 o0 T1) o1 T2
07376                return bf1(bf0(t0,t1),t2);
07377             }
07378 
07379             template <typename T0, typename T1, typename T2>
07380             static inline std::string id()
07381             {
07382                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o"   +
07383                                                        param_to_str<is_const_ref<T1>::result>::result() + ")o(" +
07384                                                        param_to_str<is_const_ref<T2>::result>::result() + ")"   ;
07385                return result;
07386             }
07387          };
07388 
07389          struct mode1
07390          {
07391             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
07392             {
07393                // T0 o0 (T1 o1 T2)
07394                return bf0(t0,bf1(t1,t2));
07395             }
07396 
07397             template <typename T0, typename T1, typename T2>
07398             static inline std::string id()
07399             {
07400                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o(" +
07401                                                        param_to_str<is_const_ref<T1>::result>::result() + "o"   +
07402                                                        param_to_str<is_const_ref<T2>::result>::result() + ")"   ;
07403                return result;
07404             }
07405          };
07406       };
07407 
07408       template <typename T>
07409       struct T0oT1oT20T3process
07410       {
07411          typedef typename details::functor_t<T> functor_t;
07412          typedef typename functor_t::bfunc_t bfunc_t;
07413 
07414          struct mode0
07415          {
07416             static inline T process(const T& t0, const T& t1,
07417                                     const T& t2, const T& t3,
07418                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07419             {
07420                // (T0 o0 T1) o1 (T2 o2 T3)
07421                return bf1(bf0(t0,t1),bf2(t2,t3));
07422             }
07423 
07424             template <typename T0, typename T1, typename T2, typename T3>
07425             static inline std::string id()
07426             {
07427                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o"  +
07428                                                        param_to_str<is_const_ref<T1>::result>::result() + ")o" +
07429                                                  "(" + param_to_str<is_const_ref<T2>::result>::result() + "o"  +
07430                                                        param_to_str<is_const_ref<T3>::result>::result() + ")"  ;
07431                return result;
07432             }
07433          };
07434 
07435          struct mode1
07436          {
07437             static inline T process(const T& t0, const T& t1,
07438                                     const T& t2, const T& t3,
07439                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07440             {
07441                // (T0 o0 (T1 o1 (T2 o2 T3))
07442                return bf0(t0,bf1(t1,bf2(t2,t3)));
07443             }
07444             template <typename T0, typename T1, typename T2, typename T3>
07445             static inline std::string id()
07446             {
07447                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() +  ")o((" +
07448                                                        param_to_str<is_const_ref<T1>::result>::result() +  ")o("  +
07449                                                        param_to_str<is_const_ref<T2>::result>::result() +  "o"    +
07450                                                        param_to_str<is_const_ref<T3>::result>::result() +  "))"   ;
07451                return result;
07452             }
07453          };
07454 
07455          struct mode2
07456          {
07457             static inline T process(const T& t0, const T& t1,
07458                                     const T& t2, const T& t3,
07459                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07460             {
07461                // (T0 o0 ((T1 o1 T2) o2 T3)
07462                return bf0(t0,bf2(bf1(t1,t2),t3));
07463             }
07464 
07465             template <typename T0, typename T1, typename T2, typename T3>
07466             static inline std::string id()
07467             {
07468                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o((" +
07469                                                        param_to_str<is_const_ref<T1>::result>::result() + "o"    +
07470                                                        param_to_str<is_const_ref<T2>::result>::result() + ")o("  +
07471                                                        param_to_str<is_const_ref<T3>::result>::result() + "))"   ;
07472                return result;
07473             }
07474          };
07475 
07476          struct mode3
07477          {
07478             static inline T process(const T& t0, const T& t1,
07479                                     const T& t2, const T& t3,
07480                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07481             {
07482                // (((T0 o0 T1) o1 T2) o2 T3)
07483                return bf2(bf1(bf0(t0,t1),t2),t3);
07484             }
07485 
07486             template <typename T0, typename T1, typename T2, typename T3>
07487             static inline std::string id()
07488             {
07489                static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + "o"    +
07490                                                         param_to_str<is_const_ref<T1>::result>::result() + ")o("  +
07491                                                         param_to_str<is_const_ref<T2>::result>::result() + "))o(" +
07492                                                         param_to_str<is_const_ref<T3>::result>::result() + ")";
07493                return result;
07494             }
07495          };
07496 
07497          struct mode4
07498          {
07499             static inline T process(const T& t0, const T& t1,
07500                                     const T& t2, const T& t3,
07501                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07502             {
07503                // ((T0 o0 (T1 o1 T2)) o2 T3
07504                return bf2(bf0(t0,bf1(t1,t2)),t3);
07505             }
07506 
07507             template <typename T0, typename T1, typename T2, typename T3>
07508             static inline std::string id()
07509             {
07510                static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + ")o("  +
07511                                                         param_to_str<is_const_ref<T1>::result>::result() + "o"    +
07512                                                         param_to_str<is_const_ref<T2>::result>::result() + "))o(" +
07513                                                         param_to_str<is_const_ref<T3>::result>::result() + ")"    ;
07514                return result;
07515             }
07516          };
07517       };
07518 
07519       template <typename T, typename T0, typename T1>
07520       struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
07521       template <typename T, typename T0, typename T1>
07522       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
07523 
07524       #define synthnode_type_define(T0_,T1_,v_)                                                                 \
07525       template <typename T, typename T0, typename T1>                                                           \
07526       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
07527       template <typename T, typename T0, typename T1>                                                           \
07528       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
07529 
07530       synthnode_type_define(const T0&,const T1&, e_vov)
07531       synthnode_type_define(const T0&,const T1 , e_voc)
07532       synthnode_type_define(const T0 ,const T1&, e_cov)
07533       synthnode_type_define(      T0&,      T1&,e_none)
07534       synthnode_type_define(const T0 ,const T1 ,e_none)
07535       synthnode_type_define(      T0&,const T1 ,e_none)
07536       synthnode_type_define(const T0 ,      T1&,e_none)
07537       synthnode_type_define(const T0&,      T1&,e_none)
07538       synthnode_type_define(      T0&,const T1&,e_none)
07539       #undef synthnode_type_define
07540 
07541       template <typename T, typename T0, typename T1, typename T2>
07542       struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
07543       template <typename T, typename T0, typename T1, typename T2>
07544       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
07545 
07546       #define synthnode_type_define(T0_,T1_,T2_,v_)                                                                    \
07547       template <typename T, typename T0, typename T1, typename T2>                                                     \
07548       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
07549       template <typename T, typename T0, typename T1, typename T2>                                                     \
07550       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
07551 
07552       synthnode_type_define(const T0&,const T1&,const T2&, e_vovov)
07553       synthnode_type_define(const T0&,const T1&,const T2 , e_vovoc)
07554       synthnode_type_define(const T0&,const T1 ,const T2&, e_vocov)
07555       synthnode_type_define(const T0 ,const T1&,const T2&, e_covov)
07556       synthnode_type_define(const T0 ,const T1&,const T2 , e_covoc)
07557       synthnode_type_define(const T0 ,const T1 ,const T2 , e_none )
07558       synthnode_type_define(const T0 ,const T1 ,const T2&, e_none )
07559       synthnode_type_define(const T0&,const T1 ,const T2 , e_none )
07560       synthnode_type_define(      T0&,      T1&,      T2&, e_none )
07561       #undef synthnode_type_define
07562 
07563       template <typename T, typename T0, typename T1, typename T2, typename T3>
07564       struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
07565       template <typename T, typename T0, typename T1, typename T2, typename T3>
07566       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
07567 
07568       #define synthnode_type_define(T0_,T1_,T2_,T3_,v_)                                                                       \
07569       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
07570       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
07571       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
07572       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
07573 
07574       synthnode_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov)
07575       synthnode_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc)
07576       synthnode_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov)
07577       synthnode_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov)
07578       synthnode_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov)
07579       synthnode_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov)
07580       synthnode_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc)
07581       synthnode_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc)
07582       synthnode_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov)
07583       synthnode_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none   )
07584       synthnode_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none   )
07585       synthnode_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none   )
07586       synthnode_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none   )
07587       synthnode_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none   )
07588       synthnode_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none   )
07589       synthnode_type_define(const T0&,const T1&,const T2 , const T3 ,e_none   )
07590       #undef synthnode_type_define
07591 
07592       template <typename T, typename T0, typename T1>
07593       class T0oT1 : public expression_node<T>
07594       {
07595       public:
07596 
07597          typedef typename details::functor_t<T> functor_t;
07598          typedef typename functor_t::bfunc_t bfunc_t;
07599          typedef T value_type;
07600          typedef T0oT1<T,T0,T1> node_type;
07601 
07602          T0oT1(T0 t0, T1 t1, const bfunc_t f)
07603          : t0_(t0),
07604            t1_(t1),
07605            f_(f)
07606          {}
07607 
07608          inline typename expression_node<T>::node_type type() const
07609          {
07610             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
07611             return result;
07612          }
07613 
07614          inline operator_type operation() const
07615          {
07616             return e_default;
07617          }
07618 
07619          inline T value() const
07620          {
07621             return f_(t0_,t1_);
07622          }
07623 
07624          inline T0 t0() const
07625          {
07626             return t0_;
07627          }
07628 
07629          inline T1 t1() const
07630          {
07631             return t1_;
07632          }
07633 
07634          inline bfunc_t f() const
07635          {
07636             return f_;
07637          }
07638 
07639          template <typename Allocator>
07640          static inline expression_node<T>* allocate(Allocator& allocator,
07641                                                     T0 t0, T1 t1,
07642                                                     bfunc_t f)
07643          {
07644             return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(t0,t1,f);
07645          }
07646 
07647       private:
07648 
07649          T0oT1(T0oT1<T,T0,T1>&) {}
07650          T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; }
07651 
07652          T0 t0_;
07653          T1 t1_;
07654          const bfunc_t f_;
07655       };
07656 
07657       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
07658       class T0oT1oT2 : public T0oT1oT2_base_node<T>
07659       {
07660       public:
07661 
07662          typedef typename details::functor_t<T> functor_t;
07663          typedef typename functor_t::bfunc_t bfunc_t;
07664          typedef T value_type;
07665          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
07666          typedef ProcessMode process_mode_t;
07667 
07668          T0oT1oT2(T0 t0, T1 t1, T2 t2, const bfunc_t f0, const bfunc_t f1)
07669          : t0_(t0),
07670            t1_(t1),
07671            t2_(t2),
07672            f0_(f0),
07673            f1_(f1)
07674          {}
07675 
07676          inline typename expression_node<T>::node_type type() const
07677          {
07678             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
07679             return result;
07680          }
07681 
07682          inline operator_type operation() const
07683          {
07684             return e_default;
07685          }
07686 
07687          inline T value() const
07688          {
07689             return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
07690          }
07691 
07692          inline T0 t0() const
07693          {
07694             return t0_;
07695          }
07696 
07697          inline T1 t1() const
07698          {
07699             return t1_;
07700          }
07701 
07702          inline T2 t2() const
07703          {
07704             return t2_;
07705          }
07706 
07707          bfunc_t f0() const
07708          {
07709             return f0_;
07710          }
07711 
07712          bfunc_t f1() const
07713          {
07714             return f1_;
07715          }
07716 
07717          std::string type_id() const
07718          {
07719             return id();
07720          }
07721 
07722          static inline std::string id()
07723          {
07724             return process_mode_t::template id<T0,T1,T2>();
07725          }
07726 
07727          template <typename Allocator>
07728          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, bfunc_t f0, bfunc_t f1)
07729          {
07730             return allocator.template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>(t0,t1,t2,f0,f1);
07731          }
07732 
07733       private:
07734 
07735          T0oT1oT2(node_type&) {}
07736          node_type& operator=(node_type&) { return *this; }
07737 
07738          T0 t0_;
07739          T1 t1_;
07740          T2 t2_;
07741          const bfunc_t f0_;
07742          const bfunc_t f1_;
07743       };
07744 
07745       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
07746       class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
07747       {
07748       public:
07749 
07750          typedef typename details::functor_t<T> functor_t;
07751          typedef typename functor_t::bfunc_t bfunc_t;
07752          typedef T value_type;
07753          typedef T0_ T0;
07754          typedef T1_ T1;
07755          typedef T2_ T2;
07756          typedef T3_ T3;
07757          typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
07758          typedef ProcessMode process_mode_t;
07759 
07760          T0oT1oT2oT3(T0 t0, T1 t1, T2 t2, T3 t3, bfunc_t f0, bfunc_t f1, bfunc_t f2)
07761          : t0_(t0),
07762            t1_(t1),
07763            t2_(t2),
07764            t3_(t3),
07765            f0_(f0),
07766            f1_(f1),
07767            f2_(f2)
07768          {}
07769 
07770          inline T value() const
07771          {
07772             return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_);
07773          }
07774 
07775          inline T0 t0() const
07776          {
07777             return t0_;
07778          }
07779 
07780          inline T1 t1() const
07781          {
07782             return t1_;
07783          }
07784 
07785          inline T2 t2() const
07786          {
07787             return t2_;
07788          }
07789 
07790          inline T3 t3() const
07791          {
07792             return t3_;
07793          }
07794 
07795          inline bfunc_t f0() const
07796          {
07797             return f0_;
07798          }
07799 
07800          inline bfunc_t f1() const
07801          {
07802             return f1_;
07803          }
07804 
07805          inline bfunc_t f2() const
07806          {
07807             return f2_;
07808          }
07809 
07810          inline std::string type_id() const
07811          {
07812             return id();
07813          }
07814 
07815          static inline std::string id()
07816          {
07817             return process_mode_t::template id<T0,T1,T2,T3>();
07818          }
07819 
07820          template <typename Allocator>
07821          static inline expression_node<T>* allocate(Allocator& allocator,
07822                                                     T0 t0, T1 t1, T2 t2, T3 t3,
07823                                                     bfunc_t f0, bfunc_t f1, bfunc_t f2)
07824          {
07825             return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(t0,t1,t2,t3,f0,f1,f2);
07826          }
07827 
07828       private:
07829 
07830          T0oT1oT2oT3(node_type&) {}
07831          node_type& operator=(node_type&) { return *this; }
07832 
07833          T0 t0_;
07834          T1 t1_;
07835          T2 t2_;
07836          T3 t3_;
07837          const bfunc_t f0_;
07838          const bfunc_t f1_;
07839          const bfunc_t f2_;
07840       };
07841 
07842       template <typename T, typename T0, typename T1, typename T2>
07843       class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
07844       {
07845       public:
07846 
07847          typedef typename details::functor_t<T> functor_t;
07848          typedef typename functor_t::tfunc_t tfunc_t;
07849          typedef T value_type;
07850          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
07851 
07852          T0oT1oT2_sf3(T0 t0, T1 t1, T2 t2, const tfunc_t f)
07853          : t0_(t0),
07854            t1_(t1),
07855            t2_(t2),
07856            f_(f)
07857          {}
07858 
07859          inline typename expression_node<T>::node_type type() const
07860          {
07861             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
07862             return result;
07863          }
07864 
07865          inline operator_type operation() const
07866          {
07867             return e_default;
07868          }
07869 
07870          inline T value() const
07871          {
07872             return f_(t0_,t1_,t2_);
07873          }
07874 
07875          inline T0 t0() const
07876          {
07877             return t0_;
07878          }
07879 
07880          inline T1 t1() const
07881          {
07882             return t1_;
07883          }
07884 
07885          inline T2 t2() const
07886          {
07887             return t2_;
07888          }
07889 
07890          tfunc_t f() const
07891          {
07892             return f_;
07893          }
07894 
07895          std::string type_id() const
07896          {
07897             return id();
07898          }
07899 
07900          static inline std::string id()
07901          {
07902             return "sf3";
07903          }
07904 
07905          template <typename Allocator>
07906          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, tfunc_t f)
07907          {
07908             return allocator.template allocate_type<node_type,T0,T1,T2,tfunc_t>(t0,t1,t2,f);
07909          }
07910 
07911       private:
07912 
07913          T0oT1oT2_sf3(node_type&) {}
07914          node_type& operator=(node_type&) { return *this; }
07915 
07916          T0 t0_;
07917          T1 t1_;
07918          T2 t2_;
07919          const tfunc_t f_;
07920       };
07921 
07922       template <typename T, typename T0, typename T1, typename T2>
07923       class sf3ext_type_node : public T0oT1oT2_base_node<T>
07924       {
07925       public:
07926 
07927          virtual T0 t0() const = 0;
07928 
07929          virtual T1 t1() const = 0;
07930 
07931          virtual T2 t2() const = 0;
07932       };
07933 
07934       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
07935       class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
07936       {
07937       public:
07938 
07939          typedef typename details::functor_t<T> functor_t;
07940          typedef typename functor_t::tfunc_t tfunc_t;
07941          typedef T value_type;
07942          typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
07943 
07944          T0oT1oT2_sf3ext(T0 t0, T1 t1, T2 t2)
07945          : t0_(t0),
07946            t1_(t1),
07947            t2_(t2)
07948          {}
07949 
07950          inline typename expression_node<T>::node_type type() const
07951          {
07952             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
07953             return result;
07954          }
07955 
07956          inline operator_type operation() const
07957          {
07958             return e_default;
07959          }
07960 
07961          inline T value() const
07962          {
07963             return SF3Operation::process(t0_,t1_,t2_);
07964          }
07965 
07966          T0 t0() const
07967          {
07968             return t0_;
07969          }
07970 
07971          T1 t1() const
07972          {
07973             return t1_;
07974          }
07975 
07976          T2 t2() const
07977          {
07978             return t2_;
07979          }
07980 
07981          std::string type_id() const
07982          {
07983             return id();
07984          }
07985 
07986          static inline std::string id()
07987          {
07988             return SF3Operation::id();
07989          }
07990 
07991          template <typename Allocator>
07992          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2)
07993          {
07994             return allocator.template allocate_type<node_type,T0,T1,T2>(t0,t1,t2);
07995          }
07996 
07997       private:
07998 
07999          T0oT1oT2_sf3ext(node_type&) {}
08000          node_type& operator=(node_type&) { return *this; }
08001 
08002          T0 t0_;
08003          T1 t1_;
08004          T2 t2_;
08005       };
08006 
08007       template <typename T>
08008       inline bool is_sf3ext_node(const expression_node<T>* n)
08009       {
08010          switch (n->type())
08011          {
08012             case expression_node<T>::e_vovov : return true;
08013             case expression_node<T>::e_vovoc : return true;
08014             case expression_node<T>::e_vocov : return true;
08015             case expression_node<T>::e_covov : return true;
08016             case expression_node<T>::e_covoc : return true;
08017             default                          : return false;
08018          }
08019       }
08020 
08021       template <typename T, typename T0, typename T1, typename T2, typename T3>
08022       class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
08023       {
08024       public:
08025 
08026          typedef typename details::functor_t<T> functor_t;
08027          typedef typename functor_t::qfunc_t qfunc_t;
08028          typedef T value_type;
08029          typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
08030 
08031          T0oT1oT2oT3_sf4(T0 t0, T1 t1, T2 t2, T3 t3, const qfunc_t f)
08032          : t0_(t0),
08033            t1_(t1),
08034            t2_(t2),
08035            t3_(t3),
08036            f_(f)
08037          {}
08038 
08039          inline typename expression_node<T>::node_type type() const
08040          {
08041             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
08042             return result;
08043          }
08044 
08045          inline operator_type operation() const
08046          {
08047             return e_default;
08048          }
08049 
08050          inline T value() const
08051          {
08052             return f_(t0_,t1_,t2_,t3_);
08053          }
08054 
08055          inline T0 t0() const
08056          {
08057             return t0_;
08058          }
08059 
08060          inline T1 t1() const
08061          {
08062             return t1_;
08063          }
08064 
08065          inline T2 t2() const
08066          {
08067             return t2_;
08068          }
08069 
08070          inline T3 t3() const
08071          {
08072             return t3_;
08073          }
08074 
08075          qfunc_t f() const
08076          {
08077             return f_;
08078          }
08079 
08080          std::string type_id() const
08081          {
08082             return id();
08083          }
08084 
08085          static inline std::string id()
08086          {
08087             return "sf4";
08088          }
08089 
08090          template <typename Allocator>
08091          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3, qfunc_t f)
08092          {
08093             return allocator.template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>(t0,t1,t2,t3,f);
08094          }
08095 
08096       private:
08097 
08098          T0oT1oT2oT3_sf4(node_type&) {}
08099          node_type& operator=(node_type&) { return *this; }
08100 
08101          T0 t0_;
08102          T1 t1_;
08103          T2 t2_;
08104          T3 t3_;
08105          const qfunc_t f_;
08106       };
08107 
08108       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
08109       class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
08110       {
08111       public:
08112 
08113          typedef typename details::functor_t<T> functor_t;
08114          typedef typename functor_t::tfunc_t tfunc_t;
08115          typedef T value_type;
08116          typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
08117 
08118          T0oT1oT2oT3_sf4ext(T0 t0, T1 t1, T2 t2, T3 t3)
08119          : t0_(t0),
08120            t1_(t1),
08121            t2_(t2),
08122            t3_(t3)
08123          {}
08124 
08125          inline typename expression_node<T>::node_type type() const
08126          {
08127             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
08128             return result;
08129          }
08130 
08131          inline operator_type operation() const
08132          {
08133             return e_default;
08134          }
08135 
08136          inline T value() const
08137          {
08138             return SF4Operation::process(t0_,t1_,t2_,t3_);
08139          }
08140 
08141          inline T0 t0() const
08142          {
08143             return t0_;
08144          }
08145 
08146          inline T1 t1() const
08147          {
08148             return t1_;
08149          }
08150 
08151          inline T2 t2() const
08152          {
08153             return t2_;
08154          }
08155 
08156          inline T3 t3() const
08157          {
08158             return t2_;
08159          }
08160 
08161          std::string type_id() const
08162          {
08163             return id();
08164          }
08165 
08166          static inline std::string id()
08167          {
08168             return SF4Operation::id();
08169          }
08170 
08171          template <typename Allocator>
08172          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3)
08173          {
08174             return allocator.template allocate_type<node_type,T0,T1,T2,T3>(t0,t1,t2,t3);
08175          }
08176 
08177       private:
08178 
08179          T0oT1oT2oT3_sf4ext(node_type&) {}
08180          node_type& operator=(node_type&) { return *this; }
08181 
08182          T0 t0_;
08183          T1 t1_;
08184          T2 t2_;
08185          T3 t3_;
08186       };
08187 
08188       template <typename T>
08189       inline bool is_sf4ext_node(const expression_node<T>* n)
08190       {
08191          switch (n->type())
08192          {
08193             case expression_node<T>::e_vovovov : return true;
08194             case expression_node<T>::e_vovovoc : return true;
08195             case expression_node<T>::e_vovocov : return true;
08196             case expression_node<T>::e_vocovov : return true;
08197             case expression_node<T>::e_covovov : return true;
08198             case expression_node<T>::e_covocov : return true;
08199             case expression_node<T>::e_vocovoc : return true;
08200             case expression_node<T>::e_covovoc : return true;
08201             case expression_node<T>::e_vococov : return true;
08202             default                            : return false;
08203          }
08204       }
08205 
08206       template <typename T, typename T0, typename T1>
08207       struct T0oT1_define
08208       {
08209          typedef details::T0oT1<T,T0,T1> type0;
08210       };
08211 
08212       template <typename T, typename T0, typename T1, typename T2>
08213       struct T0oT1oT2_define
08214       {
08215          typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0;
08216          typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1;
08217          typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type;
08218          typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node;
08219       };
08220 
08221       template <typename T, typename T0, typename T1, typename T2, typename T3>
08222       struct T0oT1oT2oT3_define
08223       {
08224          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0;
08225          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1;
08226          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2;
08227          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3;
08228          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4;
08229          typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type;
08230       };
08231 
08232       template <typename T, typename Operation>
08233       class vov_node : public vov_base_node<T>
08234       {
08235       public:
08236 
08237          typedef expression_node<T>* expression_ptr;
08238          typedef Operation operation_t;
08239 
08240          // variable op variable node
08241          explicit vov_node(const T& v0, const T& v1)
08242          : v0_(v0),
08243            v1_(v1)
08244          {}
08245 
08246          inline T value() const
08247          {
08248             return Operation::process(v0_,v1_);
08249          }
08250 
08251          inline typename expression_node<T>::node_type type() const
08252          {
08253             return Operation::type();
08254          }
08255 
08256          inline operator_type operation() const
08257          {
08258             return Operation::operation();
08259          }
08260 
08261          inline const T& v0() const
08262          {
08263             return v0_;
08264          }
08265 
08266          inline const T& v1() const
08267          {
08268             return v1_;
08269          }
08270 
08271       protected:
08272 
08273          const T& v0_;
08274          const T& v1_;
08275 
08276       private:
08277 
08278          vov_node(vov_node<T,Operation>&);
08279          vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
08280       };
08281 
08282       template <typename T, typename Operation>
08283       class cov_node : public cov_base_node<T>
08284       {
08285       public:
08286 
08287          typedef expression_node<T>* expression_ptr;
08288          typedef Operation operation_t;
08289 
08290          // constant op variable node
08291          explicit cov_node(const T& c, const T& v)
08292          : c_(c),
08293            v_(v)
08294          {}
08295 
08296          inline T value() const
08297          {
08298             return Operation::process(c_,v_);
08299          }
08300 
08301          inline typename expression_node<T>::node_type type() const
08302          {
08303             return Operation::type();
08304          }
08305 
08306          inline operator_type operation() const
08307          {
08308             return Operation::operation();
08309          }
08310 
08311          inline const T c() const
08312          {
08313             return c_;
08314          }
08315 
08316          inline const T& v() const
08317          {
08318             return v_;
08319          }
08320 
08321       protected:
08322 
08323          const T  c_;
08324          const T& v_;
08325 
08326       private:
08327 
08328          cov_node(const cov_node<T,Operation>&);
08329          cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
08330       };
08331 
08332       template <typename T, typename Operation>
08333       class voc_node : public voc_base_node<T>
08334       {
08335       public:
08336 
08337          typedef expression_node<T>* expression_ptr;
08338          typedef Operation operation_t;
08339 
08340          // variable op constant node
08341          explicit voc_node(const T& v, const T& c)
08342          : v_(v),
08343            c_(c)
08344          {}
08345 
08346          inline T value() const
08347          {
08348             return Operation::process(v_,c_);
08349          }
08350 
08351          inline operator_type operation() const
08352          {
08353             return Operation::operation();
08354          }
08355 
08356          inline const T c() const
08357          {
08358             return c_;
08359          }
08360 
08361          inline const T& v() const
08362          {
08363             return v_;
08364          }
08365 
08366       protected:
08367 
08368          const T& v_;
08369          const T  c_;
08370 
08371       private:
08372 
08373          voc_node(const voc_node<T,Operation>&);
08374          voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
08375       };
08376 
08377       template <typename T, typename Operation>
08378       class vob_node : public vob_base_node<T>
08379       {
08380       public:
08381 
08382          typedef expression_node<T>* expression_ptr;
08383          typedef std::pair<expression_ptr,bool> branch_t;
08384          typedef Operation operation_t;
08385 
08386          // variable op constant node
08387          explicit vob_node(const T& v, const expression_ptr branch)
08388          : v_(v)
08389          {
08390             init_branches<1>(branch_,branch);
08391          }
08392 
08393         ~vob_node()
08394          {
08395             cleanup_branches<T,1>::execute(branch_);
08396          }
08397 
08398          inline T value() const
08399          {
08400             return Operation::process(v_,branch_[0].first->value());
08401          }
08402 
08403          inline operator_type operation() const
08404          {
08405             return Operation::operation();
08406          }
08407 
08408          inline const T& v() const
08409          {
08410             return v_;
08411          }
08412 
08413          inline expression_node<T>* branch(const std::size_t&) const
08414          {
08415             return branch_[0].first;
08416          }
08417 
08418       private:
08419 
08420          vob_node(const vob_node<T,Operation>&);
08421          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
08422 
08423          const T& v_;
08424          branch_t branch_[1];
08425       };
08426 
08427       template <typename T, typename Operation>
08428       class bov_node : public bov_base_node<T>
08429       {
08430       public:
08431 
08432          typedef expression_node<T>* expression_ptr;
08433          typedef std::pair<expression_ptr,bool> branch_t;
08434          typedef Operation operation_t;
08435 
08436          // variable op constant node
08437          explicit bov_node(const expression_ptr branch, const T& v)
08438          : v_(v)
08439          {
08440             init_branches<1>(branch_,branch);
08441          }
08442 
08443         ~bov_node()
08444          {
08445             cleanup_branches<T,1>::execute(branch_);
08446          }
08447 
08448          inline T value() const
08449          {
08450             return Operation::process(branch_[0].first->value(),v_);
08451          }
08452 
08453          inline operator_type operation() const
08454          {
08455             return Operation::operation();
08456          }
08457 
08458          inline const T& v() const
08459          {
08460             return v_;
08461          }
08462 
08463          inline expression_node<T>* branch(const std::size_t&) const
08464          {
08465             return branch_[0].first;
08466          }
08467 
08468       private:
08469 
08470          bov_node(const bov_node<T,Operation>&);
08471          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
08472 
08473          const T& v_;
08474          branch_t branch_[1];
08475       };
08476 
08477       template <typename T, typename Operation>
08478       class cob_node : public cob_base_node<T>
08479       {
08480       public:
08481 
08482          typedef expression_node<T>* expression_ptr;
08483          typedef std::pair<expression_ptr,bool> branch_t;
08484          typedef Operation operation_t;
08485 
08486          // variable op constant node
08487          explicit cob_node(const T c, const expression_ptr branch)
08488          : c_(c)
08489          {
08490             init_branches<1>(branch_,branch);
08491          }
08492 
08493         ~cob_node()
08494          {
08495             cleanup_branches<T,1>::execute(branch_);
08496          }
08497 
08498          inline T value() const
08499          {
08500             return Operation::process(c_,branch_[0].first->value());
08501          }
08502 
08503          inline operator_type operation() const
08504          {
08505             return Operation::operation();
08506          }
08507 
08508          inline const T c() const
08509          {
08510             return c_;
08511          }
08512 
08513          inline void set_c(const T new_c)
08514          {
08515             (*const_cast<T*>(&c_)) = new_c;
08516          }
08517 
08518          inline expression_node<T>* branch(const std::size_t&) const
08519          {
08520             return branch_[0].first;
08521          }
08522 
08523          inline expression_node<T>* move_branch(const std::size_t&)
08524          {
08525             branch_[0].second = false;
08526             return branch_[0].first;
08527          }
08528 
08529       private:
08530 
08531          cob_node(const cob_node<T,Operation>&);
08532          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
08533 
08534          const T c_;
08535          branch_t branch_[1];
08536       };
08537 
08538       template <typename T, typename Operation>
08539       class boc_node : public boc_base_node<T>
08540       {
08541       public:
08542 
08543          typedef expression_node<T>* expression_ptr;
08544          typedef std::pair<expression_ptr,bool> branch_t;
08545          typedef Operation operation_t;
08546 
08547          // variable op constant node
08548          explicit boc_node(const expression_ptr branch, const T c)
08549          : c_(c)
08550          {
08551             init_branches<1>(branch_,branch);
08552          }
08553 
08554         ~boc_node()
08555          {
08556             cleanup_branches<T,1>::execute(branch_);
08557          }
08558 
08559          inline T value() const
08560          {
08561             return Operation::process(branch_[0].first->value(),c_);
08562          }
08563 
08564          inline operator_type operation() const
08565          {
08566             return Operation::operation();
08567          }
08568 
08569          inline const T c() const
08570          {
08571             return c_;
08572          }
08573 
08574          inline void set_c(const T new_c)
08575          {
08576             (*const_cast<T*>(&c_)) = new_c;
08577          }
08578 
08579          inline expression_node<T>* branch(const std::size_t&) const
08580          {
08581             return branch_[0].first;
08582          }
08583 
08584       private:
08585 
08586          boc_node(const boc_node<T,Operation>&);
08587          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
08588 
08589          const T c_;
08590          branch_t branch_[1];
08591       };
08592 
08593       #ifndef exprtk_disable_string_capabilities
08594       template <typename T, typename SType0, typename SType1, typename Operation>
08595       class sos_node : public sos_base_node<T>
08596       {
08597       public:
08598 
08599          typedef expression_node<T>* expression_ptr;
08600          typedef Operation operation_t;
08601 
08602          // string op string node
08603          explicit sos_node(SType0 s0, SType1 s1)
08604          : s0_(s0),
08605            s1_(s1)
08606          {}
08607 
08608          inline T value() const
08609          {
08610             return Operation::process(s0_,s1_);
08611          }
08612 
08613          inline typename expression_node<T>::node_type type() const
08614          {
08615             return Operation::type();
08616          }
08617 
08618          inline operator_type operation() const
08619          {
08620             return Operation::operation();
08621          }
08622 
08623          inline std::string& s0()
08624          {
08625             return s0_;
08626          }
08627 
08628          inline std::string& s1()
08629          {
08630             return s1_;
08631          }
08632 
08633       protected:
08634 
08635          SType0 s0_;
08636          SType1 s1_;
08637 
08638       private:
08639 
08640          sos_node(sos_node<T,SType0,SType1,Operation>&);
08641          sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
08642       };
08643 
08644       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
08645       class str_xrox_node : public sos_base_node<T>
08646       {
08647       public:
08648 
08649          typedef expression_node<T>* expression_ptr;
08650          typedef Operation operation_t;
08651 
08652          // string-range op string node
08653          explicit str_xrox_node(SType0 s0, SType1 s1, RangePack rp0)
08654          : s0_(s0),
08655            s1_(s1),
08656            rp0_(rp0)
08657          {}
08658 
08659         ~str_xrox_node()
08660          {
08661             rp0_.free();
08662          }
08663 
08664          inline T value() const
08665          {
08666             std::size_t r0 = 0;
08667             std::size_t r1 = 0;
08668             if (rp0_(r0,r1,s0_.size()))
08669                return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_);
08670             else
08671                return T(0);
08672          }
08673 
08674          inline typename expression_node<T>::node_type type() const
08675          {
08676             return Operation::type();
08677          }
08678 
08679          inline operator_type operation() const
08680          {
08681             return Operation::operation();
08682          }
08683 
08684          inline std::string& s0()
08685          {
08686             return s0_;
08687          }
08688 
08689          inline std::string& s1()
08690          {
08691             return s1_;
08692          }
08693 
08694       protected:
08695 
08696          SType0    s0_;
08697          SType1    s1_;
08698          RangePack rp0_;
08699 
08700       private:
08701 
08702          str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
08703          str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
08704       };
08705 
08706       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
08707       class str_xoxr_node : public sos_base_node<T>
08708       {
08709       public:
08710 
08711          typedef expression_node<T>* expression_ptr;
08712          typedef Operation operation_t;
08713 
08714          // string op string range node
08715          explicit str_xoxr_node(SType0 s0, SType1 s1, RangePack rp1)
08716          : s0_(s0),
08717            s1_(s1),
08718            rp1_(rp1)
08719          {}
08720 
08721         ~str_xoxr_node()
08722          {
08723             rp1_.free();
08724          }
08725 
08726          inline T value() const
08727          {
08728             std::size_t r0 = 0;
08729             std::size_t r1 = 0;
08730             if (rp1_(r0,r1,s1_.size()))
08731                return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1));
08732             else
08733                return T(0);
08734          }
08735 
08736          inline typename expression_node<T>::node_type type() const
08737          {
08738             return Operation::type();
08739          }
08740 
08741          inline operator_type operation() const
08742          {
08743             return Operation::operation();
08744          }
08745 
08746          inline std::string& s0()
08747          {
08748             return s0_;
08749          }
08750 
08751          inline std::string& s1()
08752          {
08753             return s1_;
08754          }
08755 
08756       protected:
08757 
08758          SType0    s0_;
08759          SType1    s1_;
08760          RangePack rp1_;
08761 
08762       private:
08763 
08764          str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
08765          str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
08766       };
08767 
08768       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
08769       class str_xroxr_node : public sos_base_node<T>
08770       {
08771       public:
08772 
08773          typedef expression_node<T>* expression_ptr;
08774          typedef Operation operation_t;
08775 
08776          // string-range op string-range node
08777          explicit str_xroxr_node(SType0 s0, SType1 s1, RangePack rp0, RangePack rp1)
08778          : s0_(s0),
08779            s1_(s1),
08780            rp0_(rp0),
08781            rp1_(rp1)
08782          {}
08783 
08784         ~str_xroxr_node()
08785          {
08786             rp0_.free();
08787             rp1_.free();
08788          }
08789 
08790          inline T value() const
08791          {
08792             std::size_t r0_0 = 0;
08793             std::size_t r0_1 = 0;
08794             std::size_t r1_0 = 0;
08795             std::size_t r1_1 = 0;
08796             if (rp0_(r0_0,r1_0,s0_.size()) && rp1_(r0_1,r1_1,s1_.size()))
08797                return Operation::process(s0_.substr(r0_0,(r1_0 - r0_0) + 1),
08798                                          s1_.substr(r0_1,(r1_1 - r0_1) + 1));
08799             else
08800                return T(0);
08801          }
08802 
08803          inline typename expression_node<T>::node_type type() const
08804          {
08805             return Operation::type();
08806          }
08807 
08808          inline operator_type operation() const
08809          {
08810             return Operation::operation();
08811          }
08812 
08813          inline std::string& s0()
08814          {
08815             return s0_;
08816          }
08817 
08818          inline std::string& s1()
08819          {
08820             return s1_;
08821          }
08822 
08823       protected:
08824 
08825          SType0    s0_;
08826          SType1    s1_;
08827          RangePack rp0_;
08828          RangePack rp1_;
08829 
08830       private:
08831 
08832          str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
08833          str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
08834       };
08835 
08836       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
08837       class sosos_node : public sosos_base_node<T>
08838       {
08839       public:
08840 
08841          typedef expression_node<T>* expression_ptr;
08842          typedef Operation operation_t;
08843 
08844          // variable op variable node
08845          explicit sosos_node(SType0 s0, SType1 s1, SType2 s2)
08846          : s0_(s0),
08847            s1_(s1),
08848            s2_(s2)
08849          {}
08850 
08851          inline T value() const
08852          {
08853             return Operation::process(s0_,s1_,s2_);
08854          }
08855 
08856          inline typename expression_node<T>::node_type type() const
08857          {
08858             return Operation::type();
08859          }
08860 
08861          inline operator_type operation() const
08862          {
08863             return Operation::operation();
08864          }
08865 
08866          inline std::string& s0()
08867          {
08868             return s0_;
08869          }
08870 
08871          inline std::string& s1()
08872          {
08873             return s1_;
08874          }
08875 
08876          inline std::string& s2()
08877          {
08878             return s2_;
08879          }
08880 
08881       protected:
08882 
08883          SType0 s0_;
08884          SType1 s1_;
08885          SType2 s2_;
08886 
08887       private:
08888 
08889          sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
08890          sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
08891       };
08892       #endif
08893 
08894       template <typename T, typename PowOp>
08895       class ipow_node : public expression_node<T>
08896       {
08897       public:
08898 
08899          typedef expression_node<T>* expression_ptr;
08900          typedef PowOp operation_t;
08901 
08902          explicit ipow_node(const T& v)
08903          : v_(v)
08904          {}
08905 
08906          inline T value() const
08907          {
08908             return PowOp::result(v_);
08909          }
08910 
08911          inline typename expression_node<T>::node_type type() const
08912          {
08913             return expression_node<T>::e_ipow;
08914          }
08915 
08916       private:
08917 
08918          ipow_node(const ipow_node<T,PowOp>&);
08919          ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
08920 
08921          const T& v_;
08922       };
08923 
08924       template <typename T, typename PowOp>
08925       class ipowinv_node : public expression_node<T>
08926       {
08927       public:
08928 
08929          typedef expression_node<T>* expression_ptr;
08930          typedef PowOp operation_t;
08931 
08932          explicit ipowinv_node(const T& v)
08933          : v_(v)
08934          {}
08935 
08936          inline T value() const
08937          {
08938             return (T(1) / PowOp::result(v_));
08939          }
08940 
08941          inline typename expression_node<T>::node_type type() const
08942          {
08943             return expression_node<T>::e_ipowinv;
08944          }
08945 
08946       private:
08947 
08948          ipowinv_node(const ipowinv_node<T,PowOp>&);
08949          ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
08950 
08951          const T& v_;
08952       };
08953 
08954       template <typename T>
08955       inline bool is_vov_node(const expression_node<T>* node)
08956       {
08957          return (0 != dynamic_cast<const vov_base_node<T>*>(node));
08958       }
08959 
08960       template <typename T>
08961       inline bool is_cov_node(const expression_node<T>* node)
08962       {
08963          return (0 != dynamic_cast<const cov_base_node<T>*>(node));
08964       }
08965 
08966       template <typename T>
08967       inline bool is_voc_node(const expression_node<T>* node)
08968       {
08969          return (0 != dynamic_cast<const voc_base_node<T>*>(node));
08970       }
08971 
08972       template <typename T>
08973       inline bool is_cob_node(const expression_node<T>* node)
08974       {
08975          return (0 != dynamic_cast<const cob_base_node<T>*>(node));
08976       }
08977 
08978       template <typename T>
08979       inline bool is_boc_node(const expression_node<T>* node)
08980       {
08981          return (0 != dynamic_cast<const boc_base_node<T>*>(node));
08982       }
08983 
08984       template <typename T>
08985       inline bool is_t0ot1ot2_node(const expression_node<T>* node)
08986       {
08987          return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
08988       }
08989 
08990       template <typename T>
08991       inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
08992       {
08993          return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
08994       }
08995 
08996       template <typename T>
08997       inline bool is_uv_node(const expression_node<T>* node)
08998       {
08999          return (0 != dynamic_cast<const uv_base_node<T>*>(node));
09000       }
09001 
09002       template <typename T>
09003       inline bool is_string_node(const expression_node<T>* node)
09004       {
09005          return (expression_node<T>::e_stringvar == node->type());
09006       }
09007 
09008       template <typename T>
09009       inline bool is_string_range_node(const expression_node<T>* node)
09010       {
09011          return (expression_node<T>::e_stringvarrng == node->type());
09012       }
09013 
09014       template <typename T>
09015       inline bool is_const_string_node(const expression_node<T>* node)
09016       {
09017          return (expression_node<T>::e_stringconst == node->type());
09018       }
09019 
09020       template <typename T>
09021       inline bool is_const_string_range_node(const expression_node<T>* node)
09022       {
09023          return (expression_node<T>::e_cstringvarrng == node->type());
09024       }
09025 
09026       template <typename T>
09027       inline bool is_generally_string_node(const expression_node<T>* node)
09028       {
09029          return is_string_node            (node) ||
09030                 is_const_string_node      (node) ||
09031                 is_string_range_node      (node) ||
09032                 is_const_string_range_node(node);
09033       }
09034 
09035       class node_allocator
09036       {
09037       public:
09038 
09039          template <typename ResultNode, typename OpType, typename ExprNode>
09040          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
09041          {
09042             return allocate<ResultNode>(operation,branch[0]);
09043          }
09044 
09045          template <typename ResultNode, typename OpType, typename ExprNode>
09046          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
09047          {
09048             return allocate<ResultNode>(operation,branch[0],branch[1]);
09049          }
09050 
09051          template <typename ResultNode, typename OpType, typename ExprNode>
09052          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
09053          {
09054             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
09055          }
09056 
09057          template <typename ResultNode, typename OpType, typename ExprNode>
09058          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
09059          {
09060             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
09061          }
09062 
09063          template <typename ResultNode, typename OpType, typename ExprNode>
09064          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
09065          {
09066             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
09067          }
09068 
09069          template <typename ResultNode, typename OpType, typename ExprNode>
09070          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
09071          {
09072             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
09073          }
09074 
09075          template <typename node_type>
09076          inline expression_node<typename node_type::value_type>* allocate() const
09077          {
09078             return new node_type();
09079          }
09080 
09081          template <typename node_type,
09082                    typename Type,
09083                    typename Allocator,
09084                    template<typename,typename> class Sequence>
09085          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
09086          {
09087             return new node_type(seq);
09088          }
09089 
09090          template <typename node_type, typename T1>
09091          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
09092          {
09093             return new node_type(t1);
09094          }
09095 
09096          template <typename node_type, typename T1>
09097          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
09098          {
09099             return new node_type(t1);
09100          }
09101 
09102          template <typename node_type,
09103                    typename T1, typename T2>
09104          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
09105          {
09106             return new node_type(t1,t2);
09107          }
09108 
09109          template <typename node_type,
09110                    typename T1, typename T2>
09111          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
09112          {
09113             return new node_type(t1,t2);
09114          }
09115 
09116          template <typename node_type,
09117                    typename T1, typename T2>
09118          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
09119          {
09120             return new node_type(t1,t2);
09121          }
09122 
09123          template <typename node_type,
09124                    typename T1, typename T2>
09125          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
09126          {
09127             return new node_type(t1,t2);
09128          }
09129 
09130          template <typename node_type,
09131                    typename T1, typename T2>
09132          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
09133          {
09134             return new node_type(t1,t2);
09135          }
09136 
09137          template <typename node_type,
09138                    typename T1, typename T2, typename T3>
09139          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
09140          {
09141             return new node_type(t1,t2,t3);
09142          }
09143 
09144          template <typename node_type,
09145                    typename T1, typename T2, typename T3, typename T4>
09146          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
09147          {
09148             return new node_type(t1,t2,t3,t4);
09149          }
09150 
09151          template <typename node_type,
09152                    typename T1, typename T2, typename T3>
09153          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
09154          {
09155             return new node_type(t1,t2,t3);
09156          }
09157 
09158          template <typename node_type,
09159                    typename T1, typename T2, typename T3, typename T4>
09160          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
09161          {
09162             return new node_type(t1,t2,t3,t4);
09163          }
09164 
09165          template <typename node_type,
09166                    typename T1, typename T2, typename T3, typename T4, typename T5>
09167          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
09168          {
09169             return new node_type(t1,t2,t3,t4,t5);
09170          }
09171 
09172          template <typename node_type,
09173                    typename T1, typename T2, typename T3>
09174          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09175                                                                           const T3& t3) const
09176          {
09177             return new node_type(t1,t2,t3);
09178          }
09179 
09180          template <typename node_type,
09181                    typename T1, typename T2,
09182                    typename T3, typename T4>
09183          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09184                                                                           const T3& t3, const T4& t4) const
09185          {
09186             return new node_type(t1,t2,t3,t4);
09187          }
09188 
09189          template <typename node_type,
09190                    typename T1, typename T2,
09191                    typename T3, typename T4, typename T5>
09192          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09193                                                                           const T3& t3, const T4& t4,
09194                                                                           const T5& t5) const
09195          {
09196             return new node_type(t1,t2,t3,t4,t5);
09197          }
09198 
09199          template <typename node_type,
09200                    typename T1, typename T2,
09201                    typename T3, typename T4, typename T5, typename T6>
09202          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09203                                                                           const T3& t3, const T4& t4,
09204                                                                           const T5& t5, const T6& t6) const
09205          {
09206             return new node_type(t1,t2,t3,t4,t5,t6);
09207          }
09208 
09209          template <typename node_type,
09210                    typename T1, typename T2,
09211                    typename T3, typename T4,
09212                    typename T5, typename T6, typename T7>
09213          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09214                                                                           const T3& t3, const T4& t4,
09215                                                                           const T5& t5, const T6& t6,
09216                                                                           const T7& t7) const
09217          {
09218             return new node_type(t1,t2,t3,t4,t5,t6,t7);
09219          }
09220 
09221          template <typename node_type,
09222                    typename T1, typename T2,
09223                    typename T3, typename T4,
09224                    typename T5, typename T6,
09225                    typename T7, typename T8>
09226          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09227                                                                           const T3& t3, const T4& t4,
09228                                                                           const T5& t5, const T6& t6,
09229                                                                           const T7& t7, const T8& t8) const
09230          {
09231             return new node_type(t1,t2,t3,t4,t5,t6,t7,t8);
09232          }
09233 
09234          template <typename node_type,
09235                    typename T1, typename T2,
09236                    typename T3, typename T4,
09237                    typename T5, typename T6,
09238                    typename T7, typename T8, typename T9>
09239          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09240                                                                           const T3& t3, const T4& t4,
09241                                                                           const T5& t5, const T6& t6,
09242                                                                           const T7& t7, const T8& t8,
09243                                                                           const T9& t9) const
09244          {
09245             return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
09246          }
09247 
09248          template <typename node_type,
09249                    typename T1, typename T2,
09250                    typename T3, typename T4,
09251                    typename T5, typename T6,
09252                    typename T7, typename T8,
09253                    typename T9, typename T10>
09254          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
09255                                                                           const T3& t3, const  T4&  t4,
09256                                                                           const T5& t5, const  T6&  t6,
09257                                                                           const T7& t7, const  T8&  t8,
09258                                                                           const T9& t9, const T10& t10) const
09259          {
09260             return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10);
09261          }
09262 
09263          template <typename node_type,
09264                    typename T1, typename T2, typename T3>
09265          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
09266          {
09267             return new node_type(t1,t2,t3);
09268          }
09269 
09270          template <typename node_type,
09271                    typename T1, typename T2,
09272                    typename T3, typename T4>
09273          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
09274                                                                                T3 t3, T4 t4) const
09275          {
09276             return new node_type(t1,t2,t3,t4);
09277          }
09278 
09279          template <typename node_type,
09280                    typename T1, typename T2,
09281                    typename T3, typename T4,
09282                    typename T5>
09283          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
09284                                                                                T3 t3, T4 t4,
09285                                                                                T5 t5) const
09286          {
09287             return new node_type(t1,t2,t3,t4,t5);
09288          }
09289 
09290          template <typename node_type,
09291                    typename T1, typename T2,
09292                    typename T3, typename T4,
09293                    typename T5, typename T6, typename T7>
09294          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
09295                                                                                T3 t3, T4 t4,
09296                                                                                T5 t5, T6 t6,
09297                                                                                T7 t7) const
09298          {
09299             return new node_type(t1,t2,t3,t4,t5,t6,t7);
09300          }
09301 
09302          template <typename T>
09303          void inline free(expression_node<T>*& e) const
09304          {
09305             delete e;
09306             e = 0;
09307          }
09308       };
09309 
09310       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
09311       {
09312          #define register_op(Symbol,Type,Args)                                               \
09313          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
09314 
09315          register_op(      "abs",e_abs     , 1)
09316          register_op(     "acos",e_acos    , 1)
09317          register_op(    "acosh",e_acosh   , 1)
09318          register_op(     "asin",e_asin    , 1)
09319          register_op(    "asinh",e_asinh   , 1)
09320          register_op(     "atan",e_atan    , 1)
09321          register_op(    "atanh",e_atanh   , 1)
09322          register_op(     "ceil",e_ceil    , 1)
09323          register_op(      "cos",e_cos     , 1)
09324          register_op(     "cosh",e_cosh    , 1)
09325          register_op(      "exp",e_exp     , 1)
09326          register_op(    "expm1",e_expm1   , 1)
09327          register_op(    "floor",e_floor   , 1)
09328          register_op(      "log",e_log     , 1)
09329          register_op(    "log10",e_log10   , 1)
09330          register_op(     "log2",e_log2    , 1)
09331          register_op(    "log1p",e_log1p   , 1)
09332          register_op(    "round",e_round   , 1)
09333          register_op(      "sin",e_sin     , 1)
09334          register_op(     "sinc",e_sinc    , 1)
09335          register_op(     "sinh",e_sinh    , 1)
09336          register_op(      "sec",e_sec     , 1)
09337          register_op(      "csc",e_csc     , 1)
09338          register_op(     "sqrt",e_sqrt    , 1)
09339          register_op(      "tan",e_tan     , 1)
09340          register_op(     "tanh",e_tanh    , 1)
09341          register_op(      "cot",e_cot     , 1)
09342          register_op(  "rad2deg",e_r2d     , 1)
09343          register_op(  "deg2rad",e_d2r     , 1)
09344          register_op( "deg2grad",e_d2g     , 1)
09345          register_op( "grad2deg",e_g2d     , 1)
09346          register_op(      "sgn",e_sgn     , 1)
09347          register_op(      "not",e_notl    , 1)
09348          register_op(      "erf",e_erf     , 1)
09349          register_op(     "erfc",e_erfc    , 1)
09350          register_op(     "frac",e_frac    , 1)
09351          register_op(    "trunc",e_trunc   , 1)
09352          register_op(    "atan2",e_atan2   , 2)
09353          register_op(      "mod",e_mod     , 2)
09354          register_op(     "logn",e_logn    , 2)
09355          register_op(      "pow",e_pow     , 2)
09356          register_op(     "root",e_root    , 2)
09357          register_op(   "roundn",e_roundn  , 2)
09358          register_op(    "equal",e_equal   , 2)
09359          register_op("not_equal",e_nequal  , 2)
09360          register_op(    "hypot",e_hypot   , 2)
09361          register_op(      "shr",e_shr     , 2)
09362          register_op(      "shl",e_shl     , 2)
09363          register_op(    "clamp",e_clamp   , 3)
09364          register_op(   "iclamp",e_iclamp  , 3)
09365          register_op(  "inrange",e_inrange , 3)
09366          #undef register_op
09367       }
09368 
09369    } // namespace details
09370 
09371    template <typename T>
09372    class ifunction
09373    {
09374    public:
09375 
09376       explicit ifunction(const std::size_t& pc, const bool hse = true)
09377       : param_count(pc),
09378         has_side_effects(hse)
09379       {}
09380 
09381       virtual ~ifunction()
09382       {}
09383 
09384       std::size_t param_count;
09385       bool has_side_effects;
09386 
09387       inline virtual T operator()()
09388       {
09389          return std::numeric_limits<T>::quiet_NaN();
09390       }
09391 
09392       inline virtual T operator()(const T&)
09393       {
09394          return std::numeric_limits<T>::quiet_NaN();
09395       }
09396 
09397       inline virtual T operator()(const T&,const T&)
09398       {
09399          return std::numeric_limits<T>::quiet_NaN();
09400       }
09401 
09402       inline virtual T operator()(const T&, const T&, const T&)
09403       {
09404          return std::numeric_limits<T>::quiet_NaN();
09405       }
09406 
09407       inline virtual T operator()(const T&, const T&, const T&, const T&)
09408       {
09409          return std::numeric_limits<T>::quiet_NaN();
09410       }
09411 
09412       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
09413       {
09414          return std::numeric_limits<T>::quiet_NaN();
09415       }
09416 
09417       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
09418       {
09419          return std::numeric_limits<T>::quiet_NaN();
09420       }
09421 
09422       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09423       {
09424          return std::numeric_limits<T>::quiet_NaN();
09425       }
09426 
09427       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09428       {
09429          return std::numeric_limits<T>::quiet_NaN();
09430       }
09431 
09432       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09433       {
09434          return std::numeric_limits<T>::quiet_NaN();
09435       }
09436 
09437       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09438       {
09439          return std::numeric_limits<T>::quiet_NaN();
09440       }
09441 
09442       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09443                                   const T&)
09444       {
09445          return std::numeric_limits<T>::quiet_NaN();
09446       }
09447 
09448       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09449                                   const T&, const T&)
09450       {
09451          return std::numeric_limits<T>::quiet_NaN();
09452       }
09453 
09454       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09455                                   const T&, const T&, const T&)
09456       {
09457          return std::numeric_limits<T>::quiet_NaN();
09458       }
09459 
09460       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09461                                   const T&, const T&, const T&, const T&)
09462       {
09463          return std::numeric_limits<T>::quiet_NaN();
09464       }
09465 
09466       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09467                                   const T&, const T&, const T&, const T&, const T&)
09468       {
09469          return std::numeric_limits<T>::quiet_NaN();
09470       }
09471 
09472       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09473                                   const T&, const T&, const T&, const T&, const T&, const T&)
09474       {
09475          return std::numeric_limits<T>::quiet_NaN();
09476       }
09477 
09478       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09479                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09480       {
09481          return std::numeric_limits<T>::quiet_NaN();
09482       }
09483 
09484       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09485                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09486       {
09487          return std::numeric_limits<T>::quiet_NaN();
09488       }
09489 
09490       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09491                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09492       {
09493          return std::numeric_limits<T>::quiet_NaN();
09494       }
09495 
09496       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09497                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09498       {
09499          return std::numeric_limits<T>::quiet_NaN();
09500       }
09501    };
09502 
09503    template <typename T>
09504    class ivararg_function
09505    {
09506    public:
09507 
09508       virtual ~ivararg_function()
09509       {}
09510 
09511       inline virtual T operator()(const std::vector<T>&)
09512       {
09513          return std::numeric_limits<T>::quiet_NaN();
09514       }
09515    };
09516 
09517    template <typename T> class parser;
09518    template <typename T> class expression_helper;
09519 
09520    template <typename T>
09521    class symbol_table
09522    {
09523    protected:
09524 
09525       template <typename Type> class parser;
09526 
09527       template <typename Type>
09528       class vector_holder
09529       {
09530       private:
09531 
09532          typedef Type value_type;
09533          typedef value_type* value_ptr;
09534          typedef const value_ptr const_value_ptr;
09535 
09536          class vector_holder_base
09537          {
09538          public:
09539 
09540             virtual ~vector_holder_base(){}
09541 
09542             inline value_ptr operator[](const std::size_t& index) const
09543             {
09544                return value_at(index);
09545             }
09546 
09547             inline std::size_t size() const
09548             {
09549                return vector_size();
09550             }
09551 
09552          protected:
09553 
09554             virtual value_ptr value_at(const std::size_t&) const = 0;
09555             virtual std::size_t vector_size()              const = 0;
09556          };
09557 
09558          class array_vector_impl : public vector_holder_base
09559          {
09560          public:
09561 
09562             array_vector_impl(const T* vec, const std::size_t& vec_size)
09563             : vec_(vec),
09564               size_(vec_size)
09565             {}
09566 
09567          protected:
09568 
09569             value_ptr value_at(const std::size_t& index) const
09570             {
09571                if (index < size_)
09572                   return const_cast<const_value_ptr>(vec_ + index);
09573                else
09574                   return const_value_ptr(0);
09575             }
09576 
09577             std::size_t vector_size() const
09578             {
09579                return size_;
09580             }
09581 
09582          private:
09583 
09584             array_vector_impl operator=(const array_vector_impl&);
09585 
09586             const T* vec_;
09587             const std::size_t size_;
09588          };
09589 
09590          template <typename Allocator,
09591                    template <typename,typename> class Sequence>
09592          class sequence_vector_impl : public vector_holder_base
09593          {
09594          public:
09595 
09596             typedef Sequence<Type,Allocator> sequence_t;
09597 
09598             sequence_vector_impl(sequence_t& seq)
09599             : sequence_(seq)
09600             {}
09601 
09602          protected:
09603 
09604             value_ptr value_at(const std::size_t& index) const
09605             {
09606                return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
09607             }
09608 
09609             std::size_t vector_size() const
09610             {
09611                return sequence_.size();
09612             }
09613 
09614          private:
09615 
09616             sequence_vector_impl operator=(const sequence_vector_impl&);
09617 
09618             sequence_t& sequence_;
09619          };
09620 
09621       public:
09622 
09623          vector_holder(Type* vec, const std::size_t& vec_size)
09624          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
09625          {}
09626 
09627          template <typename Allocator>
09628          vector_holder(std::vector<Type,Allocator>& vec)
09629          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
09630          {}
09631 
09632          template <typename Allocator>
09633          vector_holder(std::deque<Type,Allocator>& deq)
09634          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::deque>(deq))
09635          {}
09636 
09637          inline value_ptr operator[](const std::size_t& index) const
09638          {
09639             return (*vector_holder_base_)[index];
09640          }
09641 
09642          inline std::size_t size() const
09643          {
09644             return vector_holder_base_->size();
09645          }
09646 
09647       private:
09648 
09649          mutable vector_holder_base* vector_holder_base_;
09650          unsigned char buffer[64];
09651       };
09652 
09653    protected:
09654 
09655       template <typename Type, typename RawType>
09656       struct type_store
09657       {
09658          typedef typename details::variable_node<T>  variable_node_t;
09659          typedef ifunction<T>                        ifunction_t;
09660          typedef ivararg_function<T>                 ivararg_function_t;
09661          typedef vector_holder<T>                    vector_t;
09662          #ifndef exprtk_disable_string_capabilities
09663          typedef typename details::stringvar_node<T> stringvar_node_t;
09664          #endif
09665 
09666          typedef Type type_t;
09667          typedef type_t* type_ptr;
09668          typedef std::pair<bool,type_ptr> type_pair_t;
09669          typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
09670          typedef typename type_map_t::iterator tm_itr_t;
09671          typedef typename type_map_t::const_iterator tm_const_itr_t;
09672 
09673          enum { lut_size = 256 };
09674 
09675          type_map_t  map;
09676          std::size_t size;
09677 
09678          type_store()
09679          : size(0)
09680          {}
09681 
09682          inline bool symbol_exists(const std::string& symbol_name) const
09683          {
09684             if (symbol_name.empty())
09685                return false;
09686             else if (map.end() != map.find(symbol_name))
09687                return true;
09688             else
09689                return false;
09690          }
09691 
09692          inline bool is_constant(const std::string& symbol_name) const
09693          {
09694             if (symbol_name.empty())
09695                return false;
09696             else
09697             {
09698                tm_const_itr_t itr = map.find(symbol_name);
09699                if (map.end() == itr)
09700                   return false;
09701                else
09702                   return (*itr).second.first;
09703             }
09704          }
09705 
09706          template <typename Tie, typename RType>
09707          inline bool add_impl(const std::string& symbol_name, RType t, const bool is_constant)
09708          {
09709             if (symbol_name.size() > 1)
09710             {
09711                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
09712                {
09713                   if (details::imatch(symbol_name,details::reserved_symbols[i]))
09714                   {
09715                      return false;
09716                   }
09717                }
09718             }
09719 
09720             tm_itr_t itr = map.find(symbol_name);
09721 
09722             if (map.end() == itr)
09723             {
09724                map[symbol_name] = Tie::make(t,is_constant);
09725                ++size;
09726             }
09727             return true;
09728          }
09729 
09730          struct tie_array
09731          {
09732             static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_constant = false)
09733             {
09734                return std::make_pair(is_constant,new vector_t(v.first,v.second));
09735             }
09736          };
09737 
09738          struct tie_stdvec
09739          {
09740             template <typename Allocator>
09741             static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_constant = false)
09742             {
09743                return std::make_pair(is_constant,new vector_t(v));
09744             }
09745          };
09746 
09747          struct tie_stddeq
09748          {
09749             template <typename Allocator>
09750             static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_constant = false)
09751             {
09752                return std::make_pair(is_constant,new vector_t(v));
09753             }
09754          };
09755 
09756          template <std::size_t v_size>
09757          inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_constant = false)
09758          {
09759             return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_constant);
09760          }
09761 
09762          template <typename Allocator>
09763          inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_constant = false)
09764          {
09765             return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_constant);
09766          }
09767 
09768          template <typename Allocator>
09769          inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_constant = false)
09770          {
09771             return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_constant);
09772          }
09773 
09774          inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false)
09775          {
09776             struct tie
09777             {
09778                static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_constant = false)
09779                {
09780                   return std::make_pair(is_constant,new variable_node_t(t));
09781                }
09782 
09783                #ifndef exprtk_disable_string_capabilities
09784                static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_constant = false)
09785                {
09786                   return std::make_pair(is_constant,new stringvar_node_t(t));
09787                }
09788                #endif
09789 
09790                static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
09791                {
09792                   return std::make_pair(is_constant,&t);
09793                }
09794 
09795                static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
09796                {
09797                   return std::make_pair(is_constant,&t);
09798                }
09799             };
09800 
09801             if (symbol_name.size() > 1)
09802             {
09803                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
09804                {
09805                   if (details::imatch(symbol_name,details::reserved_symbols[i]))
09806                   {
09807                      return false;
09808                   }
09809                }
09810             }
09811 
09812             tm_itr_t itr = map.find(symbol_name);
09813 
09814             if (map.end() == itr)
09815             {
09816                map[symbol_name] = tie::make(t,is_constant);
09817                ++size;
09818             }
09819             return true;
09820          }
09821 
09822          inline type_ptr get(const std::string& symbol_name)
09823          {
09824             tm_const_itr_t itr = map.find(symbol_name);
09825             if (map.end() == itr)
09826                return reinterpret_cast<type_ptr>(0);
09827             else
09828                return itr->second.second;
09829          }
09830 
09831          inline bool remove(const std::string& symbol_name, const bool delete_node = true)
09832          {
09833             tm_itr_t itr = map.find(symbol_name);
09834             if (map.end() != itr)
09835             {
09836                struct deleter
09837                {
09838                   static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
09839                   static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
09840                   #ifndef exprtk_disable_string_capabilities
09841                   static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
09842                   #endif
09843                   static inline void process(std::pair<bool,function_t*>&)         {                  }
09844                };
09845                if (delete_node)
09846                {
09847                   deleter::process((*itr).second);
09848                }
09849                map.erase(itr);
09850                --size;
09851                return true;
09852             }
09853             else
09854                return false;
09855          }
09856 
09857          inline RawType& type_ref(const std::string& symbol_name)
09858          {
09859             struct init_type
09860             {
09861                static inline double set(long double)      { return (0.0);           }
09862                static inline float  set(float)            { return (0.0f);          }
09863                static inline std::string set(std::string) { return std::string(""); }
09864             };
09865 
09866             static RawType null_type = init_type::set(RawType());
09867 
09868             tm_const_itr_t itr = map.find(symbol_name);
09869             if (map.end() == itr)
09870                return null_type;
09871             else
09872                return itr->second.second->ref();
09873          }
09874 
09875          inline void clear(const bool delete_node = true)
09876          {
09877             struct deleter
09878             {
09879                static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
09880                static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
09881                static inline void process(std::pair<bool,function_t*>&)         {                  }
09882                #ifndef exprtk_disable_string_capabilities
09883                static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
09884                #endif
09885             };
09886 
09887             if (!map.empty())
09888             {
09889                if (delete_node)
09890                {
09891                   tm_itr_t itr = map.begin();
09892                   tm_itr_t end = map.end();
09893                   while (end != itr)
09894                   {
09895                      deleter::process((*itr).second);
09896                      ++itr;
09897                   }
09898                }
09899                map.clear();
09900             }
09901 
09902             size = 0;
09903          }
09904 
09905          template <typename Allocator,
09906                    template <typename, typename> class Sequence>
09907          inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
09908          {
09909             std::size_t count = 0;
09910 
09911             if (!map.empty())
09912             {
09913                tm_const_itr_t itr = map.begin();
09914                tm_const_itr_t end = map.end();
09915                while (end != itr)
09916                {
09917                   list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
09918                   ++itr;
09919                   ++count;
09920                }
09921             }
09922 
09923             return count;
09924          }
09925 
09926          template <typename Allocator,
09927                    template <typename, typename> class Sequence>
09928          inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
09929          {
09930             std::size_t count = 0;
09931 
09932             if (!map.empty())
09933             {
09934                tm_const_itr_t itr = map.begin();
09935                tm_const_itr_t end = map.end();
09936                while (end != itr)
09937                {
09938                   vlist.push_back((*itr).first);
09939                   ++itr;
09940                   ++count;
09941                }
09942             }
09943 
09944             return count;
09945          }
09946       };
09947 
09948       typedef typename details::variable_node<T> variable_t;
09949       typedef variable_t* variable_ptr;
09950       #ifndef exprtk_disable_string_capabilities
09951       typedef typename details::stringvar_node<T> stringvar_t;
09952       typedef stringvar_t* stringvar_ptr;
09953       #endif
09954       typedef ifunction<T> function_t;
09955       typedef ivararg_function<T> vararg_function_t;
09956       typedef function_t* function_ptr;
09957       typedef vararg_function_t* vararg_function_ptr;
09958 
09959       static const std::size_t lut_size = 256;
09960 
09961       // Symbol Table Holder
09962       struct st_holder
09963       {
09964          struct st_data
09965          {
09966             type_store<typename details::variable_node<T>,T> variable_store;
09967             #ifndef exprtk_disable_string_capabilities
09968             type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
09969             #endif
09970             type_store<ifunction<T>,ifunction<T> > function_store;
09971             type_store<ivararg_function<T>,ivararg_function<T> > vararg_function_store;
09972             type_store<vector_holder<T>,vector_holder<T> > vector_store;
09973 
09974             st_data()
09975             {
09976                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
09977                {
09978                   reserved_symbol_table_.insert(details::reserved_words[i]);
09979                }
09980                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
09981                {
09982                   reserved_symbol_table_.insert(details::reserved_symbols[i]);
09983                }
09984             }
09985 
09986             inline bool is_reserved_symbol(const std::string& symbol) const
09987             {
09988                return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
09989             }
09990 
09991             std::list<T> local_symbol_list_;
09992             std::list<std::string> local_stringvar_list_;
09993             std::set<std::string> reserved_symbol_table_;
09994          };
09995 
09996          st_holder()
09997          : ref_count(1),
09998            data_(new st_data)
09999          {}
10000 
10001          st_holder(st_data* data)
10002          : ref_count(1),
10003            data_(data)
10004          {}
10005 
10006         ~st_holder()
10007          {
10008             if (data_ && (0 == ref_count))
10009             {
10010                delete data_;
10011                data_ = 0;
10012             }
10013          }
10014 
10015          std::size_t ref_count;
10016          st_data* data_;
10017       };
10018 
10019    public:
10020 
10021       symbol_table()
10022       : holder_(new st_holder)
10023       {
10024          clear();
10025       }
10026 
10027      ~symbol_table()
10028       {
10029          if (holder_)
10030          {
10031             if (0 == --holder_->ref_count)
10032             {
10033                clear();
10034                delete holder_;
10035             }
10036          }
10037       }
10038 
10039       symbol_table(const symbol_table<T>& st)
10040       {
10041          holder_ = st.holder_;
10042          holder_->ref_count++;
10043       }
10044 
10045       inline symbol_table<T>& operator=(const symbol_table<T>& st)
10046       {
10047          if (holder_)
10048          {
10049             if (0 == --holder_->ref_count)
10050             {
10051                delete holder_;
10052             }
10053             holder_ = 0;
10054          }
10055          holder_ = st.holder_;
10056          holder_->ref_count++;
10057          return *this;
10058       }
10059 
10060       inline bool operator==(const symbol_table<T>& st)
10061       {
10062          return (this == *st);
10063       }
10064 
10065       inline void clear_variables(const bool delete_node = true)
10066       {
10067          local_data().variable_store.clear(delete_node);
10068       }
10069 
10070       inline void clear_functions()
10071       {
10072          local_data().function_store.clear();
10073       }
10074 
10075       inline void clear_strings()
10076       {
10077          #ifndef exprtk_disable_string_capabilities
10078          local_data().stringvar_store.clear();
10079          #endif
10080       }
10081 
10082       inline void clear_vectors()
10083       {
10084          local_data().vector_store.clear();
10085       }
10086 
10087       inline void clear()
10088       {
10089          if (!valid()) return;
10090          clear_variables();
10091          clear_functions();
10092          clear_strings();
10093          clear_vectors();
10094       }
10095 
10096       inline std::size_t variable_count() const
10097       {
10098          if (valid())
10099             return local_data().variable_store.size;
10100          else
10101             return 0;
10102       }
10103 
10104       #ifndef exprtk_disable_string_capabilities
10105       inline std::size_t stringvar_count() const
10106       {
10107          if (valid())
10108             return local_data().stringvar_store.size;
10109          else
10110             return 0;
10111       }
10112       #endif
10113 
10114       inline std::size_t function_count() const
10115       {
10116          if (valid())
10117             return local_data().function_store.size;
10118          else
10119             return 0;
10120       }
10121 
10122       inline std::size_t vector_count() const
10123       {
10124          if (valid())
10125             return local_data().vector_store.size;
10126          else
10127             return 0;
10128       }
10129 
10130       inline variable_ptr get_variable(const std::string& variable_name)
10131       {
10132          if (!valid())
10133             return reinterpret_cast<variable_ptr>(0);
10134          else if (!valid_symbol(variable_name))
10135             return reinterpret_cast<variable_ptr>(0);
10136          else
10137             return local_data().variable_store.get(variable_name);
10138       }
10139 
10140       #ifndef exprtk_disable_string_capabilities
10141       inline stringvar_ptr get_stringvar(const std::string& string_name)
10142       {
10143          if (!valid())
10144             return reinterpret_cast<stringvar_ptr>(0);
10145          else if (!valid_symbol(string_name))
10146             return reinterpret_cast<stringvar_ptr>(0);
10147          else
10148             return local_data().stringvar_store.get(string_name);
10149       }
10150       #endif
10151 
10152       inline function_ptr get_function(const std::string& function_name)
10153       {
10154          if (!valid())
10155             return reinterpret_cast<function_ptr>(0);
10156          else if (!valid_symbol(function_name))
10157             return reinterpret_cast<function_ptr>(0);
10158          else
10159             return local_data().function_store.get(function_name);
10160       }
10161 
10162       inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name)
10163       {
10164          if (!valid())
10165             return reinterpret_cast<vararg_function_ptr>(0);
10166          else if (!valid_symbol(vararg_function_name))
10167             return reinterpret_cast<vararg_function_ptr>(0);
10168          else
10169             return local_data().vararg_function_store.get(vararg_function_name);
10170       }
10171 
10172       typedef vector_holder<T>* vector_ptr;
10173 
10174       inline vector_ptr get_vector(const std::string& vector_name)
10175       {
10176          if (!valid())
10177             return reinterpret_cast<vector_ptr>(0);
10178          else if (!valid_symbol(vector_name))
10179             return reinterpret_cast<vector_ptr>(0);
10180          else
10181             return local_data().vector_store.get(vector_name);
10182       }
10183 
10184       inline T& variable_ref(const std::string& symbol_name)
10185       {
10186          static T null_var = T(0);
10187          if (!valid())
10188             return null_var;
10189          else if (!valid_symbol(symbol_name))
10190             return null_var;
10191          else
10192             return local_data().variable_store.type_ref(symbol_name);
10193       }
10194 
10195       #ifndef exprtk_disable_string_capabilities
10196       inline std::string& stringvar_ref(const std::string& symbol_name)
10197       {
10198          static std::string null_stringvar;
10199          if (!valid())
10200             return null_stringvar;
10201          else if (!valid_symbol(symbol_name))
10202             return null_stringvar;
10203          else
10204             return local_data().stringvar_store.type_ref(symbol_name);
10205       }
10206       #endif
10207 
10208       inline bool is_constant_node(const std::string& symbol_name) const
10209       {
10210          if (!valid())
10211             return false;
10212          else if (!valid_symbol(symbol_name))
10213             return false;
10214          else if (!local_data().variable_store.symbol_exists(symbol_name))
10215             return false;
10216          else
10217             return local_data().variable_store.is_constant(symbol_name);
10218       }
10219 
10220       #ifndef exprtk_disable_string_capabilities
10221       inline bool is_constant_string(const std::string& symbol_name) const
10222       {
10223          if (!valid())
10224             return false;
10225          else if (!valid_symbol(symbol_name))
10226             return false;
10227          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
10228             return false;
10229          else
10230             return local_data().stringvar_store.is_constant(symbol_name);
10231       }
10232       #endif
10233 
10234       inline bool create_variable(const std::string& variable_name, const T& value = T(0))
10235       {
10236          if (!valid())
10237             return false;
10238          else if (!valid_symbol(variable_name))
10239             return false;
10240          else if (symbol_exists(variable_name))
10241             return false;
10242          local_data().local_symbol_list_.push_back(value);
10243          T& t = local_data().local_symbol_list_.back();
10244          return add_variable(variable_name,t);
10245       }
10246 
10247       #ifndef exprtk_disable_string_capabilities
10248       inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
10249       {
10250          if (!valid())
10251             return false;
10252          else if (!valid_symbol(stringvar_name))
10253             return false;
10254          else if (symbol_exists(stringvar_name))
10255             return false;
10256          local_data().local_stringvar_list_.push_back(value);
10257          std::string& s = local_data().local_stringvar_list_.back();
10258          return add_stringvar(stringvar_name,s);
10259       }
10260       #endif
10261 
10262       inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
10263       {
10264          if (!valid())
10265             return false;
10266          else if (!valid_symbol(variable_name))
10267             return false;
10268          else if (symbol_exists(variable_name))
10269             return false;
10270          else
10271             return local_data().variable_store.add(variable_name,t,is_constant);
10272       }
10273 
10274       inline bool add_constant(const std::string& constant_name, const T& value)
10275       {
10276          if (!valid())
10277             return false;
10278          else if (!valid_symbol(constant_name))
10279             return false;
10280          else if (symbol_exists(constant_name))
10281             return false;
10282          local_data().local_symbol_list_.push_back(value);
10283          T& t = local_data().local_symbol_list_.back();
10284          return add_variable(constant_name,t,true);
10285       }
10286 
10287       #ifndef exprtk_disable_string_capabilities
10288       inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
10289       {
10290          if (!valid())
10291             return false;
10292          else if (!valid_symbol(stringvar_name))
10293             return false;
10294          else if (symbol_exists(stringvar_name))
10295             return false;
10296          else
10297             return local_data().stringvar_store.add(stringvar_name,s,is_constant);
10298       }
10299       #endif
10300 
10301       inline bool add_function(const std::string& function_name, function_t& function)
10302       {
10303          if (!valid())
10304             return false;
10305          else if (!valid_symbol(function_name))
10306             return false;
10307          else if (symbol_exists(function_name))
10308             return false;
10309          else
10310             return local_data().function_store.add(function_name,function);
10311       }
10312 
10313       inline bool add_vararg_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
10314       {
10315          if (!valid())
10316             return false;
10317          else if (!valid_symbol(vararg_function_name))
10318             return false;
10319          else if (symbol_exists(vararg_function_name))
10320             return false;
10321          else
10322             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
10323       }
10324 
10325       template <std::size_t N>
10326       inline bool add_vector(const std::string& vector_name, T (&v)[N])
10327       {
10328          if (!valid())
10329             return false;
10330          else if (!valid_symbol(vector_name))
10331             return false;
10332          else if (symbol_exists(vector_name))
10333             return false;
10334          else
10335             return local_data().vector_store.add(vector_name,v);
10336       }
10337 
10338       inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
10339       {
10340          if (!valid())
10341             return false;
10342          else if (!valid_symbol(vector_name))
10343             return false;
10344          else if (symbol_exists(vector_name))
10345             return false;
10346          else
10347             return local_data().vector_store.add(vector_name,v,v_size);
10348       }
10349 
10350       template <typename Allocator>
10351       inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
10352       {
10353          if (!valid())
10354             return false;
10355          else if (!valid_symbol(vector_name))
10356             return false;
10357          else if (symbol_exists(vector_name))
10358             return false;
10359          else
10360             return local_data().vector_store.add(vector_name,v);
10361       }
10362 
10363       template <typename Allocator>
10364       inline bool add_vector(const std::string& vector_name, std::deque<T,Allocator>& v)
10365       {
10366          if (!valid())
10367             return false;
10368          else if (!valid_symbol(vector_name))
10369             return false;
10370          else if (symbol_exists(vector_name))
10371             return false;
10372          else
10373             return local_data().vector_store.add(vector_name,v);
10374       }
10375 
10376       inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
10377       {
10378          if (!valid())
10379             return false;
10380          else
10381             return local_data().variable_store.remove(variable_name, delete_node);
10382       }
10383 
10384       #ifndef exprtk_disable_string_capabilities
10385       inline bool remove_stringvar(const std::string& string_name)
10386       {
10387          if (!valid())
10388             return false;
10389          else
10390             return local_data().stringvar_store.remove(string_name);
10391       }
10392       #endif
10393 
10394       inline bool remove_function(const std::string& function_name)
10395       {
10396          if (!valid())
10397             return false;
10398          else
10399             return local_data().function_store.remove(function_name);
10400       }
10401 
10402       inline bool remove_vararg_function(const std::string& vararg_function_name)
10403       {
10404          if (!valid())
10405             return false;
10406          else
10407             return local_data().vararg_function_store.remove(vararg_function_name);
10408       }
10409 
10410       inline bool remove_vector(const std::string& vector_name)
10411       {
10412          if (!valid())
10413             return false;
10414          else
10415             return local_data().vector_store.remove(vector_name);
10416       }
10417 
10418       inline bool add_constants()
10419       {
10420          return add_pi()      &&
10421                 add_epsilon() &&
10422                 add_infinity();
10423       }
10424 
10425       inline bool add_pi()
10426       {
10427          static const T local_pi = T(details::numeric::constant::pi);
10428          return add_constant("pi",local_pi);
10429       }
10430 
10431       inline bool add_epsilon()
10432       {
10433          static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
10434          return add_constant("epsilon",local_epsilon);
10435       }
10436 
10437       inline bool add_infinity()
10438       {
10439          static const T local_infinity = std::numeric_limits<T>::infinity();
10440          return add_constant("inf",local_infinity);
10441       }
10442 
10443       template <typename Allocator,
10444                 template <typename, typename> class Sequence>
10445       inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
10446       {
10447          if (!valid())
10448             return 0;
10449          else
10450             return local_data().variable_store.get_list(vlist);
10451       }
10452 
10453       template <typename Allocator,
10454                 template <typename, typename> class Sequence>
10455       inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
10456       {
10457          if (!valid())
10458             return 0;
10459          else
10460             return local_data().variable_store.get_list(vlist);
10461       }
10462 
10463       #ifndef exprtk_disable_string_capabilities
10464       template <typename Allocator,
10465                 template <typename, typename> class Sequence>
10466       inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
10467       {
10468          if (!valid())
10469             return 0;
10470          else
10471             return local_data().stringvar_store.get_list(svlist);
10472       }
10473 
10474       template <typename Allocator,
10475                 template <typename, typename> class Sequence>
10476       inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
10477       {
10478          if (!valid())
10479             return 0;
10480          else
10481             return local_data().stringvar_store.get_list(svlist);
10482       }
10483       #endif
10484 
10485       template <typename Allocator,
10486                 template <typename, typename> class Sequence>
10487       inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
10488       {
10489          if (!valid())
10490             return 0;
10491          else
10492             return local_data().vector_store.get_list(vlist);
10493       }
10494 
10495       inline bool symbol_exists(const std::string& symbol_name) const
10496       {
10497          /*
10498             Will return true if symbol_name exists as either a reserved symbol,
10499             variable, stringvar or function name in any of the type stores.
10500          */
10501          if (!valid())
10502             return false;
10503          else if (local_data().variable_store.symbol_exists(symbol_name))
10504             return true;
10505          #ifndef exprtk_disable_string_capabilities
10506          else if (local_data().stringvar_store.symbol_exists(symbol_name))
10507             return true;
10508          #endif
10509          else if (local_data().function_store.symbol_exists(symbol_name))
10510             return true;
10511          else if (local_data().is_reserved_symbol(symbol_name))
10512             return true;
10513          else
10514             return false;
10515       }
10516 
10517       inline bool is_variable(const std::string& variable_name) const
10518       {
10519          if (!valid())
10520             return false;
10521          else
10522             return local_data().variable_store.symbol_exists(variable_name);
10523       }
10524 
10525       #ifndef exprtk_disable_string_capabilities
10526       inline bool is_stringvar(const std::string& stringvar_name) const
10527       {
10528          if (!valid())
10529             return false;
10530          else
10531             return local_data().stringvar_store.symbol_exists(stringvar_name);
10532       }
10533 
10534       inline bool is_conststr_stringvar(const std::string& symbol_name) const
10535       {
10536          if (!valid())
10537             return false;
10538          else if (!valid_symbol(symbol_name))
10539             return false;
10540          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
10541             return false;
10542          return (
10543                   local_data().stringvar_store.symbol_exists(symbol_name)
10544                   ||
10545                   local_data().stringvar_store.is_constant(symbol_name)
10546                 );
10547       }
10548       #endif
10549 
10550       inline bool is_function(const std::string& function_name) const
10551       {
10552          if (!valid())
10553             return false;
10554          else
10555             return local_data().function_store.symbol_exists(function_name);
10556       }
10557 
10558       inline bool is_vararg_function(const std::string& vararg_function_name) const
10559       {
10560          if (!valid())
10561             return false;
10562          else
10563             return local_data().vararg_function_store.symbol_exists(vararg_function_name);
10564       }
10565 
10566       inline bool is_vector(const std::string& vector_name) const
10567       {
10568          if (!valid())
10569             return false;
10570          else
10571             return local_data().vector_store.symbol_exists(vector_name);
10572       }
10573 
10574       inline bool valid() const
10575       {
10576          // Symbol table sanity check.
10577          return holder_ && holder_->data_;
10578       }
10579 
10580    private:
10581 
10582       inline bool valid_symbol(const std::string& symbol) const
10583       {
10584          if (symbol.empty())
10585             return false;
10586          if (!details::is_letter(symbol[0]))
10587             return false;
10588          else if (symbol.size() > 1)
10589          {
10590             for (std::size_t i = 1; i < symbol.size(); ++i)
10591             {
10592                if (
10593                     (!details::is_letter(symbol[i])) &&
10594                     (!details:: is_digit(symbol[i])) &&
10595                     ('_' != symbol[i])
10596                   )
10597                {
10598                   return false;
10599                }
10600             }
10601          }
10602 
10603          return (!local_data().is_reserved_symbol(symbol));
10604       }
10605 
10606       inline typename st_holder::st_data& local_data()
10607       {
10608          return *(holder_->data_);
10609       }
10610 
10611       inline const typename st_holder::st_data& local_data() const
10612       {
10613          return *(holder_->data_);
10614       }
10615 
10616       st_holder* holder_;
10617 
10618    };
10619 
10620    template <typename T>
10621    class expression
10622    {
10623    private:
10624 
10625       typedef details::expression_node<T>* expression_ptr;
10626 
10627       struct expression_holder
10628       {
10629          expression_holder()
10630          : ref_count(0),
10631            expr(0)
10632          {}
10633 
10634          expression_holder(expression_ptr e)
10635          : ref_count(1),
10636            expr(e)
10637          {}
10638 
10639         ~expression_holder()
10640          {
10641             if (expr && !is_variable_node(expr))
10642             {
10643                delete expr;
10644             }
10645             if (!local_var_list.empty())
10646             {
10647                for (std::size_t i = 0; i < local_var_list.size(); ++i)
10648                {
10649                   delete local_var_list[i];
10650                }
10651             }
10652          }
10653 
10654          std::size_t ref_count;
10655          expression_ptr expr;
10656          std::vector<expression_ptr> local_var_list;
10657       };
10658 
10659    public:
10660 
10661       expression()
10662       : expression_holder_(0)
10663       {
10664          set_expression(new details::null_node<T>());
10665       }
10666 
10667       expression(const expression<T>& e)
10668       : expression_holder_(e.expression_holder_),
10669         symbol_table_(e.symbol_table_)
10670       {
10671          expression_holder_->ref_count++;
10672       }
10673 
10674       inline expression<T>& operator=(const expression<T>& e)
10675       {
10676          if (this != &e)
10677          {
10678             if (expression_holder_)
10679             {
10680                if (0 == --expression_holder_->ref_count)
10681                {
10682                   delete expression_holder_;
10683                }
10684                expression_holder_ = 0;
10685             }
10686             expression_holder_ = e.expression_holder_;
10687             expression_holder_->ref_count++;
10688             symbol_table_ = e.symbol_table_;
10689          }
10690          return *this;
10691       }
10692 
10693       inline bool operator==(const expression<T>& e)
10694       {
10695          return (this == &e);
10696       }
10697 
10698       inline bool operator!() const
10699       {
10700          return ((0 == expression_holder_) || (0 == expression_holder_->expr));
10701       }
10702 
10703       inline expression<T>& release()
10704       {
10705          if (expression_holder_)
10706          {
10707             if (0 == --expression_holder_->ref_count)
10708             {
10709                delete expression_holder_;
10710             }
10711             expression_holder_ = 0;
10712          }
10713          return *this;
10714       }
10715 
10716      ~expression()
10717       {
10718          if (expression_holder_)
10719          {
10720             if (0 == --expression_holder_->ref_count)
10721             {
10722                delete expression_holder_;
10723             }
10724          }
10725       }
10726 
10727       inline T value() const
10728       {
10729          return expression_holder_->expr->value();
10730       }
10731 
10732       inline T operator()() const
10733       {
10734          return value();
10735       }
10736 
10737       inline operator T() const
10738       {
10739          return value();
10740       }
10741 
10742       inline operator bool() const
10743       {
10744          return details::is_true(value());
10745       }
10746 
10747       inline void register_symbol_table(symbol_table<T>& st)
10748       {
10749          symbol_table_ = st;
10750       }
10751 
10752       inline const symbol_table<T>& get_symbol_table() const
10753       {
10754          return symbol_table_;
10755       }
10756 
10757       inline symbol_table<T>& get_symbol_table()
10758       {
10759          return symbol_table_;
10760       }
10761 
10762    private:
10763 
10764       inline void set_expression(const expression_ptr expr)
10765       {
10766          if (expr)
10767          {
10768             if (expression_holder_)
10769             {
10770                if (0 == --expression_holder_->ref_count)
10771                {
10772                   delete expression_holder_;
10773                }
10774             }
10775             expression_holder_ = new expression_holder(expr);
10776          }
10777       }
10778 
10779       inline void register_local_var(expression_ptr expr)
10780       {
10781          if (expr)
10782          {
10783             if (expression_holder_)
10784             {
10785                expression_holder_->local_var_list.push_back(expr);
10786             }
10787          }
10788       }
10789 
10790       expression_holder* expression_holder_;
10791       symbol_table<T> symbol_table_;
10792 
10793       friend class parser<T>;
10794       friend class expression_helper<T>;
10795    };
10796 
10797    template <typename T>
10798    class expression_helper
10799    {
10800    public:
10801 
10802       static inline bool is_head_constant(const expression<T>& expr)
10803       {
10804          return details::is_constant_node(expr.expression_holder_->expr);
10805       }
10806 
10807       static inline bool is_head_variable(const expression<T>& expr)
10808       {
10809          return details::is_variable_node(expr.expression_holder_->expr);
10810       }
10811 
10812       static inline bool is_head_unary(const expression<T>& expr)
10813       {
10814          return details::is_unary_node(expr.expression_holder_->expr);
10815       }
10816 
10817       static inline bool is_head_binary(const expression<T>& expr)
10818       {
10819          return details::is_binary_node(expr.expression_holder_->expr);
10820       }
10821 
10822       static inline bool is_head_function(const expression<T>& expr)
10823       {
10824          return details::is_function(expr.expression_holder_->expr);
10825       }
10826    };
10827 
10828    namespace parser_error
10829    {
10830       enum error_mode
10831       {
10832          e_unknown = 0,
10833          e_syntax  = 1,
10834          e_token   = 2,
10835          e_numeric = 4,
10836          e_symtab  = 5,
10837          e_lexer   = 6,
10838          e_helper  = 7
10839       };
10840 
10841       struct type
10842       {
10843          lexer::token token;
10844          error_mode mode;
10845          std::string diagnostic;
10846          std::string error_line;
10847          std::size_t line_no;
10848          std::size_t column_no;
10849       };
10850 
10851       inline type make_error(error_mode mode, const std::string& diagnostic = "")
10852       {
10853          type t;
10854          t.mode       = mode;
10855          t.token.type = lexer::token::e_error;
10856          t.diagnostic = diagnostic;
10857          t.line_no    = 0;
10858          t.column_no  = 0;
10859          return t;
10860       }
10861 
10862       inline type make_error(error_mode mode, const lexer::token tk, const std::string& diagnostic = "")
10863       {
10864          type t;
10865          t.mode       = mode;
10866          t.token      = tk;
10867          t.diagnostic = diagnostic;
10868          return t;
10869       }
10870 
10871       inline std::string to_str(error_mode mode)
10872       {
10873          switch (mode)
10874          {
10875             case e_unknown : return std::string("Unknown Error");
10876             case e_syntax  : return std::string("Syntax Error");
10877             case e_token   : return std::string("Token Error");
10878             case e_numeric : return std::string("Numeric Error");
10879             case e_symtab  : return std::string("Symbol Error");
10880             case e_lexer   : return std::string("Lexer Error");
10881             case e_helper  : return std::string("Helper Error");
10882             default        : return std::string("Unknown Error");
10883          }
10884       }
10885 
10886       inline bool update_error(type& error, const std::string& expression)
10887       {
10888          if (
10889               expression.empty()                                               ||
10890               (error.token.position >= expression.size())                      ||
10891               (std::numeric_limits<std::size_t>::max() == error.token.position)
10892             )
10893          {
10894             return false;
10895          }
10896 
10897          std::size_t error_line_start = 0;
10898          for (std::size_t i = error.token.position; i > 0; --i)
10899          {
10900             if ('\n' == expression[i])
10901             {
10902                error_line_start = i;
10903                break;
10904             }
10905          }
10906 
10907          std::size_t next_nl_position = std::min(expression.size(),
10908                                                  expression.find_first_of('\n',error.token.position + 1));
10909 
10910          error.column_no  = error.token.position - error_line_start;
10911          error.error_line = expression.substr(error_line_start,
10912                                               next_nl_position - error_line_start);
10913 
10914          error.line_no = 0;
10915 
10916          for (std::size_t i = 0; i < next_nl_position; ++i)
10917          {
10918             if ('\n' == expression[i])
10919                ++error.line_no;
10920          }
10921 
10922          return true;
10923       }
10924 
10925       inline void dump_error(const type& error)
10926       {
10927          printf("Position: %02d   Type: [%s]   Msg: %s\n",
10928                 static_cast<unsigned int>(error.token.position),
10929                 exprtk::parser_error::to_str(error.mode).c_str(),
10930                 error.diagnostic.c_str());
10931       }
10932    }
10933 
10934    template <typename T>
10935    class parser
10936    {
10937    private:
10938 
10939       enum precedence_level
10940       {
10941          e_level00,
10942          e_level01,
10943          e_level02,
10944          e_level03,
10945          e_level04,
10946          e_level05,
10947          e_level06,
10948          e_level07,
10949          e_level08,
10950          e_level09,
10951          e_level10,
10952          e_level11,
10953          e_level12,
10954          e_level13,
10955          e_level14
10956       };
10957 
10958       struct state_t;
10959       struct range_pack;
10960 
10961       typedef const T&                                               cref_t;
10962       typedef const T                                               const_t;
10963       typedef ifunction                <T>                                F;
10964       typedef ivararg_function         <T>                              VAF;
10965       typedef ifunction                <T>                      ifunction_t;
10966       typedef ivararg_function         <T>               ivararg_function_t;
10967       typedef details::expression_node <T>                expression_node_t;
10968       typedef details::literal_node    <T>                   literal_node_t;
10969       typedef details::unary_node      <T>                     unary_node_t;
10970       typedef details::binary_node     <T>                    binary_node_t;
10971       typedef details::trinary_node    <T>                   trinary_node_t;
10972       typedef details::quaternary_node <T>                quaternary_node_t;
10973       typedef details::quinary_node    <T>                   quinary_node_t;
10974       typedef details::senary_node     <T>                    senary_node_t;
10975       typedef details::conditional_node<T>               conditional_node_t;
10976       typedef details::cons_conditional_node<T>     cons_conditional_node_t;
10977       typedef details::while_loop_node <T>                while_loop_node_t;
10978       typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
10979       typedef details::for_loop_node<T>                     for_loop_node_t;
10980       #ifndef exprtk_disable_break_continue
10981       typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
10982       typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
10983       typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
10984       #endif
10985       typedef details::switch_node<T>                         switch_node_t;
10986       typedef details::variable_node<T>                     variable_node_t;
10987       typedef details::vector_node<T>                         vector_node_t;
10988       #ifndef exprtk_disable_string_capabilities
10989       typedef details::stringvar_node  <T>                 stringvar_node_t;
10990       typedef details::string_literal_node<T>         string_literal_node_t;
10991       typedef details::string_range_node<T,range_pack>  string_range_node_t;
10992       typedef details::const_string_range_node<T,range_pack>  const_string_range_node_t;
10993       #endif
10994       typedef details::assignment_node<T>                 assignment_node_t;
10995       typedef details::assignment_vec_node<T>         assignment_vec_node_t;
10996       typedef details::scand_node<T>                           scand_node_t;
10997       typedef details::scor_node<T>                             scor_node_t;
10998       typedef lexer::token                                          token_t;
10999       typedef expression_node_t*                        expression_node_ptr;
11000       typedef symbol_table<T>                                symbol_table_t;
11001 
11002       typedef typename details::functor_t<T> functor_t;
11003       typedef typename functor_t::qfunc_t quaternary_functor_t;
11004       typedef typename functor_t::tfunc_t trinary_functor_t;
11005       typedef typename functor_t::bfunc_t binary_functor_t;
11006       typedef typename functor_t::ufunc_t unary_functor_t;
11007       typedef std::map<details::operator_type,unary_functor_t> unary_op_map_t;
11008       typedef std::map<details::operator_type,binary_functor_t> binary_op_map_t;
11009       typedef std::map<details::operator_type,trinary_functor_t> trinary_op_map_t;
11010       typedef std::map<std::string,std::pair<trinary_functor_t,details::operator_type> > sf3_map_t;
11011       typedef std::map<std::string,std::pair<quaternary_functor_t,details::operator_type> > sf4_map_t;
11012       typedef std::map<binary_functor_t,details::operator_type> inv_binary_op_map_t;
11013       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
11014 
11015       typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
11016       typedef details::T0oT1_define<T,const_t, cref_t> cov_t;
11017       typedef details::T0oT1_define<T, cref_t,const_t> voc_t;
11018 
11019       typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
11020       typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t;
11021       typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t;
11022       typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t;
11023       typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t;
11024       typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t;
11025       typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t;
11026 
11027       typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
11028       typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t;
11029       typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t;
11030       typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t;
11031       typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t;
11032 
11033       typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t;
11034       typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t;
11035       typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
11036       typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
11037 
11038    public:
11039 
11040       enum precompilation_step
11041       {
11042          e_unknown            =  0,
11043          e_replacer           =  1,
11044          e_joiner             =  2,
11045          e_numeric_check      =  4,
11046          e_bracket_check      =  8,
11047          e_sequence_check     = 16,
11048          e_commutative_check  = 32,
11049          e_strength_reduction = 64
11050       };
11051 
11052       struct unknown_symbol_resolver
11053       {
11054 
11055          enum symbol_type
11056          {
11057             e_variable_type = 0,
11058             e_constant_type = 1
11059          };
11060 
11061          virtual ~unknown_symbol_resolver()
11062          {}
11063 
11064          virtual bool process(const std::string& /*unknown_symbol*/, symbol_type& st, T& default_value, std::string& error_message)
11065          {
11066             st = e_variable_type;
11067             default_value = T(0);
11068             error_message = "";
11069             return true;
11070          }
11071       };
11072 
11073       static const std::size_t compile_all_opts = e_replacer          +
11074                                                   e_joiner            +
11075                                                   e_numeric_check     +
11076                                                   e_bracket_check     +
11077                                                   e_sequence_check    +
11078                                                   e_commutative_check +
11079                                                   e_strength_reduction;
11080 
11081       parser(const std::size_t compile_options = compile_all_opts)
11082       : symbol_name_caching_(false),
11083         compile_options_(compile_options),
11084         resolve_unknown_symbol_(false),
11085         unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
11086         operator_joiner_2_(2),
11087         operator_joiner_3_(3)
11088       {
11089          init_precompilation();
11090          load_operations_map(base_ops_map_);
11091          load_unary_operations_map(unary_op_map_);
11092          load_binary_operations_map(binary_op_map_);
11093          load_inv_binary_operations_map(inv_binary_op_map_);
11094          load_sf3_map(sf3_map_);
11095          load_sf4_map(sf4_map_);
11096          expression_generator_.init_synthesize_map();
11097          expression_generator_.set_parser(*this);
11098          expression_generator_.set_uom(unary_op_map_);
11099          expression_generator_.set_bom(binary_op_map_);
11100          expression_generator_.set_ibom(inv_binary_op_map_);
11101          expression_generator_.set_sf3m(sf3_map_);
11102          expression_generator_.set_sf4m(sf4_map_);
11103          expression_generator_.set_strength_reduction_state(strength_reduction_enabled());
11104       }
11105 
11106      ~parser()
11107       {
11108          local_symbol_table_.clear_variables(false);
11109       }
11110 
11111       inline void init_precompilation()
11112       {
11113          if (replacer_enabled())
11114          {
11115             symbol_replacer_.clear();
11116             symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number);
11117             symbol_replacer_.add_replace("false","0",lexer::token::e_number);
11118             helper_assembly_.token_modifier_list.clear();
11119             helper_assembly_.register_modifier(&symbol_replacer_);
11120          }
11121 
11122          if (commutative_check_enabled())
11123          {
11124             for (std::size_t i = 0; i < details::reserved_words_size; ++i)
11125             {
11126                commutative_inserter_.ignore_symbol(details::reserved_words[i]);
11127             }
11128 
11129             helper_assembly_.token_inserter_list.clear();
11130             helper_assembly_.register_inserter(&commutative_inserter_);
11131          }
11132 
11133          if (joiner_enabled())
11134          {
11135             helper_assembly_.token_joiner_list.clear();
11136             helper_assembly_.register_joiner(&operator_joiner_2_);
11137             helper_assembly_.register_joiner(&operator_joiner_3_);
11138          }
11139 
11140          if (
11141               numeric_check_enabled() ||
11142               bracket_check_enabled() ||
11143               sequence_check_enabled()
11144             )
11145          {
11146             helper_assembly_.token_scanner_list.clear();
11147 
11148             if (numeric_check_enabled())
11149             {
11150                helper_assembly_.register_scanner(&numeric_checker_);
11151             }
11152 
11153             if (bracket_check_enabled())
11154             {
11155                helper_assembly_.register_scanner(&bracket_checker_);
11156             }
11157 
11158             if (sequence_check_enabled())
11159             {
11160                helper_assembly_.register_scanner(&sequence_validator_);
11161             }
11162          }
11163       }
11164 
11165       inline bool compile(const std::string& expression_string, expression<T>& expr)
11166       {
11167          error_list_.clear();
11168          synthesis_error_.clear();
11169          brkcnt_list_.clear();
11170          local_symbol_table_.clear_variables(false);
11171          expression_generator_.set_allocator(node_allocator_);
11172 
11173          if (expression_string.empty())
11174          {
11175             set_error(
11176                make_error(parser_error::e_syntax,
11177                           "ERR00 - Empty expression!"));
11178             return false;
11179          }
11180 
11181          if (!lexer_.process(expression_string))
11182          {
11183             process_lexer_errors();
11184             return false;
11185          }
11186 
11187          if (lexer_.empty())
11188          {
11189             set_error(
11190                make_error(parser_error::e_syntax,
11191                           "ERR01 - Empty expression!"));
11192             return false;
11193          }
11194 
11195          if (!run_assemblies())
11196          {
11197             return false;
11198          }
11199 
11200          symbol_table_ = expr.get_symbol_table();
11201          symbol_name_cache_.clear();
11202 
11203          lexer_.begin();
11204          next_token();
11205 
11206          expression_node_ptr e = parse_corpus();
11207 
11208          if ((0 != e) && (token_t::e_eof == current_token_.type))
11209          {
11210             expr.set_expression(e);
11211             register_local_vars(expr);
11212             return !(!expr);
11213          }
11214          else
11215          {
11216             set_error(
11217                make_error(parser_error::e_syntax,
11218                           current_token_,
11219                           "ERR02 - Incomplete expression due to unexpected token: '" + current_token_.value + "'"));
11220 
11221             symbol_name_cache_.clear();
11222             clear_local_vars();
11223 
11224             if (0 != e)
11225             {
11226                delete e;
11227             }
11228 
11229             return false;
11230          }
11231       }
11232 
11233       void process_lexer_errors()
11234       {
11235          for (std::size_t i = 0; i < lexer_.size(); ++i)
11236          {
11237             if (lexer_[i].is_error())
11238             {
11239                std::string diagnostic = "ERR03 - ";
11240                switch (lexer_[i].type)
11241                {
11242                   case lexer::token::e_error      : diagnostic += "General token error";
11243                                                     break;
11244 
11245                   case lexer::token::e_err_symbol : diagnostic += "Symbol error";
11246                                                     break;
11247 
11248                   case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
11249                                                     break;
11250 
11251                   case lexer::token::e_err_string : diagnostic += "Invalid string token";
11252                                                     break;
11253 
11254                   case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
11255                                                     break;
11256 
11257                   default                         : diagnostic += "Unknown compiler error";
11258                }
11259 
11260                set_error(
11261                   make_error(parser_error::e_lexer,
11262                              lexer_[i],
11263                              diagnostic + ": " + lexer_[i].value));
11264             }
11265          }
11266       }
11267 
11268       inline bool replacer_enabled() const
11269       {
11270          return ((compile_options_ & e_replacer) == e_replacer);
11271       }
11272 
11273       inline bool commutative_check_enabled() const
11274       {
11275          return ((compile_options_ & e_commutative_check) == e_commutative_check);
11276       }
11277 
11278       inline bool joiner_enabled() const
11279       {
11280          return ((compile_options_ & e_joiner) == e_joiner);
11281       }
11282 
11283       inline bool numeric_check_enabled() const
11284       {
11285          return ((compile_options_ & e_numeric_check) == e_numeric_check);
11286       }
11287 
11288       inline bool bracket_check_enabled() const
11289       {
11290          return ((compile_options_ & e_bracket_check) == e_bracket_check);
11291       }
11292 
11293       inline bool sequence_check_enabled() const
11294       {
11295          return ((compile_options_ & e_sequence_check) == e_sequence_check);
11296       }
11297 
11298       inline bool strength_reduction_enabled() const
11299       {
11300          return ((compile_options_ & e_strength_reduction) == e_strength_reduction);
11301       }
11302 
11303       inline bool run_assemblies()
11304       {
11305          if (commutative_check_enabled())
11306          {
11307             helper_assembly_.run_inserters(lexer_);
11308          }
11309 
11310          if (joiner_enabled())
11311          {
11312             helper_assembly_.run_joiners(lexer_);
11313          }
11314 
11315          if (replacer_enabled())
11316          {
11317             helper_assembly_.run_modifiers(lexer_);
11318          }
11319 
11320          if (
11321               numeric_check_enabled () ||
11322               bracket_check_enabled () ||
11323               sequence_check_enabled()
11324             )
11325          {
11326             if (!helper_assembly_.run_scanners(lexer_))
11327             {
11328                if (helper_assembly_.error_token_scanner)
11329                {
11330                   lexer::helper::bracket_checker*    bracket_checker_ptr    = 0;
11331                   lexer::helper::numeric_checker*    numeric_checker_ptr    = 0;
11332                   lexer::helper::sequence_validator* sequence_validator_ptr = 0;
11333 
11334                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
11335                   {
11336                      set_error(
11337                         make_error(parser_error::e_token,
11338                                    bracket_checker_ptr->error_token(),
11339                                    "ERR04 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'"));
11340                   }
11341                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
11342                   {
11343                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
11344                      {
11345                         lexer::token error_token = lexer_[numeric_checker_ptr->error_index(i)];
11346                         set_error(
11347                            make_error(parser_error::e_token,
11348                                       error_token,
11349                                       "ERR05 - Invalid numeric token: '" + error_token.value + "'"));
11350                      }
11351                   }
11352                   else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
11353                   {
11354                      for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
11355                      {
11356                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
11357                         set_error(
11358                            make_error(parser_error::e_token,
11359                                       error_token.first,
11360                                       "ERR06 - Invalid token sequence: '" +
11361                                       error_token.first.value  + "' and '" +
11362                                       error_token.second.value + "'"));
11363                      }
11364                   }
11365                }
11366                return false;
11367             }
11368          }
11369 
11370          return true;
11371       }
11372 
11373       inline parser_error::type get_error(const std::size_t& index)
11374       {
11375          if (index < error_list_.size())
11376             return error_list_[index];
11377          else
11378             throw std::invalid_argument("parser::get_error() - Invalid error index specificed.");
11379       }
11380 
11381       inline std::string error() const
11382       {
11383          if (!error_list_.empty())
11384          {
11385             return error_list_[0].diagnostic;
11386          }
11387          else
11388             return std::string("No Error");
11389       }
11390 
11391       inline std::size_t error_count() const
11392       {
11393          return error_list_.size();
11394       }
11395 
11396       inline bool& cache_symbols()
11397       {
11398          return symbol_name_caching_;
11399       }
11400 
11401       template <typename Allocator,
11402                 template <typename,typename> class Sequence>
11403       inline std::size_t expression_symbols(Sequence<std::string,Allocator>& symbols_list)
11404       {
11405          if (!symbol_name_caching_)
11406             return 0;
11407          else if (symbol_name_cache_.empty())
11408             return 0;
11409          std::sort(symbol_name_cache_.begin(),symbol_name_cache_.end());
11410          std::unique_copy(symbol_name_cache_.begin(),
11411                           symbol_name_cache_.end(),
11412                           std::back_inserter(symbols_list));
11413          return symbol_name_cache_.size();
11414       }
11415 
11416       inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
11417       {
11418          if (!replacer_enabled())
11419             return false;
11420          else if (details::is_reserved_word(old_symbol))
11421             return false;
11422          else
11423             return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
11424       }
11425 
11426       inline bool remove_replace_symbol(const std::string& symbol)
11427       {
11428          if (!replacer_enabled())
11429             return false;
11430          else if (details::is_reserved_word(symbol))
11431             return false;
11432          else
11433             return symbol_replacer_.remove(symbol);
11434       }
11435 
11436       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
11437       {
11438          resolve_unknown_symbol_ = true;
11439          if (usr)
11440             unknown_symbol_resolver_ = usr;
11441          else
11442             unknown_symbol_resolver_ = &default_usr_;
11443       }
11444 
11445       inline void disable_unknown_symbol_resolver()
11446       {
11447          resolve_unknown_symbol_ = false;
11448          unknown_symbol_resolver_ = &default_usr_;
11449       }
11450 
11451    private:
11452 
11453       inline bool valid_base_operation(const std::string& symbol)
11454       {
11455          const std::size_t length = symbol.size();
11456          if (
11457               (length < 3) || // Shortest base op symbol length
11458               (length > 9)    // Longest base op symbol length
11459             )
11460             return false;
11461          else
11462             return (base_ops_map_.end() != base_ops_map_.find(symbol));
11463       }
11464 
11465       inline bool valid_vararg_operation(const std::string& symbol)
11466       {
11467          static const std::string s_sum     = "sum" ;
11468          static const std::string s_mul     = "mul" ;
11469          static const std::string s_avg     = "avg" ;
11470          static const std::string s_min     = "min" ;
11471          static const std::string s_max     = "max" ;
11472          static const std::string s_mand    = "mand";
11473          static const std::string s_mor     = "mor" ;
11474          static const std::string s_multi   = "~"   ;
11475          static const std::string s_mswitch = "[*]" ;
11476          return
11477                (
11478                   details::imatch(symbol,s_sum    ) ||
11479                   details::imatch(symbol,s_mul    ) ||
11480                   details::imatch(symbol,s_avg    ) ||
11481                   details::imatch(symbol,s_min    ) ||
11482                   details::imatch(symbol,s_max    ) ||
11483                   details::imatch(symbol,s_mand   ) ||
11484                   details::imatch(symbol,s_mor    ) ||
11485                   details::imatch(symbol,s_multi  ) ||
11486                   details::imatch(symbol,s_mswitch)
11487                );
11488       }
11489 
11490       inline void store_token()
11491       {
11492          lexer_.store();
11493          store_current_token_ = current_token_;
11494       }
11495 
11496       inline void restore_token()
11497       {
11498          lexer_.restore();
11499          current_token_ = store_current_token_;
11500       }
11501 
11502       #ifndef exprtk_enable_debugging
11503       inline void next_token()
11504       {
11505          current_token_ = lexer_.next_token();
11506       }
11507       #else
11508       inline void next_token()
11509       {
11510          std::string ct_str = current_token_.value;
11511          current_token_ = lexer_.next_token();
11512          printf("prev[%s] --> curr[%s]\n",
11513                 ct_str.c_str(),
11514                 current_token_.value.c_str());
11515       }
11516       #endif
11517 
11518       inline const lexer::token& current_token() const
11519       {
11520          return current_token_;
11521       }
11522 
11523       inline expression_node_ptr parse_corpus()
11524       {
11525          std::deque<expression_node_ptr> arg_list;
11526          expression_node_ptr result = error_node();
11527 
11528          scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
11529 
11530          do
11531          {
11532             expression_node_ptr arg = parse_expression();
11533             if (0 == arg)
11534                return error_node();
11535             else
11536                arg_list.push_back(arg);
11537 
11538             if (!token_is(token_t::e_eof))
11539             {
11540                set_error(
11541                   make_error(parser_error::e_syntax,
11542                              current_token_,
11543                              "ERR07 - Expected ';' at end of sub-expression, instead got: '" + current_token_.value + "'"));
11544                return error_node();
11545             }
11546          }
11547          while (!lexer_.finished());
11548 
11549          result = simplify(arg_list);
11550 
11551          sdd.delete_ptr = (0 == result);
11552          return result;
11553       }
11554 
11555       static const precedence_level default_precedence = e_level00;
11556 
11557       struct state_t
11558       {
11559          inline void set(const precedence_level& l,
11560                          const precedence_level& r,
11561                          const details::operator_type& o)
11562          {
11563             left  = l;
11564             right = r;
11565             operation = o;
11566          }
11567 
11568          inline void reset()
11569          {
11570             left  = e_level00;
11571             right = e_level00;
11572          }
11573 
11574          precedence_level left;
11575          precedence_level right;
11576          details::operator_type operation;
11577       };
11578 
11579       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
11580       {
11581          expression_node_ptr expression = parse_branch(precedence);
11582 
11583          if (0 == expression)
11584          {
11585             return error_node();
11586          }
11587 
11588          bool break_loop = false;
11589 
11590          state_t current_state;
11591 
11592          for ( ; ; )
11593          {
11594             current_state.reset();
11595 
11596             switch (current_token_.type)
11597             {
11598                case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;
11599                case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;
11600                case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;
11601                case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;
11602                case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;
11603                case token_t::e_lt     : current_state.set(e_level05,e_level06,details::    e_lt); break;
11604                case token_t::e_lte    : current_state.set(e_level05,e_level06,details::   e_lte); break;
11605                case token_t::e_eq     : current_state.set(e_level05,e_level06,details::    e_eq); break;
11606                case token_t::e_ne     : current_state.set(e_level05,e_level06,details::    e_ne); break;
11607                case token_t::e_gte    : current_state.set(e_level05,e_level06,details::   e_gte); break;
11608                case token_t::e_gt     : current_state.set(e_level05,e_level06,details::    e_gt); break;
11609                case token_t::e_add    : current_state.set(e_level07,e_level08,details::   e_add); break;
11610                case token_t::e_sub    : current_state.set(e_level07,e_level08,details::   e_sub); break;
11611                case token_t::e_div    : current_state.set(e_level10,e_level11,details::   e_div); break;
11612                case token_t::e_mul    : current_state.set(e_level10,e_level11,details::   e_mul); break;
11613                case token_t::e_mod    : current_state.set(e_level10,e_level11,details::   e_mod); break;
11614                case token_t::e_pow    : current_state.set(e_level12,e_level12,details::   e_pow); break;
11615                default                : if (token_t::e_symbol == current_token_.type)
11616                                         {
11617                                            static const std::string s_and   =   "and";
11618                                            static const std::string s_nand  =  "nand";
11619                                            static const std::string s_or    =    "or";
11620                                            static const std::string s_nor   =   "nor";
11621                                            static const std::string s_xor   =   "xor";
11622                                            static const std::string s_xnor  =  "xnor";
11623                                            static const std::string s_in    =    "in";
11624                                            static const std::string s_like  =  "like";
11625                                            static const std::string s_ilike = "ilike";
11626                                            static const std::string s_and1  =     "&";
11627                                            static const std::string s_or1   =     "|";
11628 
11629                                            if (details::imatch(current_token_.value,s_and))
11630                                            {
11631                                               current_state.set(e_level01,e_level02,details::e_and);
11632                                               break;
11633                                            }
11634                                            else if (details::imatch(current_token_.value,s_and1))
11635                                            {
11636                                               #ifndef exprtk_disable_sc_andor
11637                                               current_state.set(e_level01,e_level02,details::e_scand);
11638                                               #else
11639                                               current_state.set(e_level01,e_level02,details::e_and);
11640                                               #endif
11641                                               break;
11642                                            }
11643                                            else if (details::imatch(current_token_.value,s_nand))
11644                                            {
11645                                               current_state.set(e_level01,e_level02,details::e_nand);
11646                                               break;
11647                                            }
11648                                            else if (details::imatch(current_token_.value,s_or))
11649                                            {
11650                                               current_state.set(e_level03,e_level04,details::e_or);
11651                                               break;
11652                                            }
11653                                            else if (details::imatch(current_token_.value,s_or1))
11654                                            {
11655                                               #ifndef exprtk_disable_sc_andor
11656                                               current_state.set(e_level03,e_level04,details::e_scor);
11657                                               #else
11658                                               current_state.set(e_level03,e_level04,details::e_or);
11659                                               #endif
11660                                               break;
11661                                            }
11662                                            else if (details::imatch(current_token_.value,s_nor))
11663                                            {
11664                                               current_state.set(e_level03,e_level04,details::e_nor);
11665                                               break;
11666                                            }
11667                                            else if (details::imatch(current_token_.value,s_xor))
11668                                            {
11669                                               current_state.set(e_level03,e_level04,details::e_xor);
11670                                               break;
11671                                            }
11672                                            else if (details::imatch(current_token_.value,s_xnor))
11673                                            {
11674                                               current_state.set(e_level03,e_level04,details::e_xnor);
11675                                               break;
11676                                            }
11677                                            else if (details::imatch(current_token_.value,s_in))
11678                                            {
11679                                               current_state.set(e_level03,e_level04,details::e_in);
11680                                               break;
11681                                            }
11682                                            else if (details::imatch(current_token_.value,s_like))
11683                                            {
11684                                               current_state.set(e_level03,e_level04,details::e_like);
11685                                               break;
11686                                            }
11687                                            else if (details::imatch(current_token_.value,s_ilike))
11688                                            {
11689                                               current_state.set(e_level03,e_level04,details::e_ilike);
11690                                               break;
11691                                            }
11692                                         }
11693 
11694                                         break_loop = true;
11695             }
11696 
11697             if (break_loop)
11698                break;
11699             else if (current_state.left < precedence)
11700                break;
11701 
11702             lexer::token prev_token = current_token_;
11703 
11704             next_token();
11705 
11706             expression_node_ptr right_branch = parse_expression(current_state.right);
11707             expression_node_ptr new_expression = error_node();
11708 
11709             if (right_branch)
11710             {
11711                new_expression = expression_generator_(
11712                                                        current_state.operation,
11713                                                        expression,
11714                                                        right_branch
11715                                                      );
11716             }
11717 
11718             if ((0 == new_expression) || (0 == right_branch))
11719             {
11720                if (error_list_.empty())
11721                {
11722                   set_error(
11723                      make_error(parser_error::e_syntax,
11724                                 prev_token,
11725                                 !synthesis_error_.empty() ?
11726                                 synthesis_error_ :
11727                                 "ERR08 - General parsing error at token: '" + prev_token.value + "'"));
11728                }
11729 
11730                free_node(node_allocator_,  expression);
11731                free_node(node_allocator_,right_branch);
11732 
11733                return error_node();
11734             }
11735             else
11736             {
11737                expression = new_expression;
11738                if (token_is(token_t::e_ternary,false) && (precedence == e_level00))
11739                {
11740                   expression = parse_ternary_conditional_statement(expression);
11741                }
11742             }
11743          }
11744 
11745          return expression;
11746       }
11747 
11748       static inline expression_node_ptr error_node()
11749       {
11750          return reinterpret_cast<expression_node_ptr>(0);
11751       }
11752 
11753       template <typename Type, std::size_t N>
11754       struct scoped_delete
11755       {
11756          typedef Type* ptr_t;
11757 
11758          scoped_delete(parser<T>& pr, ptr_t& p)
11759          : delete_ptr(true),
11760            parser_(pr),
11761            p_(&p)
11762          {}
11763 
11764          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
11765          : delete_ptr(true),
11766            parser_(pr),
11767            p_(&p[0])
11768          {}
11769 
11770         ~scoped_delete()
11771          {
11772             if (delete_ptr)
11773             {
11774                for (std::size_t i = 0; i < N; ++i)
11775                {
11776                   if (p_[i] && !is_variable_node(p_[i]))
11777                   {
11778                      parser_.node_allocator_.free(p_[i]);
11779                      p_[i] = 0;
11780                   }
11781                }
11782             }
11783          }
11784 
11785          bool delete_ptr;
11786          parser<T>& parser_;
11787          ptr_t* p_;
11788 
11789       private:
11790 
11791          scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
11792       };
11793 
11794       template <typename Type>
11795       struct scoped_deq_delete
11796       {
11797          typedef Type* ptr_t;
11798 
11799          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
11800          : delete_ptr(true),
11801            parser_(pr),
11802            deq_(deq)
11803          {}
11804 
11805         ~scoped_deq_delete()
11806          {
11807             if (delete_ptr)
11808             {
11809                for (std::size_t i = 0; i < deq_.size(); ++i)
11810                {
11811                   free_node(parser_.node_allocator_,deq_[i]);
11812                }
11813                deq_.clear();
11814             }
11815          }
11816 
11817          bool delete_ptr;
11818          parser<T>& parser_;
11819          std::deque<ptr_t>& deq_;
11820 
11821       private:
11822 
11823          scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
11824       };
11825 
11826       template <typename Type>
11827       struct scoped_vec_delete
11828       {
11829          typedef Type* ptr_t;
11830 
11831          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
11832          : delete_ptr(true),
11833            parser_(pr),
11834            vec_(vec)
11835          {}
11836 
11837         ~scoped_vec_delete()
11838          {
11839             if (delete_ptr)
11840             {
11841                for (std::size_t i = 0; i < vec_.size(); ++i)
11842                {
11843                   free_node(parser_.node_allocator_,vec_[i]);
11844                }
11845                vec_.clear();
11846             }
11847          }
11848 
11849          bool delete_ptr;
11850          parser<T>& parser_;
11851          std::vector<ptr_t>& vec_;
11852 
11853       private:
11854 
11855          scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
11856       };
11857 
11858       template <std::size_t NumberofParameters>
11859       inline expression_node_ptr parse_function_call(const details::operator_type& opt_type, bool& internal_error)
11860       {
11861          expression_node_ptr branch[NumberofParameters];
11862          expression_node_ptr result  = 0;
11863 
11864          std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
11865          scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
11866 
11867          next_token();
11868 
11869          if (!token_is(token_t::e_lbracket))
11870          {
11871             return error_node();
11872          }
11873 
11874          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
11875          {
11876             branch[i] = parse_expression();
11877             if (0 == branch[i])
11878             {
11879                internal_error = true;
11880                return error_node();
11881             }
11882             else if (i < static_cast<int>(NumberofParameters - 1))
11883             {
11884                if (!token_is(token_t::e_comma))
11885                {
11886                   return error_node();
11887                }
11888             }
11889          }
11890 
11891          if (!token_is(token_t::e_rbracket))
11892          {
11893             return error_node();
11894          }
11895          else
11896             result = expression_generator_(opt_type,branch);
11897          sd.delete_ptr = false;
11898          return result;
11899       }
11900 
11901       template <std::size_t NumberofParameters>
11902       inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
11903       {
11904          expression_node_ptr branch[NumberofParameters];
11905          expression_node_ptr result  = error_node();
11906          std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
11907          scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
11908          next_token();
11909          if (!token_is(token_t::e_lbracket))
11910          {
11911             set_error(
11912                make_error(parser_error::e_syntax,
11913                           current_token_,
11914                           "ERR09 - Expecting argument list for function: '" + function_name + "'"));
11915             return error_node();
11916          }
11917 
11918          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
11919          {
11920             branch[i] = parse_expression();
11921             if (0 == branch[i])
11922             {
11923                set_error(
11924                   make_error(parser_error::e_syntax,
11925                              current_token_,
11926                              "ERR10 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
11927                return error_node();
11928             }
11929             else if (i < static_cast<int>(NumberofParameters - 1))
11930             {
11931                if (!token_is(token_t::e_comma))
11932                {
11933                   set_error(
11934                      make_error(parser_error::e_syntax,
11935                                 current_token_,
11936                                 "ERR11 - Invalid number of arguments for function: '" + function_name + "'"));
11937                   return error_node();
11938                }
11939             }
11940          }
11941 
11942          if (!token_is(token_t::e_rbracket))
11943          {
11944             set_error(
11945                make_error(parser_error::e_syntax,
11946                           current_token_,
11947                           "ERR12 - Invalid number of arguments for function: '" + function_name + "'"));
11948             return error_node();
11949          }
11950          else
11951             result = expression_generator_.function(function,branch);
11952 
11953          sd.delete_ptr = false;
11954          return result;
11955       }
11956 
11957       inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
11958       {
11959          expression_node_ptr result = expression_generator_.function(function);
11960          next_token();
11961          if (
11962                token_is(token_t::e_lbracket) &&
11963               !token_is(token_t::e_rbracket)
11964             )
11965          {
11966             set_error(
11967                make_error(parser_error::e_syntax,
11968                           current_token_,
11969                           "ERR13 - Expecting '()' to proceed: '" + function_name + "'"));
11970             return error_node();
11971          }
11972          else
11973             return result;
11974       }
11975 
11976       inline expression_node_ptr parse_base_operation()
11977       {
11978          typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
11979          const std::string operation_name = current_token_.value;
11980          map_range_t itr_range = base_ops_map_.equal_range(operation_name);
11981          if (0 == std::distance(itr_range.first,itr_range.second))
11982          {
11983             set_error(
11984                make_error(parser_error::e_syntax,
11985                           current_token_,
11986                           "ERR14 - No entries found for base operation: " + operation_name));
11987             return error_node();
11988          }
11989 
11990          for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
11991          {
11992             store_token();
11993             expression_node_ptr branch = reinterpret_cast<expression_node_ptr>(0);
11994             details::base_operation_t& operation = itr->second;
11995             bool internal_error = false; // Any error other than incorrect number of params.
11996             switch (operation.num_params)
11997             {
11998                case 1  : branch = parse_function_call<1>(operation.type,internal_error); break;
11999                case 2  : branch = parse_function_call<2>(operation.type,internal_error); break;
12000                case 3  : branch = parse_function_call<3>(operation.type,internal_error); break;
12001                case 4  : branch = parse_function_call<4>(operation.type,internal_error); break;
12002                case 5  : branch = parse_function_call<5>(operation.type,internal_error); break;
12003                case 6  : branch = parse_function_call<6>(operation.type,internal_error); break;
12004                default :
12005                         {
12006                            set_error(
12007                               make_error(parser_error::e_syntax,
12008                                          current_token_,
12009                                          "ERR15 - Impossible argument count for base function: " + operation_name));
12010                            return error_node();
12011                         }
12012             }
12013 
12014             if (branch)
12015             {
12016                return branch;
12017             }
12018             else if (internal_error)
12019             {
12020                return error_node();
12021             }
12022             remove_last_error();
12023             restore_token();
12024          }
12025 
12026          set_error(
12027             make_error(parser_error::e_syntax,
12028                        current_token_,
12029                        "ERR16 - Invalid parameter count for function: " + operation_name));
12030          return error_node();
12031       }
12032 
12033       inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
12034       {
12035          // Parse: [if][(][condition][,][consequent][,][alternative][)]
12036 
12037          expression_node_ptr consequent  = error_node();
12038          expression_node_ptr alternative = error_node();
12039 
12040          bool result = true;
12041 
12042          if (!token_is(token_t::e_comma))
12043          {
12044             set_error(
12045                make_error(parser_error::e_syntax,
12046                           current_token_,
12047                           "ERR17 - Expected ',' between if-statement condition and consequent"));
12048             result = false;
12049          }
12050          else if (0 == (consequent = parse_expression()))
12051          {
12052             set_error(
12053                make_error(parser_error::e_syntax,
12054                           current_token_,
12055                           "ERR18 - Failed to parse consequent for if-statement"));
12056             result = false;
12057          }
12058          else if (!token_is(token_t::e_comma))
12059          {
12060             set_error(
12061                make_error(parser_error::e_syntax,
12062                           current_token_,
12063                           "ERR19 - Expected ',' between if-statement consequent and alternative"));
12064             result = false;
12065          }
12066          else if (0 == (alternative = parse_expression()))
12067          {
12068             set_error(
12069                make_error(parser_error::e_syntax,
12070                           current_token_,
12071                           "ERR20 - Failed to parse alternative for if-statement"));
12072             result = false;
12073          }
12074          else if (!token_is(token_t::e_rbracket))
12075          {
12076             set_error(
12077                make_error(parser_error::e_syntax,
12078                           current_token_,
12079                           "ERR21 - Expected ')' at end of if-statement"));
12080             result = false;
12081          }
12082 
12083          if (!result)
12084          {
12085             free_node(node_allocator_,condition  );
12086             free_node(node_allocator_,consequent );
12087             free_node(node_allocator_,alternative);
12088             return error_node();
12089          }
12090          else
12091             return expression_generator_.conditional(condition,consequent,alternative);
12092       }
12093 
12094       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
12095       {
12096          expression_node_ptr consequent  = error_node();
12097          expression_node_ptr alternative = error_node();
12098 
12099          bool result = true;
12100 
12101          if (token_is(token_t::e_lcrlbracket,false))
12102          {
12103             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
12104             {
12105                set_error(
12106                   make_error(parser_error::e_syntax,
12107                              current_token_,
12108                              "ERR22 - Failed to parse body of consequent for if-statement"));
12109                result = false;
12110             }
12111          }
12112          else
12113          {
12114             if (
12115                  commutative_check_enabled() &&
12116                  token_is(token_t::e_mul,false)
12117                )
12118             {
12119                next_token();
12120             }
12121 
12122             if (0 != (consequent = parse_expression()))
12123             {
12124                if (!token_is(token_t::e_eof))
12125                {
12126                   set_error(
12127                      make_error(parser_error::e_syntax,
12128                                 current_token_,
12129                                 "ERR23 - Expected ';' at the end of the consequent for if-statement"));
12130                   result = false;
12131                }
12132             }
12133             else
12134             {
12135                set_error(
12136                   make_error(parser_error::e_syntax,
12137                              current_token_,
12138                              "ERR24 - Failed to parse body of consequent for if-statement"));
12139                result = false;
12140             }
12141          }
12142 
12143          std::string symbol = current_token_.value;
12144          if (result)
12145          {
12146             if (details::imatch(current_token_.value,"else"))
12147             {
12148                next_token();
12149 
12150                if (token_is(token_t::e_lcrlbracket,false))
12151                {
12152                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
12153                   {
12154                      set_error(
12155                         make_error(parser_error::e_syntax,
12156                                    current_token_,
12157                                    "ERR25 - Failed to parse body of the 'else' for if-statement"));
12158                      result = false;
12159                   }
12160                }
12161                else if (details::imatch(current_token_.value,"if"))
12162                {
12163                   if (0 == (alternative = parse_conditional_statement()))
12164                   {
12165                      set_error(
12166                         make_error(parser_error::e_syntax,
12167                                    current_token_,
12168                                    "ERR26 - Failed to parse body of if-else statement"));
12169                      result = false;
12170                   }
12171                }
12172                else if (0 != (alternative = parse_expression()))
12173                {
12174                   if (!token_is(token_t::e_eof))
12175                   {
12176                      set_error(
12177                         make_error(parser_error::e_syntax,
12178                                    current_token_,
12179                                    "ERR27 - Expected ';' at the end of the 'else-if' for the if-statement"));
12180                      result = false;
12181                   }
12182                }
12183                else
12184                {
12185                   set_error(
12186                      make_error(parser_error::e_syntax,
12187                                 current_token_,
12188                                 "ERR28 - Failed to parse body of the 'else' for if-statement"));
12189                   result = false;
12190                }
12191             }
12192          }
12193 
12194          if (!result)
12195          {
12196             free_node(node_allocator_,condition  );
12197             free_node(node_allocator_,consequent );
12198             free_node(node_allocator_,alternative);
12199             return error_node();
12200          }
12201          else
12202             return expression_generator_.conditional(condition,consequent,alternative);
12203       }
12204 
12205       inline expression_node_ptr parse_conditional_statement()
12206       {
12207          expression_node_ptr condition   = error_node();
12208 
12209          next_token();
12210 
12211          if (!token_is(token_t::e_lbracket))
12212          {
12213             set_error(
12214                make_error(parser_error::e_syntax,
12215                           current_token_,
12216                           "ERR29 - Expected '(' at start of if-statement, instead got: '" + current_token_.value + "'"));
12217             return error_node();
12218          }
12219          else if (0 == (condition = parse_expression()))
12220          {
12221             set_error(
12222                make_error(parser_error::e_syntax,
12223                           current_token_,
12224                           "ERR30 - Failed to parse condition for if-statement"));
12225             return error_node();
12226          }
12227          else if (token_is(token_t::e_comma,false))
12228          {
12229             // if (x,y,z)
12230             return parse_conditional_statement_01(condition);
12231          }
12232          else if (token_is(token_t::e_rbracket))
12233          {
12234             // 00. if (x) y;
12235             // 01. if (x) y; else z;
12236             // 02. if (x) y; else {z0; ... zn;}
12237             // 03. if (x) y; else if (z) w;
12238             // 04. if (x) y; else if (z) w; else u;
12239             // 05. if (x) y; else if (z) w; else {u0; ... un;}
12240             // 06. if (x) y; else if (z) {w0; ... wn;}
12241             // 07. if (x) {y0; ... yn;}
12242             // 08. if (x) {y0; ... yn;} else z;
12243             // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
12244             // 10. if (x) {y0; ... yn;} else if (z) w;
12245             // 11. if (x) {y0; ... yn;} else if (z) w; else u;
12246             // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
12247             // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
12248             return parse_conditional_statement_02(condition);
12249          }
12250 
12251          set_error(
12252             make_error(parser_error::e_syntax,
12253                        current_token_,
12254                        "ERR31 - Invalid if-statement"));
12255 
12256          free_node(node_allocator_,condition);
12257 
12258          return error_node();
12259       }
12260 
12261       inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
12262       {
12263          // Parse: [condition][?][consequent][:][alternative]
12264          expression_node_ptr consequent  = error_node();
12265          expression_node_ptr alternative = error_node();
12266 
12267          bool result = true;
12268 
12269          if (0 == condition)
12270          {
12271             set_error(
12272                make_error(parser_error::e_syntax,
12273                           current_token_,
12274                           "ERR32 - Encountered invalid condition branch for ternary if-statement"));
12275             return error_node();
12276          }
12277          else if (!token_is(token_t::e_ternary))
12278          {
12279             set_error(
12280                make_error(parser_error::e_syntax,
12281                           current_token_,
12282                           "ERR33 - Expected '?' after condition of ternary if-statement"));
12283             result = false;
12284          }
12285          else if (0 == (consequent = parse_expression()))
12286          {
12287             set_error(
12288                make_error(parser_error::e_syntax,
12289                           current_token_,
12290                           "ERR34 - Failed to parse consequent for if-statement"));
12291             result = false;
12292          }
12293          else if (!token_is(token_t::e_colon))
12294          {
12295             set_error(
12296                make_error(parser_error::e_syntax,
12297                           current_token_,
12298                           "ERR35 - Expected ':' between ternary if-statement consequent and alternative"));
12299             result = false;
12300          }
12301          else if (0 == (alternative = parse_expression()))
12302          {
12303             set_error(
12304                make_error(parser_error::e_syntax,
12305                           current_token_,
12306                           "ERR36 - Failed to parse alternative for if-statement"));
12307             result = false;
12308          }
12309 
12310          if (!result)
12311          {
12312             free_node(node_allocator_,condition  );
12313             free_node(node_allocator_,consequent );
12314             free_node(node_allocator_,alternative);
12315             return error_node();
12316          }
12317          else
12318             return expression_generator_.conditional(condition,consequent,alternative);
12319       }
12320 
12321       inline expression_node_ptr parse_while_loop()
12322       {
12323          // Parse: [while][(][test expr][)][{][expression][}]
12324          expression_node_ptr condition   = error_node();
12325          expression_node_ptr branch      = error_node();
12326          expression_node_ptr result_node = error_node();
12327 
12328          bool result = true;
12329 
12330          next_token();
12331 
12332          if (!token_is(token_t::e_lbracket))
12333          {
12334             set_error(
12335                make_error(parser_error::e_syntax,
12336                           current_token_,
12337                           "ERR37 - Expected '(' at start of while-statement condition"));
12338             return error_node();
12339          }
12340          else if (0 == (condition = parse_expression()))
12341          {
12342             set_error(
12343                make_error(parser_error::e_syntax,
12344                           current_token_,
12345                           "ERR38 - Failed to parse condition for while-loop"));
12346             return error_node();
12347          }
12348          else if (!token_is(token_t::e_rbracket))
12349          {
12350             set_error(
12351                make_error(parser_error::e_syntax,
12352                           current_token_,
12353                           "ERR39 - Expected ')' at end of while-statement condition"));
12354             result = false;
12355          }
12356 
12357          brkcnt_list_.push_front(false);
12358 
12359          if (result)
12360          {
12361             if (0 == (branch = parse_multi_sequence("while-loop")))
12362             {
12363                set_error(
12364                   make_error(parser_error::e_syntax,
12365                              current_token_,
12366                              "ERR40 - Failed to parse body of while-loop"));
12367                result = false;
12368             }
12369             else if (0 == (result_node = expression_generator_.while_loop(condition,
12370                                                                           branch,
12371                                                                           brkcnt_list_.front())))
12372             {
12373                set_error(
12374                   make_error(parser_error::e_syntax,
12375                              current_token_,
12376                              "ERR41 - Failed to synthesize while-loop"));
12377                result = false;
12378             }
12379          }
12380 
12381          if (!result)
12382          {
12383             free_node(node_allocator_,condition  );
12384             free_node(node_allocator_,branch     );
12385             free_node(node_allocator_,result_node);
12386             brkcnt_list_.pop_front();
12387             return error_node();
12388          }
12389          else
12390             return result_node;
12391       }
12392 
12393       inline expression_node_ptr parse_repeat_until_loop()
12394       {
12395          // Parse: [repeat][{][expression][}][until][(][test expr][)]
12396          expression_node_ptr condition = error_node();
12397          expression_node_ptr branch    = error_node();
12398          next_token();
12399 
12400          std::deque<expression_node_ptr> arg_list;
12401          scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
12402 
12403          {
12404             token_t::token_type seperator = token_t::e_eof;
12405 
12406             brkcnt_list_.push_front(false);
12407 
12408             for (;;)
12409             {
12410                expression_node_ptr arg = parse_expression();
12411 
12412                if (0 == arg)
12413                   return error_node();
12414                else
12415                   arg_list.push_back(arg);
12416 
12417                if (details::imatch(current_token_.value,"until"))
12418                {
12419                   next_token();
12420                   break;
12421                }
12422                else if (!token_is(seperator))
12423                {
12424                   set_error(
12425                      make_error(parser_error::e_syntax,
12426                                 current_token_,
12427                                 "ERR42 - Expected '" + token_t::to_str(seperator) + "' for body of repeat until loop"));
12428                   return error_node();
12429                }
12430 
12431                if (details::imatch(current_token_.value,"until"))
12432                {
12433                   next_token();
12434                   break;
12435                }
12436             }
12437 
12438             branch = simplify(arg_list);
12439 
12440             sdd.delete_ptr = (0 == branch);
12441 
12442             if (0 == branch)
12443             {
12444                set_error(
12445                   make_error(parser_error::e_syntax,
12446                              current_token_,
12447                              "ERR43 - Failed to parse body of repeat until loop"));
12448                brkcnt_list_.pop_front();
12449                return error_node();
12450             }
12451          }
12452 
12453          if (!token_is(token_t::e_lbracket))
12454          {
12455             set_error(
12456                make_error(parser_error::e_syntax,
12457                           current_token_,
12458                           "ERR44 - Expected '(' before condition of repeat until loop"));
12459             brkcnt_list_.pop_front();
12460             return error_node();
12461          }
12462          else if (0 == (condition = parse_expression()))
12463          {
12464             set_error(
12465                make_error(parser_error::e_syntax,
12466                           current_token_,
12467                           "ERR45 - Failed to parse condition for repeat until loop"));
12468             brkcnt_list_.pop_front();
12469             return error_node();
12470          }
12471          else if (!token_is(token_t::e_rbracket))
12472          {
12473             set_error(
12474                make_error(parser_error::e_syntax,
12475                           current_token_,
12476                           "ERR46 - Expected ')' after condition of repeat until loop"));
12477             free_node(node_allocator_,condition);
12478             brkcnt_list_.pop_front();
12479             return error_node();
12480          }
12481 
12482          expression_node_ptr result;
12483 
12484          if (0 == (result = expression_generator_.repeat_until_loop(condition,branch,brkcnt_list_.front())))
12485          {
12486             set_error(
12487                make_error(parser_error::e_syntax,
12488                           current_token_,
12489                           "ERR47 - Failed to synthesize repeat until loop"));
12490             free_node(node_allocator_,condition);
12491             brkcnt_list_.pop_front();
12492             return error_node();
12493          }
12494          else
12495          {
12496             brkcnt_list_.pop_front();
12497             return result;
12498          }
12499       }
12500 
12501       inline expression_node_ptr parse_for_loop()
12502       {
12503          expression_node_ptr initializer = error_node();
12504          expression_node_ptr condition   = error_node();
12505          expression_node_ptr incrementor = error_node();
12506          expression_node_ptr loop_body   = error_node();
12507          expression_node_ptr loop_var    = error_node();
12508          T* loop_counter = 0;
12509          bool result = true;
12510          std::string loop_counter_symbol;
12511 
12512          next_token();
12513 
12514          if (!token_is(token_t::e_lbracket))
12515          {
12516             set_error(
12517                make_error(parser_error::e_syntax,
12518                           current_token_,
12519                           "ERR48 - Expected '(' at start of for-loop"));
12520             return error_node();
12521          }
12522 
12523          if (!token_is(token_t::e_eof))
12524          {
12525             if (!token_is(token_t::e_symbol,false))
12526             {
12527                set_error(
12528                   make_error(parser_error::e_syntax,
12529                              current_token_,
12530                              "ERR49 - Expected a variable at the start of initializer section of for-loop"));
12531                return error_node();
12532             }
12533             else if (!peek_token_is(token_t::e_assign))
12534             {
12535                set_error(
12536                   make_error(parser_error::e_syntax,
12537                              current_token_,
12538                              "ERR50 - Expected variable assignment of initializer section of for-loop"));
12539                return error_node();
12540             }
12541 
12542             loop_counter_symbol = current_token_.value;
12543 
12544             if (local_symbol_table_.is_variable(loop_counter_symbol))
12545             {
12546                set_error(
12547                   make_error(parser_error::e_syntax,
12548                              current_token_,
12549                              "ERR51 - For-loop variable '" +loop_counter_symbol+ "' is being shadowed by a previous declaration"));
12550                return error_node();
12551             }
12552             else if (!symbol_table_.is_variable(loop_counter_symbol))
12553             {
12554                loop_counter = new T(T(0));
12555                local_symbol_table_.add_variable(loop_counter_symbol,*loop_counter);
12556                loop_var = local_symbol_table_.get_variable(loop_counter_symbol);
12557             }
12558 
12559             if (0 == (initializer = parse_expression()))
12560             {
12561                set_error(
12562                   make_error(parser_error::e_syntax,
12563                              current_token_,
12564                              "ERR52 - Failed to parse initializer of for-loop"));
12565                result = false;
12566             }
12567 
12568             if (!token_is(token_t::e_eof))
12569             {
12570                set_error(
12571                   make_error(parser_error::e_syntax,
12572                              current_token_,
12573                              "ERR53 - Expected ';' after initializer of for-loop"));
12574                result = false;
12575             }
12576          }
12577 
12578          if (!token_is(token_t::e_eof))
12579          {
12580             if (0 == (condition = parse_expression()))
12581             {
12582                set_error(
12583                   make_error(parser_error::e_syntax,
12584                              current_token_,
12585                              "ERR54 - Failed to parse condition of for-loop"));
12586                result = false;
12587             }
12588             else if (!token_is(token_t::e_eof))
12589             {
12590                set_error(
12591                   make_error(parser_error::e_syntax,
12592                              current_token_,
12593                              "ERR55 - Expected ';' after condition section of for-loop"));
12594                result = false;
12595             }
12596          }
12597 
12598          if (!token_is(token_t::e_rbracket))
12599          {
12600             if (0 == (incrementor = parse_expression()))
12601             {
12602                set_error(
12603                   make_error(parser_error::e_syntax,
12604                              current_token_,
12605                              "ERR56 - Failed to parse incrementor of for-loop"));
12606                result = false;
12607             }
12608             else if (!token_is(token_t::e_rbracket))
12609             {
12610                set_error(
12611                   make_error(parser_error::e_syntax,
12612                              current_token_,
12613                              "ERR57 - Expected ')' after incrementor section of for-loop"));
12614                result = false;
12615             }
12616          }
12617 
12618          if (result)
12619          {
12620             brkcnt_list_.push_front(false);
12621             if (0 == (loop_body = parse_multi_sequence("for-loop")))
12622             {
12623                set_error(
12624                   make_error(parser_error::e_syntax,
12625                              current_token_,
12626                              "ERR58 - Failed to parse body of for-loop"));
12627                result = false;
12628             }
12629          }
12630 
12631          if (!result)
12632          {
12633             local_symbol_table_.remove_variable(loop_counter_symbol);
12634             free_node(node_allocator_,initializer);
12635             free_node(node_allocator_,condition  );
12636             free_node(node_allocator_,incrementor);
12637             free_node(node_allocator_,loop_body  );
12638             delete loop_counter;
12639             brkcnt_list_.pop_front();
12640             return error_node();
12641          }
12642          else
12643          {
12644             if (loop_counter && !loop_counter_symbol.empty())
12645             {
12646                local_symbol_table_.remove_variable(loop_counter_symbol,false);
12647             }
12648 
12649             expression_node_ptr result_node =
12650                    expression_generator_.for_loop(initializer,
12651                                                   condition,
12652                                                   incrementor,
12653                                                   loop_body,
12654                                                   loop_var,
12655                                                   loop_counter,
12656                                                   brkcnt_list_.front());
12657             brkcnt_list_.pop_front();
12658             return result_node;
12659          }
12660       }
12661 
12662       inline expression_node_ptr parse_switch_statement()
12663       {
12664          std::vector<expression_node_ptr> arg_list;
12665          expression_node_ptr result = error_node();
12666 
12667          const std::string symbol = current_token_.value;
12668 
12669          if (!details::imatch(current_token_.value,"switch"))
12670          {
12671             set_error(
12672                make_error(parser_error::e_syntax,
12673                           current_token_,
12674                           "ERR59 - Expected keyword 'switch'"));
12675             return error_node();
12676          }
12677 
12678          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
12679 
12680          next_token();
12681 
12682          if (!token_is(token_t::e_lcrlbracket))
12683          {
12684             set_error(
12685                make_error(parser_error::e_syntax,
12686                           current_token_,
12687                           "ERR60 - Expected '{' for call to switch statement"));
12688             return error_node();
12689          }
12690 
12691          for ( ; ; )
12692          {
12693             if (!details::imatch("case",current_token_.value))
12694             {
12695                set_error(
12696                   make_error(parser_error::e_syntax,
12697                              current_token_,
12698                              "ERR61 - Expected either a 'case' or 'default' statement"));
12699                return error_node();
12700             }
12701 
12702             next_token();
12703 
12704             expression_node_ptr condition = parse_expression();
12705 
12706             if (0 == condition)
12707                return error_node();
12708 
12709             if (!token_is(token_t::e_colon))
12710             {
12711                set_error(
12712                   make_error(parser_error::e_syntax,
12713                              current_token_,
12714                              "ERR62 - Expected ':' for case of switch statement"));
12715                return error_node();
12716             }
12717 
12718             expression_node_ptr consequent = parse_expression();
12719 
12720             if (0 == consequent)
12721                return error_node();
12722 
12723             if (!token_is(token_t::e_eof))
12724             {
12725                set_error(
12726                   make_error(parser_error::e_syntax,
12727                              current_token_,
12728                              "ERR63 - Expected ';' at end of case for switch statement"));
12729                return error_node();
12730             }
12731 
12732             // Can we optimize away the case statement?
12733             if (is_constant_node(condition) && is_false(condition))
12734             {
12735                free_node(node_allocator_,condition);
12736                free_node(node_allocator_,consequent);
12737                condition  = 0;
12738                consequent = 0;
12739             }
12740             else
12741             {
12742                arg_list.push_back(condition);
12743                arg_list.push_back(consequent);
12744             }
12745 
12746             if (details::imatch("default",current_token_.value))
12747             {
12748                next_token();
12749                if (!token_is(token_t::e_colon))
12750                {
12751                   set_error(
12752                      make_error(parser_error::e_syntax,
12753                                 current_token_,
12754                                 "ERR64 - Expected ':' for default of switch statement"));
12755                   return error_node();
12756                }
12757 
12758                expression_node_ptr default_statement = parse_expression();
12759                if (0 == default_statement)
12760                   return error_node();
12761                else if (!token_is(token_t::e_eof))
12762                {
12763                   set_error(
12764                      make_error(parser_error::e_syntax,
12765                                 current_token_,
12766                                 "ERR65 - Expected ';' at end of default for switch statement"));
12767                   return error_node();
12768                }
12769 
12770                arg_list.push_back(default_statement);
12771                break;
12772             }
12773          }
12774 
12775          if (!token_is(token_t::e_rcrlbracket))
12776          {
12777             set_error(
12778                make_error(parser_error::e_syntax,
12779                           current_token_,
12780                           "ERR66 - Expected '}' at end of switch statement"));
12781             return error_node();
12782          }
12783 
12784          result = expression_generator_.switch_statement(arg_list);
12785 
12786          sdd.delete_ptr = (0 == result);
12787          return result;
12788       }
12789 
12790       inline expression_node_ptr parse_multi_switch_statement()
12791       {
12792          std::vector<expression_node_ptr> arg_list;
12793          expression_node_ptr result = error_node();
12794 
12795          const std::string symbol = current_token_.value;
12796 
12797          if (!details::imatch(current_token_.value,"[*]"))
12798          {
12799             set_error(
12800                make_error(parser_error::e_syntax,
12801                           current_token_,
12802                           "ERR67 - Expected token '[*]'"));
12803             return error_node();
12804          }
12805 
12806          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
12807 
12808          next_token();
12809 
12810          if (!token_is(token_t::e_lcrlbracket))
12811          {
12812             set_error(
12813                make_error(parser_error::e_syntax,
12814                           current_token_,
12815                           "ERR68 - Expected '{' for call to [*] statement"));
12816             return error_node();
12817          }
12818 
12819          for ( ; ; )
12820          {
12821             if (!details::imatch("case",current_token_.value))
12822             {
12823                set_error(
12824                   make_error(parser_error::e_syntax,
12825                              current_token_,
12826                              "ERR69 - Expected a 'case' statement for multi-switch"));
12827                return error_node();
12828             }
12829 
12830             next_token();
12831 
12832             expression_node_ptr condition = parse_expression();
12833             if (0 == condition)
12834                return error_node();
12835 
12836             if (!token_is(token_t::e_colon))
12837             {
12838                set_error(
12839                   make_error(parser_error::e_syntax,
12840                              current_token_,
12841                              "ERR70 - Expected ':' for case of [*] statement"));
12842                return error_node();
12843             }
12844 
12845             expression_node_ptr consequent = parse_expression();
12846             if (0 == consequent)
12847                return error_node();
12848 
12849             if (!token_is(token_t::e_eof))
12850             {
12851                set_error(
12852                   make_error(parser_error::e_syntax,
12853                              current_token_,
12854                              "ERR71 - Expected ';' at end of case for [*] statement"));
12855                return error_node();
12856             }
12857 
12858             // Can we optimize away the case statement?
12859             if (is_constant_node(condition) && is_false(condition))
12860             {
12861                free_node(node_allocator_,condition);
12862                free_node(node_allocator_,consequent);
12863                condition  = 0;
12864                consequent = 0;
12865             }
12866             else
12867             {
12868                arg_list.push_back(condition);
12869                arg_list.push_back(consequent);
12870             }
12871 
12872             if (token_is(token_t::e_rcrlbracket,false))
12873             {
12874                break;
12875             }
12876          }
12877 
12878          if (!token_is(token_t::e_rcrlbracket))
12879          {
12880             set_error(
12881                make_error(parser_error::e_syntax,
12882                           current_token_,
12883                           "ERR72 - Expected '}' at end of [*] statement"));
12884             return error_node();
12885          }
12886 
12887          result = expression_generator_.multi_switch_statement(arg_list);
12888 
12889          sdd.delete_ptr = (0 == result);
12890          return result;
12891       }
12892 
12893       inline expression_node_ptr parse_vararg_function()
12894       {
12895          std::deque<expression_node_ptr> arg_list;
12896          expression_node_ptr result = error_node();
12897 
12898          details::operator_type opt_type = details::e_default;
12899          const std::string symbol = current_token_.value;
12900 
12901          if (details::imatch(symbol,"~"))
12902          {
12903             next_token();
12904             return parse_multi_sequence();
12905          }
12906          else if (details::imatch(symbol,"[*]"))
12907          {
12908             return parse_multi_switch_statement();
12909          }
12910          else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum;
12911          else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod;
12912          else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg;
12913          else if (details::imatch(symbol,"min" )) opt_type = details::e_min;
12914          else if (details::imatch(symbol,"max" )) opt_type = details::e_max;
12915          else if (details::imatch(symbol,"mand")) opt_type = details::e_mand;
12916          else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor;
12917          else
12918          {
12919             set_error(
12920                make_error(parser_error::e_syntax,
12921                           current_token_,
12922                           "ERR73 - Unsupported vararg function: " + symbol));
12923             return error_node();
12924          }
12925 
12926          scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
12927 
12928          next_token();
12929          if (!token_is(token_t::e_lbracket))
12930          {
12931             set_error(
12932                make_error(parser_error::e_syntax,
12933                           current_token_,
12934                           "ERR74 - Expected '(' for call to vararg function: " + symbol));
12935             return error_node();
12936          }
12937 
12938          for ( ; ; )
12939          {
12940             expression_node_ptr arg = parse_expression();
12941             if (0 == arg)
12942                return error_node();
12943             else
12944                arg_list.push_back(arg);
12945 
12946             if (token_is(token_t::e_rbracket))
12947                break;
12948             else if (!token_is(token_t::e_comma))
12949             {
12950                set_error(
12951                   make_error(parser_error::e_syntax,
12952                              current_token_,
12953                              "ERR75 - Expected ',' for call to vararg function: " + symbol));
12954                return error_node();
12955             }
12956          }
12957 
12958          result = expression_generator_.vararg_function(opt_type,arg_list);
12959 
12960          sdd.delete_ptr = (0 == result);
12961          return result;
12962       }
12963 
12964       template <typename Allocator,
12965                 template <typename,typename> class Sequence>
12966       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list)
12967       {
12968          if (expression_list.empty())
12969             return error_node();
12970          else if (1 == expression_list.size())
12971             return expression_list[0];
12972 
12973          Sequence<expression_node_ptr,Allocator> tmp_expression_list;
12974 
12975          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
12976          {
12977             if (is_variable_node(expression_list[i]))
12978                continue;
12979             else if (is_constant_node(expression_list[i]))
12980             {
12981                free_node(node_allocator_,expression_list[i]);
12982                continue;
12983             }
12984             else
12985                tmp_expression_list.push_back(expression_list[i]);
12986          }
12987 
12988          tmp_expression_list.push_back(expression_list.back());
12989          expression_list.swap(tmp_expression_list);
12990          return expression_generator_.vararg_function(details::e_multi,expression_list);
12991       }
12992 
12993       inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
12994       {
12995          token_t::token_type close_bracket = token_t::e_rcrlbracket;
12996          token_t::token_type seperator     = token_t::e_eof;
12997 
12998          if (!token_is(token_t::e_lcrlbracket))
12999          {
13000             if (token_is(token_t::e_lbracket))
13001             {
13002                close_bracket = token_t::e_rbracket;
13003                seperator     = token_t::e_comma;
13004             }
13005             else
13006             {
13007                set_error(
13008                   make_error(parser_error::e_syntax,
13009                              current_token_,
13010                              "ERR76 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
13011                              ((!source.empty()) ? std::string(" section of " + source): "")));
13012                return error_node();
13013             }
13014          }
13015 
13016          std::deque<expression_node_ptr> arg_list;
13017          expression_node_ptr result = error_node();
13018 
13019          scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
13020 
13021          for (;;)
13022          {
13023             expression_node_ptr arg = parse_expression();
13024             if (0 == arg)
13025                return error_node();
13026             else
13027                arg_list.push_back(arg);
13028             if (token_is(close_bracket))
13029                break;
13030 
13031             bool is_next_close = peek_token_is(close_bracket);
13032 
13033             if (!token_is(seperator) && is_next_close)
13034             {
13035                set_error(
13036                   make_error(parser_error::e_syntax,
13037                              current_token_,
13038                              "ERR77 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source));
13039                return error_node();
13040             }
13041 
13042             if (token_is(close_bracket))
13043                break;
13044          }
13045 
13046          result = simplify(arg_list);
13047 
13048          sdd.delete_ptr = (0 == result);
13049          return result;
13050       }
13051 
13052       struct range_pack
13053       {
13054          range_pack()
13055          : n0_e(std::make_pair(false,expression_node_ptr(0))),
13056            n1_e(std::make_pair(false,expression_node_ptr(0))),
13057            n0_c(std::make_pair(false,0)),
13058            n1_c(std::make_pair(false,0))
13059          {}
13060 
13061          void clear()
13062          {
13063             n0_e = std::make_pair(false,expression_node_ptr(0));
13064             n1_e = std::make_pair(false,expression_node_ptr(0));
13065             n0_c = std::make_pair(false,0);
13066             n1_c = std::make_pair(false,0);
13067          }
13068 
13069          void free()
13070          {
13071             if (n0_e.first && n0_e.second)
13072             {
13073                n0_e.first = false;
13074                if (!details::is_variable_node(n0_e.second))
13075                {
13076                   delete n0_e.second;
13077                }
13078             }
13079             if (n1_e.first && n1_e.second)
13080             {
13081                n1_e.first = false;
13082                if (!details::is_variable_node(n1_e.second))
13083                {
13084                   delete n1_e.second;
13085                }
13086             }
13087          }
13088 
13089          bool const_range()
13090          {
13091            return ( n0_c.first &&  n1_c.first) &&
13092                   (!n0_e.first && !n1_e.first);
13093          }
13094 
13095          bool var_range()
13096          {
13097            return ( n0_e.first &&  n1_e.first) &&
13098                   (!n0_c.first && !n1_c.first);
13099          }
13100 
13101          bool operator()(std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
13102          {
13103             if (n0_c.first)
13104                r0 = n0_c.second;
13105             else if (n0_e.first)
13106             {
13107                T r0_value = n0_e.second->value();
13108                if (r0_value < 0)
13109                   return false;
13110                else
13111                   r0 = static_cast<std::size_t>(r0_value);
13112             }
13113             else
13114                return false;
13115 
13116             if (n1_c.first)
13117                r1 = n1_c.second;
13118             else if (n1_e.first)
13119             {
13120                T r1_value = n1_e.second->value();
13121                if (r1_value < 0)
13122                   return false;
13123                else
13124                   r1 = static_cast<std::size_t>(r1_value);
13125             }
13126             else
13127                return false;
13128 
13129             if (
13130                  (std::numeric_limits<std::size_t>::max() != size) &&
13131                  (std::numeric_limits<std::size_t>::max() == r1  )
13132                )
13133             {
13134                r1 = size;
13135             }
13136 
13137             return (r0 <= r1);
13138          }
13139 
13140          std::pair<bool,expression_node_ptr> n0_e;
13141          std::pair<bool,expression_node_ptr> n1_e;
13142          std::pair<bool,std::size_t        > n0_c;
13143          std::pair<bool,std::size_t        > n1_c;
13144       };
13145 
13146       inline bool parse_range(range_pack& rp)
13147       {
13148          // Examples of valid ranges:
13149          // 1. [1:5]     -> 1..5
13150          // 2. [ :5]     -> 0..5
13151          // 3. [1: ]     -> 1..end
13152          // 4. [x:y]     -> x..y where x <= y
13153          // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
13154          // 6. [ :y]     -> 0..y where 0 <= y
13155          // 7. [x: ]     -> x..end where x <= end
13156 
13157          rp.clear();
13158 
13159          if (!token_is(token_t::e_lsqrbracket))
13160          {
13161             set_error(
13162                make_error(parser_error::e_syntax,
13163                           current_token_,
13164                           "ERR78 - Expected '[' for start of range"));
13165             return false;
13166          }
13167 
13168          if (token_is(token_t::e_colon))
13169          {
13170             rp.n0_c.first  = true;
13171             rp.n0_c.second = 0;
13172          }
13173          else
13174          {
13175             expression_node_ptr r0 = parse_expression();
13176 
13177             if (0 == r0)
13178             {
13179                set_error(
13180                   make_error(parser_error::e_syntax,
13181                              current_token_,
13182                              "ERR79 - Failed parse begin section of range"));
13183                return false;
13184 
13185             }
13186             else if (is_constant_node(r0))
13187             {
13188                T r0_value = r0->value();
13189                if (r0_value >= T(0))
13190                {
13191                   rp.n0_c.first  = true;
13192                   rp.n0_c.second = static_cast<std::size_t>(r0_value);
13193                }
13194                free_node(node_allocator_,r0);
13195                if (r0_value < T(0))
13196                {
13197                   set_error(
13198                      make_error(parser_error::e_syntax,
13199                                 current_token_,
13200                                 "ERR80 - Range lower bound less than zero! Constraint: r0 >= 0"));
13201                   return false;
13202                }
13203             }
13204             else
13205             {
13206                rp.n0_e.first  = true;
13207                rp.n0_e.second = r0;
13208             }
13209 
13210             if (!token_is(token_t::e_colon))
13211             {
13212                set_error(
13213                   make_error(parser_error::e_syntax,
13214                              current_token_,
13215                              "ERR81 - Expected ':' for break  in range"));
13216                rp.free();
13217                return false;
13218             }
13219          }
13220 
13221          if (token_is(token_t::e_rsqrbracket))
13222          {
13223             rp.n1_c.first  = true;
13224             rp.n1_c.second = std::numeric_limits<std::size_t>::max();
13225          }
13226          else
13227          {
13228             expression_node_ptr r1 = parse_expression();
13229 
13230             if (0 == r1)
13231             {
13232                set_error(
13233                   make_error(parser_error::e_syntax,
13234                              current_token_,
13235                              "ERR82 - Failed parse end section of range"));
13236                rp.free();
13237                return false;
13238 
13239             }
13240             else if (is_constant_node(r1))
13241             {
13242                T r1_value = r1->value();
13243                if (r1_value >= T(0))
13244                {
13245                   rp.n1_c.first  = true;
13246                   rp.n1_c.second = static_cast<std::size_t>(r1_value);
13247                }
13248                free_node(node_allocator_,r1);
13249                if (r1_value < T(0))
13250                {
13251                   set_error(
13252                      make_error(parser_error::e_syntax,
13253                                 current_token_,
13254                                 "ERR83 - Range upper bound less than zero! Constraint: r1 >= 0"));
13255                   return false;
13256                }
13257             }
13258             else
13259             {
13260                rp.n1_e.first  = true;
13261                rp.n1_e.second = r1;
13262             }
13263 
13264             if (!token_is(token_t::e_rsqrbracket))
13265             {
13266                set_error(
13267                   make_error(parser_error::e_syntax,
13268                              current_token_,
13269                              "ERR84 - Expected ']' for start of range"));
13270                rp.free();
13271                return false;
13272             }
13273          }
13274 
13275          if (rp.const_range())
13276          {
13277             std::size_t r0 = 0;
13278             std::size_t r1 = 0;
13279             bool rp_result = rp(r0,r1);
13280             if (!rp_result || (r0 > r1))
13281             {
13282                set_error(
13283                   make_error(parser_error::e_syntax,
13284                              current_token_,
13285                              "ERR85 - Invalid range, Constraint: r0 <= r1"));
13286                return false;
13287             }
13288          }
13289 
13290          return true;
13291       }
13292 
13293       inline void cache_symbol(const std::string& symbol)
13294       {
13295          if (symbol_name_caching_)
13296          {
13297             symbol_name_cache_.push_back(symbol);
13298          }
13299       }
13300 
13301       inline expression_node_ptr parse_string()
13302       {
13303          const std::string symbol = current_token_.value;
13304 
13305          if (!symbol_table_.is_conststr_stringvar(symbol))
13306          {
13307             set_error(
13308                make_error(parser_error::e_syntax,
13309                           current_token_,
13310                           "ERR86 - Unknown string symbol"));
13311             return error_node();
13312          }
13313 
13314          expression_node_ptr result = symbol_table_.get_stringvar(symbol);
13315 
13316          if (symbol_table_.is_constant_node(symbol))
13317          {
13318             result = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(result)->str());
13319          }
13320 
13321          cache_symbol(symbol);
13322 
13323          if (peek_token_is(token_t::e_lsqrbracket))
13324          {
13325             next_token();
13326             range_pack rp;
13327             if (!parse_range(rp))
13328             {
13329                free_node(node_allocator_,result);
13330                return error_node();
13331             }
13332             result = expression_generator_(dynamic_cast<details::stringvar_node<T>*>(result)->ref(),rp);
13333             if (result)
13334                rp.clear();
13335          }
13336          else
13337             next_token();
13338 
13339          return result;
13340       }
13341 
13342       inline expression_node_ptr parse_const_string()
13343       {
13344          const std::string const_str = current_token_.value;
13345          expression_node_ptr result = expression_generator_(const_str);
13346 
13347          if (peek_token_is(token_t::e_lsqrbracket))
13348          {
13349             next_token();
13350             range_pack rp;
13351 
13352             if (!parse_range(rp))
13353             {
13354                free_node(node_allocator_,result);
13355                return error_node();
13356             }
13357 
13358             free_node(node_allocator_,result);
13359 
13360             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
13361             {
13362                rp.n1_c.second = const_str.size() - 1;
13363             }
13364 
13365             if (
13366                  (rp.n0_c.first && rp.n0_c.second >= const_str.size()) ||
13367                  (rp.n1_c.first && rp.n1_c.second >= const_str.size())
13368                )
13369             {
13370                set_error(
13371                   make_error(parser_error::e_syntax,
13372                              current_token_,
13373                              "ERR87 - Overflow in range for string: '" + const_str + "'[" +
13374                              (rp.n0_c.first ? details::to_str(rp.n0_c.second) : "?") + ":" +
13375                              (rp.n1_c.first ? details::to_str(rp.n1_c.second) : "?") + "]"));
13376                return error_node();
13377             }
13378 
13379             result = expression_generator_(const_str,rp);
13380 
13381             if (result)
13382                rp.clear();
13383          }
13384          else
13385             next_token();
13386 
13387          return result;
13388       }
13389 
13390       inline expression_node_ptr parse_vector()
13391       {
13392          const std::string symbol       = current_token_.value;
13393          typename symbol_table_t::vector_ptr vec = symbol_table_.get_vector(symbol);
13394          expression_node_ptr index_expr = error_node();
13395 
13396          next_token();
13397          if (!token_is(token_t::e_lsqrbracket))
13398          {
13399             set_error(
13400                make_error(parser_error::e_syntax,
13401                           current_token_,
13402                           "ERR88 - Expected '[' for index of vector: '" + symbol + "'"));
13403             return error_node();
13404          }
13405          else if (token_is(token_t::e_rsqrbracket))
13406          {
13407             return expression_generator_(T(vec->size()));
13408          }
13409          else if (0 == (index_expr = parse_expression()))
13410          {
13411             set_error(
13412                make_error(parser_error::e_syntax,
13413                           current_token_,
13414                           "ERR89 - Failed to parse index for vector: '" + symbol + "'"));
13415             return error_node();
13416          }
13417          else if (!token_is(token_t::e_rsqrbracket))
13418          {
13419             set_error(
13420                make_error(parser_error::e_syntax,
13421                           current_token_,
13422                           "ERR90 - Expected ']' for index of vector: '" + symbol + "'"));
13423             return error_node();
13424          }
13425 
13426          return expression_generator_.vector_element(symbol,vec,index_expr);
13427       }
13428 
13429       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
13430       {
13431          std::vector<expression_node_ptr> arg_list;
13432          expression_node_ptr result = error_node();
13433 
13434          const std::string symbol = current_token_.value;
13435 
13436          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
13437 
13438          next_token();
13439          if (!token_is(token_t::e_lbracket))
13440          {
13441             set_error(
13442                make_error(parser_error::e_syntax,
13443                           current_token_,
13444                           "ERR91 - Expected '(' for call to vararg function: " + vararg_function_name));
13445             return error_node();
13446          }
13447 
13448          if (!token_is(token_t::e_rbracket))
13449          {
13450             for ( ; ; )
13451             {
13452                expression_node_ptr arg = parse_expression();
13453                if (0 == arg)
13454                   return error_node();
13455                else
13456                   arg_list.push_back(arg);
13457 
13458                if (token_is(token_t::e_rbracket))
13459                   break;
13460                else if (!token_is(token_t::e_comma))
13461                {
13462                   set_error(
13463                      make_error(parser_error::e_syntax,
13464                                 current_token_,
13465                                 "ERR92 - Expected ',' for call to vararg function: " + vararg_function_name));
13466                   return error_node();
13467                }
13468             }
13469          }
13470 
13471          result = expression_generator_.vararg_function_call(vararg_function,arg_list);
13472 
13473          sdd.delete_ptr = (0 == result);
13474 
13475          return result;
13476       }
13477 
13478       template <typename Type, std::size_t NumberOfParameters>
13479       struct parse_special_function_impl
13480       {
13481          static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type)
13482          {
13483             expression_node_ptr branch[NumberOfParameters];
13484             expression_node_ptr result  = error_node();
13485             std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
13486             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
13487 
13488             p.next_token();
13489             if (!p.token_is(token_t::e_lbracket))
13490             {
13491                p.set_error(
13492                     make_error(parser_error::e_syntax,
13493                                p.current_token(),
13494                                "ERR93 - Expected '(' for special function"));
13495                return error_node();
13496             }
13497 
13498             for (std::size_t i = 0; i < NumberOfParameters; ++i)
13499             {
13500                branch[i] = p.parse_expression();
13501                if (0 == branch[i])
13502                {
13503                   return p.error_node();
13504                }
13505                else if (i < (NumberOfParameters - 1))
13506                {
13507                   if (!p.token_is(token_t::e_comma))
13508                   {
13509                      p.set_error(
13510                           make_error(parser_error::e_syntax,
13511                                      p.current_token(),
13512                                      "ERR94 - Expected ',' before next parameter of special function"));
13513                      return p.error_node();
13514                   }
13515                }
13516             }
13517 
13518             if (!p.token_is(token_t::e_rbracket))
13519                return p.error_node();
13520             else
13521                result = p.expression_generator_.special_function(opt_type,branch);
13522             sd.delete_ptr = (0 == result);
13523             return result;
13524          }
13525       };
13526 
13527       inline expression_node_ptr parse_special_function()
13528       {
13529          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
13530          if (
13531               !details::is_digit(current_token_.value[2]) ||
13532               !details::is_digit(current_token_.value[3])
13533             )
13534          {
13535             set_error(
13536                make_error(parser_error::e_token,
13537                           current_token_,
13538                           "ERR95 - Invalid special function[1]: " + current_token_.value));
13539             return error_node();
13540          }
13541 
13542          const unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0');
13543 
13544          if (id >= details::e_sffinal)
13545          {
13546             set_error(
13547                make_error(parser_error::e_token,
13548                           current_token_,
13549                           "ERR96 - Invalid special function[2]: " + current_token_.value));
13550             return error_node();
13551          }
13552 
13553          const std::size_t sf_3_to_4 = details::e_sf48;
13554          const details::operator_type opt_type = details::operator_type(id + 1000);
13555          const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4;
13556 
13557          switch (NumberOfParameters)
13558          {
13559             case 3  : return parse_special_function_impl<T,3>::process(*this,opt_type);
13560             case 4  : return parse_special_function_impl<T,4>::process(*this,opt_type);
13561             default : return error_node();
13562          }
13563       }
13564 
13565       inline expression_node_ptr parse_null_statement()
13566       {
13567          next_token();
13568          return node_allocator_.allocate<details::null_node<T> >();
13569       }
13570 
13571       #ifndef exprtk_disable_break_continue
13572       inline expression_node_ptr parse_break_statement()
13573       {
13574          if (!brkcnt_list_.empty())
13575          {
13576             next_token();
13577             brkcnt_list_.front() = true;
13578             expression_node_ptr ret = error_node();
13579             if (token_is(token_t::e_lsqrbracket))
13580             {
13581                if (0 == (ret = parse_expression()))
13582                {
13583                   set_error(
13584                      make_error(parser_error::e_syntax,
13585                                 current_token_,
13586                                 "ERR97 - Failed to parse return expression for 'break' statement"));
13587                   return error_node();
13588                }
13589                else if (!token_is(token_t::e_rsqrbracket))
13590                {
13591                   set_error(
13592                      make_error(parser_error::e_syntax,
13593                                 current_token_,
13594                                 "ERR98 - Expected ']' at the completed of break's return expression"));
13595                   return error_node();
13596                }
13597             }
13598             return node_allocator_.allocate<details::break_node<T> >(ret);
13599          }
13600          else
13601          {
13602             set_error(
13603                make_error(parser_error::e_syntax,
13604                           current_token_,
13605                           "ERR99 - Invalid use of 'break', allowed only in the scope of a loop"));
13606          }
13607          return error_node();
13608       }
13609 
13610       inline expression_node_ptr parse_continue_statement()
13611       {
13612          if (!brkcnt_list_.empty())
13613          {
13614             next_token();
13615             brkcnt_list_.front() = true;
13616             return node_allocator_.allocate<details::continue_node<T> >();
13617          }
13618          else
13619          {
13620             set_error(
13621                make_error(parser_error::e_syntax,
13622                           current_token_,
13623                           "ERR100 - Invalid use of 'continue', allowed only in the scope of a loop"));
13624             return error_node();
13625          }
13626       }
13627       #endif
13628 
13629       inline expression_node_ptr parse_symtab_symbol()
13630       {
13631          const std::string symbol = current_token_.value;
13632          // Are we dealing with a variable or a special constant?
13633          expression_node_ptr variable = symbol_table_.get_variable(symbol);
13634          if (variable)
13635          {
13636             cache_symbol(symbol);
13637             if (symbol_table_.is_constant_node(symbol))
13638             {
13639                variable = expression_generator_(variable->value());
13640             }
13641             next_token();
13642             return variable;
13643          }
13644 
13645          // Are we dealing with a local variable?
13646          variable = local_symbol_table_.get_variable(symbol);
13647          if (variable)
13648          {
13649             cache_symbol(symbol);
13650             if (local_symbol_table_.is_constant_node(symbol))
13651             {
13652                variable = expression_generator_(variable->value());
13653             }
13654             next_token();
13655             return variable;
13656          }
13657 
13658          #ifndef exprtk_disable_string_capabilities
13659          // Are we dealing with a string variable?
13660          if (symbol_table_.is_stringvar(symbol))
13661          {
13662             return parse_string();
13663          }
13664          #endif
13665 
13666          // Are we dealing with a function?
13667          ifunction<T>* function = symbol_table_.get_function(symbol);
13668 
13669          if (function)
13670          {
13671             expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
13672             switch (function->param_count)
13673             {
13674                case  0 : func_node = parse_function_call_0  (function,symbol); break;
13675                case  1 : func_node = parse_function_call< 1>(function,symbol); break;
13676                case  2 : func_node = parse_function_call< 2>(function,symbol); break;
13677                case  3 : func_node = parse_function_call< 3>(function,symbol); break;
13678                case  4 : func_node = parse_function_call< 4>(function,symbol); break;
13679                case  5 : func_node = parse_function_call< 5>(function,symbol); break;
13680                case  6 : func_node = parse_function_call< 6>(function,symbol); break;
13681                case  7 : func_node = parse_function_call< 7>(function,symbol); break;
13682                case  8 : func_node = parse_function_call< 8>(function,symbol); break;
13683                case  9 : func_node = parse_function_call< 9>(function,symbol); break;
13684                case 10 : func_node = parse_function_call<10>(function,symbol); break;
13685                case 11 : func_node = parse_function_call<11>(function,symbol); break;
13686                case 12 : func_node = parse_function_call<12>(function,symbol); break;
13687                case 13 : func_node = parse_function_call<13>(function,symbol); break;
13688                case 14 : func_node = parse_function_call<14>(function,symbol); break;
13689                case 15 : func_node = parse_function_call<15>(function,symbol); break;
13690                case 16 : func_node = parse_function_call<16>(function,symbol); break;
13691                case 17 : func_node = parse_function_call<17>(function,symbol); break;
13692                case 18 : func_node = parse_function_call<18>(function,symbol); break;
13693                case 19 : func_node = parse_function_call<19>(function,symbol); break;
13694                case 20 : func_node = parse_function_call<20>(function,symbol); break;
13695                default : {
13696                            set_error(
13697                               make_error(parser_error::e_syntax,
13698                                          current_token_,
13699                                          "ERR101 - Invalid number of parameters for function: " + symbol));
13700                            return error_node();
13701                          }
13702             }
13703 
13704             if (func_node)
13705                return func_node;
13706             else
13707             {
13708                set_error(
13709                   make_error(parser_error::e_syntax,
13710                              current_token_,
13711                              "ERR102 - Failed to generate node for function: '" + symbol + "'"));
13712                return error_node();
13713             }
13714          }
13715 
13716          // Are we dealing with a vararg function?
13717          ivararg_function<T>* vararg_function = symbol_table_.get_vararg_function(symbol);
13718 
13719          if (vararg_function)
13720          {
13721             expression_node_ptr vararg_func_node = error_node();
13722             vararg_func_node = parse_vararg_function_call(vararg_function,symbol);
13723 
13724             if (vararg_func_node)
13725                return vararg_func_node;
13726             else
13727             {
13728                set_error(
13729                   make_error(parser_error::e_syntax,
13730                              current_token_,
13731                              "ERR103 - Failed to generate node for vararg function: '" + symbol + "'"));
13732                return error_node();
13733             }
13734          }
13735 
13736          // Are we dealing with a vector element?
13737          if (symbol_table_.is_vector(symbol))
13738          {
13739             return parse_vector();
13740          }
13741 
13742          if (details::is_reserved_symbol(symbol))
13743          {
13744                set_error(
13745                   make_error(parser_error::e_syntax,
13746                              current_token_,
13747                              "ERR104 - Invalid use of reserved symbol '" + symbol + "'"));
13748                return error_node();
13749          }
13750 
13751          // Should we handle unknown symbols?
13752          if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
13753          {
13754             T default_value = T(0);
13755             std::string error_message;
13756             typename unknown_symbol_resolver::symbol_type symbol_type;
13757 
13758             if (unknown_symbol_resolver_->process(symbol,symbol_type,default_value,error_message))
13759             {
13760                bool create_result = false;
13761                switch (symbol_type)
13762                {
13763                   case unknown_symbol_resolver::e_variable_type : create_result = symbol_table_.create_variable(symbol,default_value);
13764                                                                   break;
13765 
13766                   case unknown_symbol_resolver::e_constant_type : create_result = symbol_table_.add_constant(symbol,default_value);
13767                                                                   break;
13768 
13769                   default                                       : create_result = false;
13770                }
13771 
13772                if (create_result)
13773                {
13774                   expression_node_ptr variable = symbol_table_.get_variable(symbol);
13775                   if (variable)
13776                   {
13777                      cache_symbol(symbol);
13778                      if (symbol_table_.is_constant_node(symbol))
13779                      {
13780                         variable = expression_generator_(variable->value());
13781                      }
13782                      next_token();
13783                      return variable;
13784                   }
13785                }
13786 
13787                set_error(
13788                   make_error(parser_error::e_symtab,
13789                              current_token_,
13790                              "ERR105 - Failed to create variable: '" + symbol + "'"));
13791 
13792                return error_node();
13793             }
13794          }
13795 
13796          set_error(
13797             make_error(parser_error::e_syntax,
13798                        current_token_,
13799                        "ERR106 - Undefined variable or function: '" + symbol + "'"));
13800          return error_node();
13801       }
13802 
13803       inline expression_node_ptr parse_symbol()
13804       {
13805          static const std::string symbol_if       = "if"      ;
13806          static const std::string symbol_while    = "while"   ;
13807          static const std::string symbol_repeat   = "repeat"  ;
13808          static const std::string symbol_for      = "for"     ;
13809          static const std::string symbol_switch   = "switch"  ;
13810          static const std::string symbol_null     = "null"    ;
13811          static const std::string symbol_break    = "break"   ;
13812          static const std::string symbol_continue = "continue";
13813 
13814          if (valid_vararg_operation(current_token_.value))
13815          {
13816             return parse_vararg_function();
13817          }
13818          else if (valid_base_operation(current_token_.value))
13819          {
13820             return parse_base_operation();
13821          }
13822          else if (details::imatch(current_token_.value,symbol_if))
13823          {
13824             return parse_conditional_statement();
13825          }
13826          else if (details::imatch(current_token_.value,symbol_while))
13827          {
13828             return parse_while_loop();
13829          }
13830          else if (details::imatch(current_token_.value,symbol_repeat))
13831          {
13832             return parse_repeat_until_loop();
13833          }
13834          else if (details::imatch(current_token_.value,symbol_for))
13835          {
13836             return parse_for_loop();
13837          }
13838          else if (details::imatch(current_token_.value,symbol_switch))
13839          {
13840             return parse_switch_statement();
13841          }
13842          else if (details::is_valid_sf_symbol(current_token_.value))
13843          {
13844             return parse_special_function();
13845          }
13846          else if (details::imatch(current_token_.value,symbol_null))
13847          {
13848             return parse_null_statement();
13849          }
13850          #ifndef exprtk_disable_break_continue
13851          else if (details::imatch(current_token_.value,symbol_break))
13852          {
13853             return parse_break_statement();
13854          }
13855          else if (details::imatch(current_token_.value,symbol_continue))
13856          {
13857             return parse_continue_statement();
13858          }
13859          #endif
13860          else if (symbol_table_.valid())
13861          {
13862             return parse_symtab_symbol();
13863          }
13864          else
13865          {
13866             set_error(
13867                make_error(parser_error::e_symtab,
13868                           current_token_,
13869                           "ERR107 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
13870             return error_node();
13871          }
13872       }
13873 
13874       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
13875       {
13876          expression_node_ptr branch = error_node();
13877 
13878          if (token_t::e_number == current_token_.type)
13879          {
13880             T numeric_value = T(0);
13881 
13882             if (details::string_to_real(current_token_.value,numeric_value))
13883             {
13884                expression_node_ptr literal_exp = expression_generator_(numeric_value);
13885                next_token();
13886                branch = literal_exp;
13887             }
13888             else
13889             {
13890                set_error(
13891                   make_error(parser_error::e_numeric,
13892                              current_token_,
13893                              "ERR108 - Failed to convert '" + current_token_.value + "' to a number"));
13894                return error_node();
13895             }
13896          }
13897          else if (token_t::e_symbol == current_token_.type)
13898          {
13899             branch = parse_symbol();
13900          }
13901          #ifndef exprtk_disable_string_capabilities
13902          else if (token_t::e_string == current_token_.type)
13903          {
13904             branch = parse_const_string();
13905          }
13906          #endif
13907          else if (token_t::e_lbracket == current_token_.type)
13908          {
13909             next_token();
13910             if (0 == (branch = parse_expression()))
13911                return error_node();
13912             else if (!token_is(token_t::e_rbracket))
13913             {
13914                set_error(
13915                   make_error(parser_error::e_syntax,
13916                              current_token_,
13917                              "ERR109 - Expected ')' instead of: '" + current_token_.value + "'"));
13918                return error_node();
13919             }
13920          }
13921          else if (token_t::e_lsqrbracket == current_token_.type)
13922          {
13923             next_token();
13924             if (0 == (branch = parse_expression()))
13925                return error_node();
13926             else if (!token_is(token_t::e_rsqrbracket))
13927             {
13928                set_error(
13929                   make_error(parser_error::e_syntax,
13930                              current_token_,
13931                              "ERR110 - Expected ']' instead of: '" + current_token_.value + "'"));
13932                return error_node();
13933             }
13934          }
13935          else if (token_t::e_lcrlbracket == current_token_.type)
13936          {
13937             next_token();
13938             if (0 == (branch = parse_expression()))
13939                return error_node();
13940             else if (!token_is(token_t::e_rcrlbracket))
13941             {
13942                set_error(
13943                   make_error(parser_error::e_syntax,
13944                              current_token_,
13945                              "ERR111 - Expected '}' instead of: '" + current_token_.value + "'"));
13946                return error_node();
13947             }
13948          }
13949          else if (token_t::e_sub == current_token_.type)
13950          {
13951             next_token();
13952             branch = expression_generator_(details::e_neg,
13953                                            // Was the previous operation exponentiation?
13954                                            (e_level12 == precedence) ?
13955                                            parse_branch    (e_level09) :
13956                                            parse_expression(e_level09));
13957          }
13958          else if (token_t::e_add == current_token_.type)
13959          {
13960             next_token();
13961             branch = parse_expression(e_level13);
13962          }
13963          else if (token_t::e_eof == current_token_.type)
13964          {
13965             set_error(
13966                make_error(parser_error::e_syntax,
13967                           current_token_,
13968                           "ERR112 - Premature end of expression[1]"));
13969             return error_node();
13970          }
13971          else
13972          {
13973             set_error(
13974                make_error(parser_error::e_syntax,
13975                           current_token_,
13976                           "ERR113 - Premature end of expression[2]"));
13977             return error_node();
13978          }
13979 
13980          if (
13981               branch &&
13982               (e_level00 == precedence) &&
13983               token_is(token_t::e_ternary,false)
13984             )
13985          {
13986             branch = parse_ternary_conditional_statement(branch);
13987          }
13988 
13989          return branch;
13990       }
13991 
13992       inline bool token_is(const typename token_t::token_type& ttype, const bool advance_token = true)
13993       {
13994          if (current_token_.type != ttype)
13995          {
13996             return false;
13997          }
13998 
13999          if (advance_token)
14000          {
14001             next_token();
14002          }
14003 
14004          return true;
14005       }
14006 
14007       inline bool peek_token_is(const typename token_t::token_type& ttype)
14008       {
14009          return (lexer_.peek_next_token().type == ttype);
14010       }
14011 
14012       template <typename Type>
14013       class expression_generator
14014       {
14015       public:
14016 
14017          typedef details::expression_node<Type>* expression_node_ptr;
14018          typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
14019          typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
14020          typedef typename exprtk::parser<Type> parser_t;
14021          typedef const Type& vtype;
14022          typedef const Type  ctype;
14023 
14024          inline void init_synthesize_map()
14025          {
14026             synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
14027             synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
14028             synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
14029 
14030             #define register_synthezier(S)                      \
14031             synthesize_map_[S ::node_type::id()] = S ::process; \
14032 
14033             register_synthezier(synthesize_vovov_expression0)
14034             register_synthezier(synthesize_vovov_expression1)
14035             register_synthezier(synthesize_vovoc_expression0)
14036             register_synthezier(synthesize_vovoc_expression1)
14037             register_synthezier(synthesize_vocov_expression0)
14038             register_synthezier(synthesize_vocov_expression1)
14039             register_synthezier(synthesize_covov_expression0)
14040             register_synthezier(synthesize_covov_expression1)
14041             register_synthezier(synthesize_covoc_expression0)
14042             register_synthezier(synthesize_covoc_expression1)
14043             register_synthezier(synthesize_cocov_expression1)
14044             register_synthezier(synthesize_vococ_expression0)
14045 
14046             register_synthezier(synthesize_vovovov_expression0)
14047             register_synthezier(synthesize_vovovoc_expression0)
14048             register_synthezier(synthesize_vovocov_expression0)
14049             register_synthezier(synthesize_vocovov_expression0)
14050             register_synthezier(synthesize_covovov_expression0)
14051             register_synthezier(synthesize_covocov_expression0)
14052             register_synthezier(synthesize_vocovoc_expression0)
14053             register_synthezier(synthesize_covovoc_expression0)
14054             register_synthezier(synthesize_vococov_expression0)
14055 
14056             register_synthezier(synthesize_vovovov_expression1)
14057             register_synthezier(synthesize_vovovoc_expression1)
14058             register_synthezier(synthesize_vovocov_expression1)
14059             register_synthezier(synthesize_vocovov_expression1)
14060             register_synthezier(synthesize_covovov_expression1)
14061             register_synthezier(synthesize_covocov_expression1)
14062             register_synthezier(synthesize_vocovoc_expression1)
14063             register_synthezier(synthesize_covovoc_expression1)
14064             register_synthezier(synthesize_vococov_expression1)
14065 
14066             register_synthezier(synthesize_vovovov_expression2)
14067             register_synthezier(synthesize_vovovoc_expression2)
14068             register_synthezier(synthesize_vovocov_expression2)
14069             register_synthezier(synthesize_vocovov_expression2)
14070             register_synthezier(synthesize_covovov_expression2)
14071             register_synthezier(synthesize_covocov_expression2)
14072             register_synthezier(synthesize_vocovoc_expression2)
14073             register_synthezier(synthesize_covovoc_expression2)
14074 
14075             register_synthezier(synthesize_vovovov_expression3)
14076             register_synthezier(synthesize_vovovoc_expression3)
14077             register_synthezier(synthesize_vovocov_expression3)
14078             register_synthezier(synthesize_vocovov_expression3)
14079             register_synthezier(synthesize_covovov_expression3)
14080             register_synthezier(synthesize_covocov_expression3)
14081             register_synthezier(synthesize_vocovoc_expression3)
14082             register_synthezier(synthesize_covovoc_expression3)
14083             register_synthezier(synthesize_vococov_expression3)
14084 
14085             register_synthezier(synthesize_vovovov_expression4)
14086             register_synthezier(synthesize_vovovoc_expression4)
14087             register_synthezier(synthesize_vovocov_expression4)
14088             register_synthezier(synthesize_vocovov_expression4)
14089             register_synthezier(synthesize_covovov_expression4)
14090             register_synthezier(synthesize_covocov_expression4)
14091             register_synthezier(synthesize_vocovoc_expression4)
14092             register_synthezier(synthesize_covovoc_expression4)
14093          }
14094 
14095          inline void set_parser(parser_t& p)
14096          {
14097             parser_ = &p;
14098          }
14099 
14100          inline void set_uom(unary_op_map_t& unary_op_map)
14101          {
14102             unary_op_map_ = &unary_op_map;
14103          }
14104 
14105          inline void set_bom(binary_op_map_t& binary_op_map)
14106          {
14107             binary_op_map_ = &binary_op_map;
14108          }
14109 
14110          inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
14111          {
14112             inv_binary_op_map_ = &inv_binary_op_map;
14113          }
14114 
14115          inline void set_sf3m(sf3_map_t& sf3_map)
14116          {
14117             sf3_map_ = &sf3_map;
14118          }
14119 
14120          inline void set_sf4m(sf4_map_t& sf4_map)
14121          {
14122             sf4_map_ = &sf4_map;
14123          }
14124 
14125          inline void set_allocator(details::node_allocator& na)
14126          {
14127             node_allocator_ = &na;
14128          }
14129 
14130          inline void set_strength_reduction_state(const bool strength_reduction_enabled)
14131          {
14132             strength_reduction_enabled_ = strength_reduction_enabled;
14133          }
14134 
14135          inline bool strength_reduction_enabled() const
14136          {
14137             return strength_reduction_enabled_;
14138          }
14139 
14140          inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
14141          {
14142             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
14143             if ((*binary_op_map_).end() == bop_itr)
14144                return false;
14145             bop = bop_itr->second;
14146             return true;
14147          }
14148 
14149          inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
14150          {
14151             typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
14152             if ((*unary_op_map_).end() == uop_itr)
14153                return false;
14154             uop = uop_itr->second;
14155             return true;
14156          }
14157 
14158          inline details::operator_type get_operator(const binary_functor_t& bop)
14159          {
14160             return (*inv_binary_op_map_).find(bop)->second;
14161          }
14162 
14163          inline expression_node_ptr operator()(const Type& v) const
14164          {
14165             return node_allocator_->allocate<literal_node_t>(v);
14166          }
14167 
14168          inline expression_node_ptr operator()(const std::string& s) const
14169          {
14170             return node_allocator_->allocate<string_literal_node_t>(s);
14171          }
14172 
14173          inline expression_node_ptr operator()(std::string& s, range_pack& rp) const
14174          {
14175             return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
14176          }
14177 
14178          inline expression_node_ptr operator()(const std::string& s, range_pack& rp) const
14179          {
14180             return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
14181          }
14182 
14183          inline bool unary_optimizable(const details::operator_type& operation) const
14184          {
14185             return (details::e_abs   == operation) || (details::e_acos  == operation) ||
14186                    (details::e_acosh == operation) || (details::e_asin  == operation) ||
14187                    (details::e_asinh == operation) || (details::e_atan  == operation) ||
14188                    (details::e_atanh == operation) || (details::e_ceil  == operation) ||
14189                    (details::e_cos   == operation) || (details::e_cosh  == operation) ||
14190                    (details::e_exp   == operation) || (details::e_expm1 == operation) ||
14191                    (details::e_floor == operation) || (details::e_log   == operation) ||
14192                    (details::e_log10 == operation) || (details::e_log2  == operation) ||
14193                    (details::e_log1p == operation) || (details::e_neg   == operation) ||
14194                    (details::e_pos   == operation) || (details::e_round == operation) ||
14195                    (details::e_sin   == operation) || (details::e_sinc  == operation) ||
14196                    (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
14197                    (details::e_tan   == operation) || (details::e_tanh  == operation) ||
14198                    (details::e_cot   == operation) || (details::e_sec   == operation) ||
14199                    (details::e_csc   == operation) || (details::e_r2d   == operation) ||
14200                    (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
14201                    (details::e_g2d   == operation) || (details::e_notl  == operation) ||
14202                    (details::e_sgn   == operation) || (details::e_erf   == operation) ||
14203                    (details::e_erfc  == operation) || (details::e_frac  == operation) ||
14204                    (details::e_trunc == operation);
14205          }
14206 
14207          inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc)
14208          {
14209             typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
14210             if (sf3_map_->end() == itr)
14211                return false;
14212             else
14213                tfunc = itr->second.first;
14214             return true;
14215          }
14216 
14217          inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc)
14218          {
14219             typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
14220             if (sf4_map_->end() == itr)
14221                return false;
14222             else
14223                qfunc = itr->second.first;
14224             return true;
14225          }
14226 
14227          inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation)
14228          {
14229             typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
14230             if (sf3_map_->end() == itr)
14231                return false;
14232             else
14233                operation = itr->second.second;
14234             return true;
14235          }
14236 
14237          inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation)
14238          {
14239             typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
14240             if (sf4_map_->end() == itr)
14241                return false;
14242             else
14243                operation = itr->second.second;
14244             return true;
14245          }
14246 
14247          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
14248          {
14249             if (0 == branch[0])
14250                return error_node();
14251             else if (details::is_null_node(branch[0]))
14252                return branch[0];
14253             else if (details::is_break_node(branch[0]))
14254                return error_node();
14255             else if (details::is_continue_node(branch[0]))
14256                return error_node();
14257             else if (details::is_constant_node(branch[0]))
14258                return synthesize_expression<unary_node_t,1>(operation,branch);
14259             else if (unary_optimizable(operation) && details::is_variable_node(branch[0]))
14260                return synthesize_uv_expression(operation,branch);
14261             else
14262                return synthesize_unary_expression(operation,branch);
14263          }
14264 
14265          inline bool is_assignment_operation(const details::operator_type& operation) const
14266          {
14267             return (details::e_addass == operation) ||
14268                    (details::e_subass == operation) ||
14269                    (details::e_mulass == operation) ||
14270                    (details::e_divass == operation);
14271          }
14272 
14273          #ifndef exprtk_disable_string_capabilities
14274          inline bool valid_string_operation(const details::operator_type& operation) const
14275          {
14276             return (details::e_add   == operation) ||
14277                    (details::e_lt    == operation) ||
14278                    (details::e_lte   == operation) ||
14279                    (details::e_gt    == operation) ||
14280                    (details::e_gte   == operation) ||
14281                    (details::e_eq    == operation) ||
14282                    (details::e_ne    == operation) ||
14283                    (details::e_in    == operation) ||
14284                    (details::e_like  == operation) ||
14285                    (details::e_ilike == operation);
14286          }
14287          #else
14288          inline bool valid_string_operation(const details::operator_type&) const
14289          {
14290             return false;
14291          }
14292          #endif
14293 
14294          inline std::string to_str(const details::operator_type& operation) const
14295          {
14296             switch (operation)
14297             {
14298                case details::e_add  : return "+";
14299                case details::e_sub  : return "-";
14300                case details::e_mul  : return "*";
14301                case details::e_div  : return "/";
14302                case details::e_mod  : return "%";
14303                case details::e_pow  : return "^";
14304                case details::e_lt   : return "<";
14305                case details::e_lte  : return "<=";
14306                case details::e_gt   : return ">";
14307                case details::e_gte  : return ">=";
14308                case details::e_eq   : return "==";
14309                case details::e_ne   : return "!=";
14310                case details::e_and  : return "and";
14311                case details::e_nand : return "nand";
14312                case details::e_or   : return "or";
14313                case details::e_nor  : return "nor";
14314                case details::e_xor  : return "xor";
14315                case details::e_xnor : return "xnor";
14316                default              : return "UNKNOWN";
14317             }
14318          }
14319 
14320          inline bool operation_optimizable(const details::operator_type& operation) const
14321          {
14322             return (details::e_add  == operation) ||
14323                    (details::e_sub  == operation) ||
14324                    (details::e_mul  == operation) ||
14325                    (details::e_div  == operation) ||
14326                    (details::e_mod  == operation) ||
14327                    (details::e_pow  == operation) ||
14328                    (details::e_lt   == operation) ||
14329                    (details::e_lte  == operation) ||
14330                    (details::e_gt   == operation) ||
14331                    (details::e_gte  == operation) ||
14332                    (details::e_eq   == operation) ||
14333                    (details::e_ne   == operation) ||
14334                    (details::e_and  == operation) ||
14335                    (details::e_nand == operation) ||
14336                    (details::e_or   == operation) ||
14337                    (details::e_nor  == operation) ||
14338                    (details::e_xor  == operation) ||
14339                    (details::e_xnor == operation) ||
14340                    false;
14341          }
14342 
14343          inline std::string branch_to_id(expression_node_ptr branch)
14344          {
14345             static const std::string null_str   ("(null)" );
14346             static const std::string const_str  ("(c)"    );
14347             static const std::string var_str    ("(v)"    );
14348             static const std::string vov_str    ("(vov)"  );
14349             static const std::string cov_str    ("(cov)"  );
14350             static const std::string voc_str    ("(voc)"  );
14351             static const std::string str_str    ("(s)"    );
14352             static const std::string strrng_str ("(rngs)" );
14353             static const std::string cs_str     ("(cs)"   );
14354             static const std::string cstrrng_str("(crngs)");
14355 
14356             if (details::is_null_node(branch))
14357                return null_str;
14358             else if (details::is_constant_node(branch))
14359                return const_str;
14360             else if (details::is_variable_node(branch))
14361                return var_str;
14362             else if (details::is_vov_node(branch))
14363                return vov_str;
14364             else if (details::is_cov_node(branch))
14365                return cov_str;
14366             else if (details::is_voc_node(branch))
14367                return voc_str;
14368             else if (details::is_string_node(branch))
14369                return str_str;
14370             else if (details::is_const_string_node(branch))
14371                return cs_str;
14372             else if (details::is_string_range_node(branch))
14373                return strrng_str;
14374             else if (details::is_const_string_range_node(branch))
14375                return cstrrng_str;
14376             else if (details::is_t0ot1ot2_node(branch))
14377                return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
14378             else if (details::is_t0ot1ot2ot3_node(branch))
14379                return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
14380             else
14381                return "ERROR";
14382          }
14383 
14384          inline std::string branch_to_id(expression_node_ptr (&branch)[2])
14385          {
14386             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
14387          }
14388 
14389          inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14390          {
14391             if (!operation_optimizable(operation))
14392                return false;
14393             else
14394                return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
14395          }
14396 
14397          inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14398          {
14399             if (!operation_optimizable(operation))
14400                return false;
14401             else
14402                return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
14403          }
14404 
14405          inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14406          {
14407             if (!operation_optimizable(operation))
14408                return false;
14409             else
14410                return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
14411          }
14412 
14413          inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14414          {
14415             if (!operation_optimizable(operation))
14416                return false;
14417             else
14418                return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
14419          }
14420 
14421          inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14422          {
14423             if (!operation_optimizable(operation))
14424                return false;
14425             else
14426                return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
14427          }
14428 
14429          inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14430          {
14431             if (!operation_optimizable(operation))
14432                return false;
14433             else
14434                return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
14435          }
14436 
14437          inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14438          {
14439             if (!operation_optimizable(operation))
14440                return false;
14441             else
14442                return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
14443          }
14444 
14445          inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14446          {
14447             if (!operation_optimizable(operation))
14448                return false;
14449             else
14450                return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
14451          }
14452 
14453          inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14454          {
14455             if (!operation_optimizable(operation))
14456                return false;
14457             else
14458                return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
14459          }
14460 
14461          inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14462          {
14463             return is_assignment_operation(operation) &&
14464                    (
14465                      (
14466                        !details::is_variable_node(branch[0]) &&
14467                        !details::is_vector_node  (branch[0])
14468                      ) ||
14469                      is_generally_string_node(branch[1])
14470                    );
14471          }
14472 
14473          inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
14474          {
14475             return (
14476                      details::is_break_node   (branch[0]) ||
14477                      details::is_break_node   (branch[1]) ||
14478                      details::is_continue_node(branch[0]) ||
14479                      details::is_continue_node(branch[1])
14480                    );
14481          }
14482 
14483          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14484          {
14485             const bool b0_string = is_generally_string_node(branch[0]);
14486             const bool b1_string = is_generally_string_node(branch[1]);
14487             bool result = false;
14488             if (b0_string ^ b1_string)
14489                result = true;
14490             else if (!valid_string_operation(operation) && b0_string && b1_string)
14491                result = true;
14492             if (result)
14493             {
14494                parser_->set_synthesis_error("Invalid string operation.");
14495             }
14496             return result;
14497          }
14498 
14499          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14500          {
14501             const bool b0_string = is_generally_string_node(branch[0]);
14502             const bool b1_string = is_generally_string_node(branch[1]);
14503             const bool b2_string = is_generally_string_node(branch[2]);
14504             bool result = false;
14505             if ((b0_string ^ b1_string) || (b1_string ^ b2_string))
14506                result = true;
14507             else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
14508                result = true;
14509             if (result)
14510             {
14511                parser_->set_synthesis_error("Invalid string operation.");
14512             }
14513             return result;
14514          }
14515 
14516          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14517          {
14518             const bool b0_string = is_generally_string_node(branch[0]);
14519             const bool b1_string = is_generally_string_node(branch[1]);
14520             return (b0_string && b1_string && valid_string_operation(operation));
14521          }
14522 
14523          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14524          {
14525             const bool b0_string = is_generally_string_node(branch[0]);
14526             const bool b1_string = is_generally_string_node(branch[1]);
14527             const bool b2_string = is_generally_string_node(branch[2]);
14528             return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
14529          }
14530 
14531          #ifndef exprtk_disable_sc_andor
14532          inline bool is_shortcircuit_expression(const details::operator_type& operation)
14533          {
14534             return ((details::e_scand == operation) || (details::e_scor == operation));
14535          }
14536          #else
14537          inline bool is_shortcircuit_expression(const details::operator_type&)
14538          {
14539             return false;
14540          }
14541          #endif
14542 
14543          inline bool is_null_present(expression_node_ptr (&branch)[2])
14544          {
14545             return details::is_null_node(branch[0]) ||
14546                    details::is_null_node(branch[1]);
14547          }
14548 
14549          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14550          {
14551             if ((0 == branch[0]) || (0 == branch[1]))
14552                return error_node();
14553             else if (is_invalid_string_op(operation,branch))
14554                return error_node();
14555             else if (is_invalid_assignment_op(operation,branch))
14556                return error_node();
14557             else if (is_invalid_break_continue_op(branch))
14558                return error_node();
14559             else if (details::e_assign == operation)
14560                return synthesize_assignment_expression(operation,branch);
14561             else if (is_assignment_operation(operation))
14562                return synthesize_assignment_operation_expression(operation,branch);
14563             else if (is_shortcircuit_expression(operation))
14564                return synthesize_shortcircuit_expression(operation,branch);
14565             else if (is_string_operation(operation,branch))
14566                return synthesize_string_expression(operation,branch);
14567             else if (is_null_present(branch))
14568                return synthesize_null_expression(operation,branch);
14569 
14570             expression_node_ptr result = error_node();
14571 
14572             if (synthesize_expression(operation,branch,result))
14573                return result;
14574             else if (uvouv_optimizable(operation,branch))
14575                return synthesize_uvouv_expression(operation,branch);
14576             else if (vob_optimizable(operation,branch))
14577                return synthesize_vob_expression::process(*this,operation,branch);
14578             else if (bov_optimizable(operation,branch))
14579                return synthesize_bov_expression::process(*this,operation,branch);
14580             else if (cob_optimizable(operation,branch))
14581                return synthesize_cob_expression::process(*this,operation,branch);
14582             else if (boc_optimizable(operation,branch))
14583                return synthesize_boc_expression::process(*this,operation,branch);
14584             else if (cov_optimizable(operation,branch))
14585                return synthesize_cov_expression::process(*this,operation,branch);
14586             else if (binext_optimizable(operation,branch))
14587                return synthesize_binary_ext_expression::process(*this,operation,branch);
14588             else
14589                return synthesize_expression<binary_node_t,2>(operation,branch);
14590          }
14591 
14592          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14593          {
14594             if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
14595             {
14596                details::free_all_nodes(*node_allocator_,branch);
14597                return error_node();
14598             }
14599             else if (is_invalid_string_op(operation,branch))
14600                return error_node();
14601             else if (is_string_operation(operation,branch))
14602                return synthesize_string_expression(operation,branch);
14603             else
14604                return synthesize_expression<trinary_node_t,3>(operation,branch);
14605          }
14606 
14607          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
14608          {
14609             return synthesize_expression<quaternary_node_t,4>(operation,branch);
14610          }
14611 
14612          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[5])
14613          {
14614             return synthesize_expression<quinary_node_t,5>(operation,branch);
14615          }
14616 
14617          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[6])
14618          {
14619             return synthesize_expression<senary_node_t,6>(operation,branch);
14620          }
14621 
14622          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
14623          {
14624             expression_node_ptr branch[1] = { b0 };
14625             return synthesize_expression<unary_node_t,1>(operation,branch);
14626          }
14627 
14628          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
14629          {
14630             if ((0 == b0) || (0 == b1))
14631                return error_node();
14632             else
14633             {
14634                expression_node_ptr branch[2] = { b0, b1 };
14635                return expression_generator<Type>::operator()(operation,branch);
14636             }
14637          }
14638 
14639          inline expression_node_ptr conditional(expression_node_ptr condition,
14640                                                 expression_node_ptr consequent,
14641                                                 expression_node_ptr alternative) const
14642          {
14643             if ((0 == condition) || (0 == consequent))
14644             {
14645                free_node(*node_allocator_,condition);
14646                free_node(*node_allocator_,consequent);
14647                free_node(*node_allocator_,alternative);
14648                return error_node();
14649             }
14650             // Can the condition be immediately evaluated? if so optimize.
14651             else if (details::is_constant_node(condition))
14652             {
14653                // True branch
14654                if (details::is_true(condition))
14655                {
14656                   free_node(*node_allocator_,condition);
14657                   free_node(*node_allocator_,alternative);
14658                   return consequent;
14659                }
14660                // False branch
14661                else
14662                {
14663                   free_node(*node_allocator_,condition);
14664                   free_node(*node_allocator_,consequent);
14665                   if (alternative)
14666                      return alternative;
14667                   else
14668                      return node_allocator_->allocate<details::null_node<T> >();
14669                }
14670             }
14671             else if ((0 != consequent) && (0 != alternative))
14672             {
14673                return node_allocator_->allocate<conditional_node_t>(condition,consequent,alternative);
14674             }
14675             else
14676                return node_allocator_->allocate<cons_conditional_node_t>(condition,consequent);
14677          }
14678 
14679          inline expression_node_ptr while_loop(expression_node_ptr condition,
14680                                                expression_node_ptr branch,
14681                                                const bool brkcont = false) const
14682          {
14683             if (details::is_constant_node(condition))
14684             {
14685                expression_node_ptr result = error_node();
14686                if (details::is_true(condition))
14687                   // Infinite loops are not allowed.
14688                   result = error_node();
14689                else
14690                   result = node_allocator_->allocate<details::null_node<Type> >();
14691                free_node(*node_allocator_,condition);
14692                free_node(*node_allocator_,branch);
14693                return result;
14694             }
14695             else if (details::is_null_node(condition))
14696             {
14697                free_node(*node_allocator_,condition);
14698                return branch;
14699             }
14700             else if (!brkcont)
14701                return node_allocator_->allocate<while_loop_node_t>(condition,branch);
14702             #ifndef exprtk_disable_break_continue
14703             else
14704                return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
14705             #else
14706                return error_node();
14707             #endif
14708          }
14709 
14710          inline expression_node_ptr repeat_until_loop(expression_node_ptr condition,
14711                                                       expression_node_ptr branch,
14712                                                       const bool brkcont = false) const
14713          {
14714             if (details::is_constant_node(condition))
14715             {
14716                if (details::is_true(condition) && details::is_constant_node(branch))
14717                {
14718                   free_node(*node_allocator_,condition);
14719                   return branch;
14720                }
14721                expression_node_ptr result = error_node();
14722                free_node(*node_allocator_,condition);
14723                free_node(*node_allocator_,branch);
14724                return result;
14725             }
14726             else if (details::is_null_node(condition))
14727             {
14728                free_node(*node_allocator_,condition);
14729                return branch;
14730             }
14731             else if (!brkcont)
14732                return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
14733             #ifndef exprtk_disable_break_continue
14734             else
14735                return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
14736             #else
14737                return error_node();
14738             #endif
14739          }
14740 
14741          inline expression_node_ptr for_loop(expression_node_ptr initializer,
14742                                              expression_node_ptr condition,
14743                                              expression_node_ptr incrementor,
14744                                              expression_node_ptr loop_body,
14745                                              expression_node_ptr loop_var,
14746                                              T* loop_counter,
14747                                              bool brkcont = false) const
14748          {
14749             if (details::is_constant_node(condition))
14750             {
14751                expression_node_ptr result = error_node();
14752                if (details::is_true(condition))
14753                   // Infinite loops are not allowed.
14754                   result = error_node();
14755                else
14756                   result = node_allocator_->allocate<details::null_node<Type> >();
14757                free_node(*node_allocator_,initializer     );
14758                free_node(*node_allocator_,condition       );
14759                free_node(*node_allocator_,incrementor     );
14760                free_node(*node_allocator_,loop_body       );
14761                free_node(*node_allocator_,loop_var   ,true);
14762                delete loop_counter;
14763                return result;
14764             }
14765             else if (details::is_null_node(condition))
14766             {
14767                free_node(*node_allocator_,initializer);
14768                free_node(*node_allocator_,condition  );
14769                free_node(*node_allocator_,incrementor);
14770                return loop_body;
14771             }
14772             else if (!brkcont)
14773                return node_allocator_->allocate<for_loop_node_t>(initializer,
14774                                                                  condition,
14775                                                                  incrementor,
14776                                                                  loop_body,
14777                                                                  loop_var,
14778                                                                  loop_counter);
14779             #ifndef exprtk_disable_break_continue
14780             else
14781                return node_allocator_->allocate<for_loop_bc_node_t>(initializer,
14782                                                                     condition,
14783                                                                     incrementor,
14784                                                                     loop_body,
14785                                                                     loop_var,
14786                                                                     loop_counter);
14787             #else
14788             return error_node();
14789             #endif
14790          }
14791 
14792          template <typename Allocator,
14793                    template <typename,typename> class Sequence>
14794          inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arglist)
14795          {
14796             expression_node_ptr result = error_node();
14797 
14798             for (std::size_t i = 0; i < (arglist.size() / 2); ++i)
14799             {
14800                expression_node_ptr condition  = arglist[(2 * i)    ];
14801                expression_node_ptr consequent = arglist[(2 * i) + 1];
14802 
14803                if ((0 == result) && details::is_true(condition))
14804                {
14805                   result = consequent;
14806                   break;
14807                }
14808             }
14809 
14810             if (0 == result)
14811             {
14812                result = arglist.back();
14813             }
14814 
14815             for (std::size_t i = 0; i < arglist.size(); ++i)
14816             {
14817                expression_node_ptr current_expr = arglist[i];
14818 
14819                if (current_expr && (current_expr != result))
14820                {
14821                   free_node(*node_allocator_,current_expr);
14822                }
14823             }
14824 
14825             return result;
14826          }
14827 
14828          template <typename Allocator,
14829                    template <typename,typename> class Sequence>
14830          inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arglist)
14831          {
14832             expression_node_ptr result = error_node();
14833 
14834             for (std::size_t i = 0; i < (arglist.size() / 2); ++i)
14835             {
14836                expression_node_ptr condition  = arglist[(2 * i)    ];
14837                expression_node_ptr consequent = arglist[(2 * i) + 1];
14838 
14839                if (details::is_true(condition))
14840                {
14841                   result = consequent;
14842                }
14843             }
14844 
14845             if (0 == result)
14846             {
14847                T zero = T(0);
14848                result = node_allocator_->allocate<literal_node_t>(zero);
14849             }
14850 
14851             for (std::size_t i = 0; i < arglist.size(); ++i)
14852             {
14853                expression_node_ptr current_expr = arglist[i];
14854 
14855                if (current_expr && (current_expr != result))
14856                {
14857                   free_node(*node_allocator_,current_expr);
14858                }
14859             }
14860 
14861             return result;
14862          }
14863 
14864          template <typename Allocator,
14865                    template <typename,typename> class Sequence>
14866          inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arglist)
14867          {
14868             if (!all_nodes_valid(arglist))
14869             {
14870                details::free_all_nodes(*node_allocator_,arglist);
14871                return error_node();
14872             }
14873             else if (is_constant_foldable(arglist))
14874                return const_optimize_switch(arglist);
14875             else
14876                return node_allocator_->allocate<details::switch_node<Type> >(arglist);
14877          }
14878 
14879          template <typename Allocator,
14880                    template <typename,typename> class Sequence>
14881          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arglist)
14882          {
14883             if (!all_nodes_valid(arglist))
14884             {
14885                details::free_all_nodes(*node_allocator_,arglist);
14886                return error_node();
14887             }
14888             else if (is_constant_foldable(arglist))
14889                return const_optimize_mswitch(arglist);
14890             else
14891                return node_allocator_->allocate<details::multi_switch_node<Type> >(arglist);
14892          }
14893 
14894          #define unary_opr_switch_statements           \
14895          case_stmt(details::  e_abs,details::  abs_op) \
14896          case_stmt(details:: e_acos,details:: acos_op) \
14897          case_stmt(details::e_acosh,details::acosh_op) \
14898          case_stmt(details:: e_asin,details:: asin_op) \
14899          case_stmt(details::e_asinh,details::asinh_op) \
14900          case_stmt(details:: e_atan,details:: atan_op) \
14901          case_stmt(details::e_atanh,details::atanh_op) \
14902          case_stmt(details:: e_ceil,details:: ceil_op) \
14903          case_stmt(details::  e_cos,details::  cos_op) \
14904          case_stmt(details:: e_cosh,details:: cosh_op) \
14905          case_stmt(details::  e_exp,details::  exp_op) \
14906          case_stmt(details::e_expm1,details::expm1_op) \
14907          case_stmt(details::e_floor,details::floor_op) \
14908          case_stmt(details::  e_log,details::  log_op) \
14909          case_stmt(details::e_log10,details::log10_op) \
14910          case_stmt(details:: e_log2,details:: log2_op) \
14911          case_stmt(details::e_log1p,details::log1p_op) \
14912          case_stmt(details::  e_neg,details::  neg_op) \
14913          case_stmt(details::  e_pos,details::  pos_op) \
14914          case_stmt(details::e_round,details::round_op) \
14915          case_stmt(details::  e_sin,details::  sin_op) \
14916          case_stmt(details:: e_sinc,details:: sinc_op) \
14917          case_stmt(details:: e_sinh,details:: sinh_op) \
14918          case_stmt(details:: e_sqrt,details:: sqrt_op) \
14919          case_stmt(details::  e_tan,details::  tan_op) \
14920          case_stmt(details:: e_tanh,details:: tanh_op) \
14921          case_stmt(details::  e_cot,details::  cot_op) \
14922          case_stmt(details::  e_sec,details::  sec_op) \
14923          case_stmt(details::  e_csc,details::  csc_op) \
14924          case_stmt(details::  e_r2d,details::  r2d_op) \
14925          case_stmt(details::  e_d2r,details::  d2r_op) \
14926          case_stmt(details::  e_d2g,details::  d2g_op) \
14927          case_stmt(details::  e_g2d,details::  g2d_op) \
14928          case_stmt(details:: e_notl,details:: notl_op) \
14929          case_stmt(details::  e_sgn,details::  sgn_op) \
14930          case_stmt(details::  e_erf,details::  erf_op) \
14931          case_stmt(details:: e_erfc,details:: erfc_op) \
14932          case_stmt(details:: e_frac,details:: frac_op) \
14933          case_stmt(details::e_trunc,details::trunc_op) \
14934 
14935          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1])
14936          {
14937             T& v = dynamic_cast<details::variable_node<T>*>(branch[0])->ref();
14938             switch (operation)
14939             {
14940                #define case_stmt(op0,op1)                                                          \
14941                case op0 : return node_allocator_->                                                 \
14942                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
14943 
14944                unary_opr_switch_statements
14945                #undef case_stmt
14946                default : return error_node();
14947             }
14948          }
14949 
14950          inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1])
14951          {
14952             switch (operation)
14953             {
14954                #define case_stmt(op0,op1)                                                                \
14955                case op0 : return node_allocator_->                                                       \
14956                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
14957 
14958                unary_opr_switch_statements
14959                #undef case_stmt
14960                default : return error_node();
14961             }
14962          }
14963 
14964          inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14965          {
14966             expression_node_ptr temp_node = error_node();
14967             switch (operation)
14968             {
14969                #define case_stmt(op0,op1)                                              \
14970                case op0 : temp_node = node_allocator_->                                \
14971                                          allocate<details::sf3_node<Type,op1<Type> > > \
14972                                             (operation,branch);                        \
14973                           break;                                                       \
14974 
14975                case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
14976                case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
14977                case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
14978                case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
14979                case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
14980                case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
14981                case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
14982                case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
14983                case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
14984                case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
14985                case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
14986                case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
14987                case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
14988                case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
14989                case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
14990                case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
14991                case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
14992                case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
14993                case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
14994                case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
14995                case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
14996                case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
14997                case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
14998                case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
14999                #undef case_stmt
15000                default : return error_node();
15001             }
15002 
15003             T v = temp_node->value();
15004             node_allocator_->free(temp_node);
15005             details::free_node(*node_allocator_,temp_node);
15006 
15007             return node_allocator_->allocate<literal_node_t>(v);
15008          }
15009 
15010          inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
15011          {
15012             const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15013             const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15014             const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[2])->ref();
15015 
15016             switch (operation)
15017             {
15018                #define case_stmt(op0,op1)                                                 \
15019                case op0 : return node_allocator_->                                        \
15020                                     allocate_rrr<details::sf3_var_node<Type,op1<Type> > > \
15021                                        (v0,v1,v2);                                        \
15022 
15023                case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
15024                case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
15025                case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
15026                case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
15027                case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
15028                case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
15029                case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
15030                case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
15031                case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
15032                case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
15033                case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
15034                case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
15035                case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
15036                case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
15037                case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
15038                case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
15039                case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
15040                case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
15041                case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
15042                case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
15043                case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
15044                case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
15045                case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
15046                case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
15047                #undef case_stmt
15048                default : return error_node();
15049             }
15050          }
15051 
15052          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
15053          {
15054             if (!all_nodes_valid(branch))
15055                return error_node();
15056             else if (is_constant_foldable(branch))
15057                return const_optimize_sf3(operation,branch);
15058             else if (all_nodes_variables(branch))
15059                return varnode_optimize_sf3(operation,branch);
15060             else
15061             {
15062                switch (operation)
15063                {
15064                   #define case_stmt(op0,op1)                                                     \
15065                   case op0 : return node_allocator_->                                            \
15066                                 allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); \
15067 
15068                   case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
15069                   case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
15070                   case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
15071                   case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
15072                   case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
15073                   case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
15074                   case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
15075                   case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
15076                   case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
15077                   case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
15078                   case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
15079                   case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
15080                   case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
15081                   case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
15082                   case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
15083                   case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
15084                   case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
15085                   case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
15086                   case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
15087                   case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
15088                   case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
15089                   case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
15090                   case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
15091                   case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
15092                   #undef case_stmt
15093                   default : return error_node();
15094                }
15095             }
15096          }
15097 
15098          inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
15099          {
15100             expression_node_ptr temp_node = error_node();
15101             switch (operation)
15102             {
15103                #define case_stmt(op0,op1)                                                                 \
15104                case op0 : temp_node = node_allocator_->                                                   \
15105                                          allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
15106                           break;                                                                          \
15107 
15108                case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
15109                case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
15110                case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
15111                case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
15112                case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
15113                case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
15114                case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
15115                case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
15116                case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
15117                case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
15118                case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
15119                case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
15120                case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
15121                case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
15122                case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
15123                case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
15124                case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
15125                case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
15126                case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
15127                case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
15128                case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
15129                case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
15130                case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
15131                case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
15132                case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
15133                case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
15134                #undef case_stmt
15135                default : return error_node();
15136             }
15137             T v = temp_node->value();
15138             details::free_node(*node_allocator_,temp_node);
15139             return node_allocator_->allocate<literal_node_t>(v);
15140          }
15141 
15142          inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
15143          {
15144             const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15145             const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15146             const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[2])->ref();
15147             const Type& v3 = dynamic_cast<details::variable_node<Type>*>(branch[3])->ref();
15148 
15149             switch (operation)
15150             {
15151                #define case_stmt(op0,op1)                                                         \
15152                case op0 : return node_allocator_->                                                \
15153                              allocate_rrrr<details::sf4_var_node<Type,op1<Type> > >(v0,v1,v2,v3); \
15154 
15155                case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
15156                case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
15157                case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
15158                case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
15159                case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
15160                case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
15161                case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
15162                case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
15163                case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
15164                case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
15165                case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
15166                case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
15167                case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
15168                case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
15169                case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
15170                case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
15171                case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
15172                case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
15173                case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
15174                case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
15175                case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
15176                case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
15177                case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
15178                case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
15179                case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
15180                case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
15181                #undef case_stmt
15182                default : return error_node();
15183             }
15184          }
15185 
15186          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
15187          {
15188             if (!all_nodes_valid(branch))
15189                return error_node();
15190             else if (is_constant_foldable(branch))
15191                return const_optimize_sf4(operation,branch);
15192             else if (all_nodes_variables(branch))
15193                return varnode_optimize_sf4(operation,branch);
15194             switch (operation)
15195             {
15196                #define case_stmt(op0,op1)                                                     \
15197                case op0 : return node_allocator_->                                            \
15198                              allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
15199 
15200                case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
15201                case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
15202                case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
15203                case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
15204                case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
15205                case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
15206                case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
15207                case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
15208                case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
15209                case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
15210                case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
15211                case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
15212                case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
15213                case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
15214                case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
15215                case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
15216                case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
15217                case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
15218                case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
15219                case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
15220                case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
15221                case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
15222                case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
15223                case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
15224                case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
15225                case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
15226                #undef case_stmt
15227                default : return error_node();
15228             }
15229          }
15230 
15231          template <typename Allocator,
15232                    template <typename,typename> class Sequence>
15233          inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arglist)
15234          {
15235             expression_node_ptr temp_node = error_node();
15236             switch (operation)
15237             {
15238                #define case_stmt(op0,op1)                                                 \
15239                case op0 : temp_node = node_allocator_->                                   \
15240                                          allocate<details::vararg_node<Type,op1<Type> > > \
15241                                             (arglist);                                    \
15242                           break;                                                          \
15243 
15244                case_stmt(details::e_sum,  details::vararg_add_op  )
15245                case_stmt(details::e_prod, details::vararg_mul_op  )
15246                case_stmt(details::e_avg,  details::vararg_avg_op  )
15247                case_stmt(details::e_min,  details::vararg_min_op  )
15248                case_stmt(details::e_max,  details::vararg_max_op  )
15249                case_stmt(details::e_mand, details::vararg_mand_op )
15250                case_stmt(details::e_mor,  details::vararg_mor_op  )
15251                case_stmt(details::e_multi,details::vararg_multi_op)
15252                #undef case_stmt
15253                default : return error_node();
15254             }
15255             T v = temp_node->value();
15256             details::free_node(*node_allocator_,temp_node);
15257             return node_allocator_->allocate<literal_node_t>(v);
15258          }
15259 
15260          inline bool special_one_parameter_vararg(const details::operator_type& operation)
15261          {
15262             return (
15263                      (details::e_sum  == operation) ||
15264                      (details::e_prod == operation) ||
15265                      (details::e_avg  == operation) ||
15266                      (details::e_min  == operation) ||
15267                      (details::e_max  == operation)
15268                    );
15269          }
15270 
15271          template <typename Allocator,
15272                    template <typename,typename> class Sequence>
15273          inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arglist)
15274          {
15275             switch (operation)
15276             {
15277                #define case_stmt(op0,op1)                                                  \
15278                case op0 : return node_allocator_->                                         \
15279                              allocate<details::vararg_varnode<Type,op1<Type> > >(arglist); \
15280 
15281                case_stmt(details::e_sum,  details::vararg_add_op  )
15282                case_stmt(details::e_prod, details::vararg_mul_op  )
15283                case_stmt(details::e_avg,  details::vararg_avg_op  )
15284                case_stmt(details::e_min,  details::vararg_min_op  )
15285                case_stmt(details::e_max,  details::vararg_max_op  )
15286                case_stmt(details::e_mand, details::vararg_mand_op )
15287                case_stmt(details::e_mor,  details::vararg_mor_op  )
15288                case_stmt(details::e_multi,details::vararg_multi_op)
15289                #undef case_stmt
15290                default : return error_node();
15291             }
15292          }
15293 
15294          template <typename Allocator,
15295                    template <typename,typename> class Sequence>
15296          inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arglist)
15297          {
15298             if (!all_nodes_valid(arglist))
15299             {
15300                details::free_all_nodes(*node_allocator_,arglist);
15301                return error_node();
15302             }
15303             else if (is_constant_foldable(arglist))
15304                return const_optimize_varargfunc(operation,arglist);
15305             else if ((arglist.size() == 1) && special_one_parameter_vararg(operation))
15306                return arglist[0];
15307             else if (all_nodes_variables(arglist))
15308                   return varnode_optimize_varargfunc(operation,arglist);
15309 
15310             switch (operation)
15311             {
15312                #define case_stmt(op0,op1)                                               \
15313                case op0 : return node_allocator_->                                      \
15314                              allocate<details::vararg_node<Type,op1<Type> > >(arglist); \
15315 
15316                case_stmt(details::e_sum,  details::vararg_add_op  )
15317                case_stmt(details::e_prod, details::vararg_mul_op  )
15318                case_stmt(details::e_avg,  details::vararg_avg_op  )
15319                case_stmt(details::e_min,  details::vararg_min_op  )
15320                case_stmt(details::e_max,  details::vararg_max_op  )
15321                case_stmt(details::e_mand, details::vararg_mand_op )
15322                case_stmt(details::e_mor,  details::vararg_mor_op  )
15323                case_stmt(details::e_multi,details::vararg_multi_op)
15324                #undef case_stmt
15325                default : return error_node();
15326             }
15327          }
15328 
15329          template <std::size_t N>
15330          inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
15331          {
15332             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
15333             expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
15334             if (0 == result)
15335                return error_node();
15336             else
15337             {
15338                // Can the function call be completely optimized?
15339                if (details::is_constant_node(result))
15340                   return result;
15341                else if (!all_nodes_valid(b))
15342                   return error_node();
15343                else if (N != f->param_count)
15344                {
15345                   details::free_all_nodes(*node_allocator_,b);
15346                   return error_node();
15347                }
15348 
15349                function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(result);
15350 
15351                if (func_node_ptr)
15352                {
15353                   if (func_node_ptr->init_branches(b))
15354                      return result;
15355                   else
15356                   {
15357                      details::free_all_nodes(*node_allocator_,b);
15358                      return error_node();
15359                   }
15360                }
15361                else
15362                {
15363                   details::free_all_nodes(*node_allocator_,b);
15364                   return error_node();
15365                }
15366             }
15367          }
15368 
15369          inline expression_node_ptr function(ifunction_t* f)
15370          {
15371             typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
15372             return node_allocator_->allocate<function_N_node_t>(f);
15373          }
15374 
15375          inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
15376                                                          std::vector<expression_node_ptr>& arglist)
15377          {
15378             if (!all_nodes_valid(arglist))
15379             {
15380                details::free_all_nodes(*node_allocator_,arglist);
15381                return error_node();
15382             }
15383 
15384             expression_node_ptr result = node_allocator_->allocate<details::vararg_function_node<Type,ivararg_function<T> > >(vaf,arglist);
15385 
15386             if (!arglist.empty() && is_constant_foldable(arglist))
15387             {
15388                Type v = result->value();
15389                details::free_node(*node_allocator_,result);
15390                result = node_allocator_->allocate<literal_node_t>(v);
15391             }
15392 
15393             return result;
15394          }
15395 
15396          inline expression_node_ptr vector_element(const std::string& symbol,
15397                                                    typename symbol_table_t::vector_ptr vector_base,
15398                                                    expression_node_ptr index)
15399          {
15400             expression_node_ptr result = error_node();
15401 
15402             if (details::is_constant_node(index))
15403             {
15404                std::size_t i = static_cast<std::size_t>(index->value());
15405                details::free_node(*node_allocator_,index);
15406                Type* v = (*vector_base)[i];
15407                const std::string vec_symbol = symbol + "__" + details::to_str(i);
15408                bool created_var = false;
15409 
15410                if (!parser_->local_symbol_table_.symbol_exists(vec_symbol))
15411                {
15412                   parser_->local_symbol_table_.add_variable(vec_symbol,(*v));
15413                   created_var = true;
15414                }
15415 
15416                result = parser_->local_symbol_table_.get_variable(vec_symbol);
15417 
15418                if (created_var)
15419                {
15420                   parser_->register_local_var(result);
15421                }
15422             }
15423             else
15424                result = node_allocator_->allocate<details::vector_node<Type> >(index,(*vector_base)[0]);
15425 
15426             return result;
15427          }
15428 
15429       private:
15430 
15431          template <std::size_t N, typename NodePtr>
15432          inline bool is_constant_foldable(NodePtr (&b)[N]) const
15433          {
15434             for (std::size_t i = 0; i < N; ++i)
15435             {
15436                if (0 == b[i])
15437                   return false;
15438                else if (!details::is_constant_node(b[i]))
15439                   return false;
15440             }
15441 
15442             return true;
15443          }
15444 
15445          template <typename NodePtr,
15446                    typename Allocator,
15447                    template <typename,typename> class Sequence>
15448          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
15449          {
15450             for (std::size_t i = 0; i < b.size(); ++i)
15451             {
15452                if (0 == b[i])
15453                   return false;
15454                else if (!details::is_constant_node(b[i]))
15455                   return false;
15456             }
15457 
15458             return true;
15459          }
15460 
15461          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
15462          {
15463             if (details::is_variable_node(branch[0]))
15464                return synthesize_expression<assignment_node_t,2>(operation,branch);
15465             else if (details::is_vector_node(branch[0]))
15466                return synthesize_expression<assignment_vec_node_t,2>(operation,branch);
15467             else
15468             {
15469                parser_->set_synthesis_error("Invalid assignment operation.[1]");
15470                return error_node();
15471             }
15472          }
15473 
15474          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
15475                                                                                expression_node_ptr (&branch)[2])
15476          {
15477             if (details::is_variable_node(branch[0]))
15478             {
15479                switch (operation)
15480                {
15481                   #define case_stmt(op0,op1)                                                                  \
15482                   case op0 : return node_allocator_->                                                         \
15483                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
15484                                    (operation,branch[0],branch[1]);                                           \
15485 
15486                   case_stmt(details:: e_addass,details:: add_op)
15487                   case_stmt(details:: e_subass,details:: sub_op)
15488                   case_stmt(details:: e_mulass,details:: mul_op)
15489                   case_stmt(details:: e_divass,details:: div_op)
15490                   #undef case_stmt
15491                   default : return error_node();
15492                }
15493             }
15494             if (details::is_vector_node(branch[0]))
15495             {
15496                switch (operation)
15497                {
15498                   #define case_stmt(op0,op1)                                                                      \
15499                   case op0 : return node_allocator_->                                                             \
15500                                 template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
15501                                    (operation,branch[0],branch[1]);                                               \
15502 
15503                   case_stmt(details:: e_addass,details:: add_op)
15504                   case_stmt(details:: e_subass,details:: sub_op)
15505                   case_stmt(details:: e_mulass,details:: mul_op)
15506                   case_stmt(details:: e_divass,details:: div_op)
15507                   #undef case_stmt
15508                   default : return error_node();
15509                }
15510             }
15511             else
15512             {
15513                parser_->set_synthesis_error("Invalid assignment operation[2].");
15514                return error_node();
15515             }
15516          }
15517 
15518          #ifndef exprtk_disable_sc_andor
15519          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
15520          {
15521             expression_node_ptr result = error_node();
15522             if (details::is_constant_node(branch[0]))
15523             {
15524                if ((details::e_scand == operation) && (T(0) == branch[0]->value()))
15525                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
15526                else if ((details::e_scor == operation) && (T(0) != branch[0]->value()))
15527                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
15528             }
15529 
15530             if (details::is_constant_node(branch[1]) && (0 == result))
15531             {
15532                if ((details::e_scand == operation) && (T(0) == branch[1]->value()))
15533                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
15534                else if ((details::e_scor == operation) && (T(0) != branch[1]->value()))
15535                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
15536             }
15537 
15538             if (result)
15539             {
15540                free_node(*node_allocator_,branch[0]);
15541                free_node(*node_allocator_,branch[1]);
15542                return result;
15543             }
15544             else if (details::e_scand == operation)
15545                return synthesize_expression<scand_node_t,2>(operation,branch);
15546             else if (details::e_scor == operation)
15547                return synthesize_expression<scor_node_t,2>(operation,branch);
15548             else
15549                return error_node();
15550          }
15551          #else
15552          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
15553          {
15554             return error_node();
15555          }
15556          #endif
15557 
15558          #define basic_opr_switch_statements         \
15559          case_stmt(details:: e_add,details:: add_op) \
15560          case_stmt(details:: e_sub,details:: sub_op) \
15561          case_stmt(details:: e_mul,details:: mul_op) \
15562          case_stmt(details:: e_div,details:: div_op) \
15563          case_stmt(details:: e_mod,details:: mod_op) \
15564          case_stmt(details:: e_pow,details:: pow_op) \
15565 
15566          #define extended_opr_switch_statements      \
15567          case_stmt(details::  e_lt,details::  lt_op) \
15568          case_stmt(details:: e_lte,details:: lte_op) \
15569          case_stmt(details::  e_gt,details::  gt_op) \
15570          case_stmt(details:: e_gte,details:: gte_op) \
15571          case_stmt(details::  e_eq,details::  eq_op) \
15572          case_stmt(details::  e_ne,details::  ne_op) \
15573          case_stmt(details:: e_and,details:: and_op) \
15574          case_stmt(details::e_nand,details::nand_op) \
15575          case_stmt(details::  e_or,details::  or_op) \
15576          case_stmt(details:: e_nor,details:: nor_op) \
15577          case_stmt(details:: e_xor,details:: xor_op) \
15578          case_stmt(details::e_xnor,details::xnor_op) \
15579 
15580          #ifndef exprtk_disable_cardinal_pow_optimisation
15581          template <template <typename,typename> class IPowNode>
15582          inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p)
15583          {
15584             switch (p)
15585             {
15586                #define case_stmt(cp)                                                     \
15587                case cp : return node_allocator_->                                        \
15588                             allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
15589 
15590                case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
15591                case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
15592                case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
15593                case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
15594                case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
15595                case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
15596                case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
15597                case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
15598                case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
15599                case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
15600                case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
15601                case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
15602                case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
15603                case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
15604                case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
15605                #undef case_stmt
15606                default : return error_node();
15607             }
15608          }
15609 
15610          inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c)
15611          {
15612             const bool not_recipricol = (c >= T(0));
15613             const unsigned int p = static_cast<unsigned int>(std::abs(c));
15614             if (0 == p)
15615                return node_allocator_->allocate_c<literal_node_t>(T(1));
15616             else if (T(2) == c)
15617             {
15618                return node_allocator_->
15619                   template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
15620             }
15621             else
15622             {
15623                if (not_recipricol)
15624                   return cardinal_pow_optimization_impl<details::ipow_node>(v,p);
15625                else
15626                   return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p);
15627             }
15628          }
15629 
15630          inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c)
15631          {
15632             return (details::e_pow == operation) && (std::abs(c) <= T(60)) && details::numeric::is_integer(c);
15633          }
15634          #else
15635          inline expression_node_ptr cardinal_pow_optimization(T&, const T&)
15636          {
15637             return error_node();
15638          }
15639 
15640          inline bool cardinal_pow_optimizable(const details::operator_type&, const T&)
15641          {
15642             return false;
15643          }
15644          #endif
15645 
15646          struct synthesize_binary_ext_expression
15647          {
15648             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15649                                                       const details::operator_type& operation,
15650                                                       expression_node_ptr (&branch)[2])
15651             {
15652                switch (operation)
15653                {
15654                   #define case_stmt(op0,op1)                                                           \
15655                   case op0 : return expr_gen.node_allocator_->                                         \
15656                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
15657                                    (branch[0],branch[1]);                                              \
15658 
15659                   basic_opr_switch_statements
15660                   extended_opr_switch_statements
15661                   #undef case_stmt
15662                   default : return error_node();
15663                }
15664             }
15665          };
15666 
15667          struct synthesize_vob_expression
15668          {
15669             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15670                                                       const details::operator_type& operation,
15671                                                       expression_node_ptr (&branch)[2])
15672             {
15673                const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15674 
15675                if (details::is_sf3ext_node(branch[1]))
15676                {
15677                   expression_node_ptr result = error_node();
15678                   if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result))
15679                   {
15680                      free_node(*expr_gen.node_allocator_,branch[1]);
15681                      return result;
15682                   }
15683                }
15684 
15685                switch (operation)
15686                {
15687                   #define case_stmt(op0,op1)                                                       \
15688                   case op0 : return expr_gen.node_allocator_->                                     \
15689                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
15690                                    (v,branch[1]);                                                  \
15691 
15692                   basic_opr_switch_statements
15693                   extended_opr_switch_statements
15694                   #undef case_stmt
15695                   default : return error_node();
15696                }
15697             }
15698          };
15699 
15700          struct synthesize_bov_expression
15701          {
15702             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15703                                                       const details::operator_type& operation,
15704                                                       expression_node_ptr (&branch)[2])
15705             {
15706                const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15707 
15708                if (details::is_sf3ext_node(branch[0]))
15709                {
15710                   expression_node_ptr result = error_node();
15711                   if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
15712                   {
15713                      free_node(*expr_gen.node_allocator_,branch[0]);
15714                      return result;
15715                   }
15716                }
15717 
15718                switch (operation)
15719                {
15720                   #define case_stmt(op0,op1)                                                       \
15721                   case op0 : return expr_gen.node_allocator_->                                     \
15722                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
15723                                    (branch[0],v);                                                  \
15724 
15725                   basic_opr_switch_statements
15726                   extended_opr_switch_statements
15727                   #undef case_stmt
15728                   default : return error_node();
15729                }
15730             }
15731          };
15732 
15733          struct synthesize_cob_expression
15734          {
15735             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15736                                                       const details::operator_type& operation,
15737                                                       expression_node_ptr (&branch)[2])
15738             {
15739                const Type c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
15740                free_node(*expr_gen.node_allocator_,branch[0]);
15741                if (details::is_cob_node(branch[1]))
15742                {
15743                   // Simplify expressions of the form:
15744                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x)))))))))
15745                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x)))))))))
15746                   if (
15747                        (operation == details::e_mul) ||
15748                        (operation == details::e_add)
15749                      )
15750                   {
15751                      details::cob_base_node<Type>* cobnode = dynamic_cast<details::cob_base_node<Type>*>(branch[1]);
15752                      if (operation == cobnode->operation())
15753                      {
15754                         switch (operation)
15755                         {
15756                            case details::e_add : cobnode->set_c(c + cobnode->c()); break;
15757                            case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
15758                            default             : return error_node();
15759                         }
15760                         return cobnode;
15761                      }
15762                   }
15763 
15764                   if (operation == details::e_mul)
15765                   {
15766                      details::cob_base_node<Type>* cobnode = dynamic_cast<details::cob_base_node<Type>*>(branch[1]);
15767                      details::operator_type cob_opr = cobnode->operation();
15768 
15769                      if (
15770                           (details::e_div == cob_opr) ||
15771                           (details::e_mul == cob_opr)
15772                         )
15773                      {
15774                         switch (cob_opr)
15775                         {
15776                            case details::e_div : cobnode->set_c(c * cobnode->c()); break;
15777                            case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
15778                            default             : return error_node();
15779                         }
15780                         return cobnode;
15781                      }
15782                   }
15783                   else if (operation == details::e_div)
15784                   {
15785                      details::cob_base_node<Type>* cobnode = dynamic_cast<details::cob_base_node<Type>*>(branch[1]);
15786                      details::operator_type cob_opr = cobnode->operation();
15787 
15788                      if (
15789                           (details::e_div == cob_opr) ||
15790                           (details::e_mul == cob_opr)
15791                         )
15792                      {
15793                         details::expression_node<Type>* new_cobnode = error_node();
15794                         switch (cob_opr)
15795                         {
15796                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
15797                                                                   template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
15798                                                                      (c / cobnode->c(),cobnode->move_branch(0));
15799                                                  break;
15800 
15801                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
15802                                                                   template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
15803                                                                      (c / cobnode->c(),cobnode->move_branch(0));
15804                                                  break;
15805 
15806                            default             : return error_node();
15807                         }
15808 
15809                         free_node(*expr_gen.node_allocator_,branch[1]);
15810                         return new_cobnode;
15811                      }
15812                   }
15813                }
15814                else if (details::is_sf3ext_node(branch[1]))
15815                {
15816                   expression_node_ptr result = error_node();
15817                   if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
15818                   {
15819                      free_node(*expr_gen.node_allocator_,branch[1]);
15820                      return result;
15821                   }
15822                }
15823 
15824                switch (operation)
15825                {
15826                   #define case_stmt(op0,op1)                                                       \
15827                   case op0 : return expr_gen.node_allocator_->                                     \
15828                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
15829                                    (c,branch[1]);                                                  \
15830 
15831                   basic_opr_switch_statements
15832                   extended_opr_switch_statements
15833                   #undef case_stmt
15834                   default : return error_node();
15835                }
15836             }
15837          };
15838 
15839          struct synthesize_boc_expression
15840          {
15841             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15842                                                       const details::operator_type& operation,
15843                                                       expression_node_ptr (&branch)[2])
15844             {
15845                const Type c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
15846                details::free_node(*(expr_gen.node_allocator_),branch[1]);
15847                if (details::is_boc_node(branch[0]))
15848                {
15849                   // Simplify expressions of the form:
15850                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1)
15851                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1)
15852                   if (
15853                        (operation == details::e_mul) ||
15854                        (operation == details::e_add)
15855                      )
15856                   {
15857                      details::boc_base_node<Type>* bocnode = dynamic_cast<details::boc_base_node<Type>*>(branch[0]);
15858                      if (operation == bocnode->operation())
15859                      {
15860                         switch (operation)
15861                         {
15862                            case details::e_add : bocnode->set_c(c + bocnode->c()); break;
15863                            case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
15864                            default             : return error_node();
15865                         }
15866                         return bocnode;
15867                      }
15868                   }
15869                   else if (operation == details::e_div)
15870                   {
15871                      details::boc_base_node<Type>* bocnode = dynamic_cast<details::boc_base_node<Type>*>(branch[0]);
15872                      details::operator_type boc_opr = bocnode->operation();
15873 
15874                      if (
15875                           (details::e_div == boc_opr) ||
15876                           (details::e_mul == boc_opr)
15877                         )
15878                      {
15879                         switch (boc_opr)
15880                         {
15881                            case details::e_div : bocnode->set_c(c * bocnode->c()); break;
15882                            case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
15883                            default             : return error_node();
15884                         }
15885                         return bocnode;
15886                      }
15887                   }
15888                }
15889 
15890                if (details::is_sf3ext_node(branch[0]))
15891                {
15892                   expression_node_ptr result = error_node();
15893                   if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result))
15894                   {
15895                      free_node(*expr_gen.node_allocator_,branch[0]);
15896                      return result;
15897                   }
15898                }
15899 
15900                switch (operation)
15901                {
15902                   #define case_stmt(op0,op1)                                                    \
15903                   case op0 : return expr_gen.node_allocator_->                                  \
15904                              template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
15905                                 (branch[0],c);                                                  \
15906 
15907                   basic_opr_switch_statements
15908                   extended_opr_switch_statements
15909                   #undef case_stmt
15910                   default : return error_node();
15911                }
15912             }
15913          };
15914 
15915          inline bool synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2], expression_node_ptr& result)
15916          {
15917             result = error_node();
15918             if (!operation_optimizable(operation))
15919                return false;
15920             const std::string node_id = branch_to_id(branch);
15921             typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
15922             if (synthesize_map_.end() != itr)
15923             {
15924                result = itr->second(*this,operation,branch);
15925                return true;
15926             }
15927             else
15928                return false;
15929          }
15930 
15931          struct synthesize_vov_expression
15932          {
15933             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15934                                                       const details::operator_type& operation,
15935                                                       expression_node_ptr (&branch)[2])
15936             {
15937                const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15938                const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15939                switch (operation)
15940                {
15941                   #define case_stmt(op0,op1)                                                       \
15942                   case op0 : return expr_gen.node_allocator_->                                     \
15943                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
15944                                    (v1,v2);                                                        \
15945 
15946                   basic_opr_switch_statements
15947                   extended_opr_switch_statements
15948                   #undef case_stmt
15949                   default : return error_node();
15950                }
15951             }
15952          };
15953 
15954          struct synthesize_cov_expression
15955          {
15956             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15957                                                       const details::operator_type& operation,
15958                                                       expression_node_ptr (&branch)[2])
15959             {
15960                const Type  c = dynamic_cast<details::literal_node<Type>*> (branch[0])->value();
15961                const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15962                details::free_node(*(expr_gen.node_allocator_),branch[0]);
15963                switch (operation)
15964                {
15965                   #define case_stmt(op0,op1)                                                       \
15966                   case op0 : return expr_gen.node_allocator_->                                     \
15967                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
15968                                    (c,v);                                                          \
15969 
15970                   basic_opr_switch_statements
15971                   extended_opr_switch_statements
15972                   #undef case_stmt
15973                   default : return error_node();
15974                }
15975             }
15976          };
15977 
15978          struct synthesize_voc_expression
15979          {
15980             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15981                                                       const details::operator_type& operation,
15982                                                       expression_node_ptr (&branch)[2])
15983             {
15984                const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15985                const Type  c = dynamic_cast<details::literal_node<Type>*> (branch[1])->value();
15986                details::free_node(*(expr_gen.node_allocator_),branch[1]);
15987 
15988                if (expr_gen.cardinal_pow_optimizable(operation,c))
15989                {
15990                   if (T(1) == c)
15991                      return branch[0];
15992                   else
15993                      return expr_gen.cardinal_pow_optimization(v,c);
15994                }
15995 
15996                switch (operation)
15997                {
15998                   #define case_stmt(op0,op1)                                                       \
15999                   case op0 : return expr_gen.node_allocator_->                                     \
16000                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
16001                                    (v,c);                                                          \
16002 
16003                   basic_opr_switch_statements
16004                   extended_opr_switch_statements
16005                   #undef case_stmt
16006                   default : return error_node();
16007                }
16008             }
16009          };
16010 
16011          struct synthesize_sf3ext_expression
16012          {
16013             template <typename T0, typename T1, typename T2>
16014             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16015                                                       const details::operator_type& sf3opr,
16016                                                       T0 t0, T1 t1, T2 t2)
16017             {
16018                switch (sf3opr)
16019                {
16020                   #define case_stmt(op0,op1)                                           \
16021                   case op0 : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,op1<Type> >::  \
16022                                        allocate(*(expr_gen.node_allocator_),t0,t1,t2); \
16023 
16024                   case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
16025                   case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
16026                   case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
16027                   case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
16028                   case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
16029                   case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
16030                   case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
16031                   case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
16032                   case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
16033                   case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
16034                   case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
16035                   case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
16036                   case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
16037                   case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
16038                   case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
16039                   case_stmt(details::e_sf30,details::sf30_op)
16040                   #undef case_stmt
16041                   default : return error_node();
16042                }
16043             }
16044 
16045             template <typename T0, typename T1, typename T2>
16046             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
16047                                        T0 t0, T1 t1, T2 t2,
16048                                        expression_node_ptr& result)
16049             {
16050                details::operator_type sf3opr;
16051                if (!expr_gen.sf3_optimizable(id,sf3opr))
16052                   return false;
16053                else
16054                   result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
16055                return true;
16056             }
16057 
16058          };
16059 
16060          struct synthesize_sf4ext_expression
16061          {
16062             template <typename T0, typename T1, typename T2, typename T3>
16063             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16064                                                       const details::operator_type& sf4opr,
16065                                                       T0 t0, T1 t1, T2 t2, T3 t3)
16066             {
16067                switch (sf4opr)
16068                {
16069                   #define case_stmt(op0,op1)                                                   \
16070                   case op0 : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,op1<Type> >:: \
16071                                        allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3);      \
16072 
16073                   case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
16074                   case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
16075                   case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
16076                   case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
16077                   case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
16078                   case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
16079                   case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
16080                   case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
16081                   case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
16082                   case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
16083                   case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
16084                   case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
16085                   case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
16086                   case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
16087                   case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
16088                   case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
16089                   case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
16090                   case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
16091                   case_stmt(details::e_sf4ext00,details::sfext00_op) case_stmt(details::e_sf4ext01,details::sfext01_op)
16092                   case_stmt(details::e_sf4ext02,details::sfext02_op) case_stmt(details::e_sf4ext03,details::sfext03_op)
16093                   case_stmt(details::e_sf4ext04,details::sfext04_op) case_stmt(details::e_sf4ext05,details::sfext05_op)
16094                   case_stmt(details::e_sf4ext06,details::sfext06_op) case_stmt(details::e_sf4ext07,details::sfext07_op)
16095                   case_stmt(details::e_sf4ext08,details::sfext08_op) case_stmt(details::e_sf4ext09,details::sfext09_op)
16096                   case_stmt(details::e_sf4ext10,details::sfext10_op) case_stmt(details::e_sf4ext11,details::sfext11_op)
16097                   case_stmt(details::e_sf4ext12,details::sfext12_op) case_stmt(details::e_sf4ext13,details::sfext13_op)
16098                   case_stmt(details::e_sf4ext14,details::sfext14_op) case_stmt(details::e_sf4ext15,details::sfext15_op)
16099                   case_stmt(details::e_sf4ext16,details::sfext16_op) case_stmt(details::e_sf4ext17,details::sfext17_op)
16100                   case_stmt(details::e_sf4ext18,details::sfext18_op) case_stmt(details::e_sf4ext19,details::sfext19_op)
16101                   case_stmt(details::e_sf4ext20,details::sfext20_op) case_stmt(details::e_sf4ext21,details::sfext21_op)
16102                   case_stmt(details::e_sf4ext22,details::sfext22_op) case_stmt(details::e_sf4ext23,details::sfext23_op)
16103                   case_stmt(details::e_sf4ext24,details::sfext24_op) case_stmt(details::e_sf4ext25,details::sfext25_op)
16104                   case_stmt(details::e_sf4ext26,details::sfext26_op) case_stmt(details::e_sf4ext27,details::sfext27_op)
16105                   case_stmt(details::e_sf4ext28,details::sfext28_op) case_stmt(details::e_sf4ext29,details::sfext29_op)
16106                   case_stmt(details::e_sf4ext30,details::sfext30_op) case_stmt(details::e_sf4ext31,details::sfext31_op)
16107                   case_stmt(details::e_sf4ext32,details::sfext32_op) case_stmt(details::e_sf4ext33,details::sfext33_op)
16108                   case_stmt(details::e_sf4ext34,details::sfext34_op) case_stmt(details::e_sf4ext35,details::sfext35_op)
16109                   case_stmt(details::e_sf4ext36,details::sfext36_op) case_stmt(details::e_sf4ext37,details::sfext37_op)
16110                   case_stmt(details::e_sf4ext38,details::sfext38_op) case_stmt(details::e_sf4ext39,details::sfext39_op)
16111                   case_stmt(details::e_sf4ext40,details::sfext40_op) case_stmt(details::e_sf4ext41,details::sfext41_op)
16112                   case_stmt(details::e_sf4ext42,details::sfext42_op) case_stmt(details::e_sf4ext43,details::sfext43_op)
16113                   case_stmt(details::e_sf4ext44,details::sfext44_op) case_stmt(details::e_sf4ext45,details::sfext45_op)
16114                   #undef case_stmt
16115                   default : return error_node();
16116                }
16117             }
16118 
16119             template <typename T0, typename T1, typename T2, typename T3>
16120             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
16121                                        T0 t0, T1 t1, T2 t2, T3 t3,
16122                                        expression_node_ptr& result)
16123             {
16124                details::operator_type sf4opr;
16125                if (!expr_gen.sf4_optimizable(id,sf4opr))
16126                   return false;
16127                else
16128                   result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
16129                return true;
16130             }
16131 
16132             // T o (sf3ext)
16133             template <typename ExternalType>
16134             static inline bool compile_right(expression_generator<Type>& expr_gen,
16135                                              ExternalType t,
16136                                              const details::operator_type& operation,
16137                                              expression_node_ptr& sf3node,
16138                                              expression_node_ptr& result)
16139             {
16140                if (!details::is_sf3ext_node(sf3node))
16141                   return false;
16142 
16143                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
16144                sf3ext_base_ptr n = dynamic_cast<sf3ext_base_ptr>(sf3node);
16145                std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
16146 
16147                switch (n->type())
16148                {
16149                   case details::expression_node<Type>::e_covoc : return compile_right_impl
16150                                                                         <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16151 
16152                   case details::expression_node<Type>::e_covov : return compile_right_impl
16153                                                                         <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16154 
16155                   case details::expression_node<Type>::e_vocov : return compile_right_impl
16156                                                                         <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>(expr_gen,id,t,sf3node,result);
16157 
16158                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
16159                                                                         <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16160 
16161                   case details::expression_node<Type>::e_vovov : return compile_right_impl
16162                                                                         <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16163 
16164                   default                                      : return false;
16165                }
16166             }
16167 
16168             // (sf3ext) o T
16169             template <typename ExternalType>
16170             static inline bool compile_left(expression_generator<Type>& expr_gen,
16171                                             ExternalType t,
16172                                             const details::operator_type& operation,
16173                                             expression_node_ptr& sf3node,
16174                                             expression_node_ptr& result)
16175             {
16176                if (!details::is_sf3ext_node(sf3node))
16177                   return false;
16178 
16179                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
16180                sf3ext_base_ptr n = dynamic_cast<sf3ext_base_ptr>(sf3node);
16181                std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
16182                switch (n->type())
16183                {
16184                   case details::expression_node<Type>::e_covoc : return compile_left_impl
16185                                                                         <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16186 
16187                   case details::expression_node<Type>::e_covov : return compile_left_impl
16188                                                                         <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16189 
16190                   case details::expression_node<Type>::e_vocov : return compile_left_impl
16191                                                                         <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>(expr_gen,id,t,sf3node,result);
16192 
16193                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
16194                                                                         <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16195 
16196                   case details::expression_node<Type>::e_vovov : return compile_left_impl
16197                                                                         <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16198 
16199                   default                                      : return false;
16200                }
16201             }
16202 
16203             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
16204             static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
16205                                                   const std::string& id,
16206                                                   ExternalType t,
16207                                                   expression_node_ptr& node,
16208                                                   expression_node_ptr& result)
16209             {
16210                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
16211                if (n)
16212                {
16213                   T0 t0 = n->t0();
16214                   T1 t1 = n->t1();
16215                   T2 t2 = n->t2();
16216                   return synthesize_sf4ext_expression::
16217                            template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result);
16218                }
16219                else
16220                   return false;
16221             }
16222 
16223             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
16224             static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
16225                                                  const std::string& id,
16226                                                  ExternalType t,
16227                                                  expression_node_ptr& node,
16228                                                  expression_node_ptr& result)
16229             {
16230                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
16231                if (n)
16232                {
16233                   T0 t0 = n->t0();
16234                   T1 t1 = n->t1();
16235                   T2 t2 = n->t2();
16236                   return synthesize_sf4ext_expression::
16237                            template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result);
16238                }
16239                else
16240                   return false;
16241             }
16242          };
16243 
16244          struct synthesize_vovov_expression0
16245          {
16246             typedef typename vovov_t::type0 node_type;
16247             typedef typename vovov_t::sf3_type sf3_type;
16248             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16249                                                       const details::operator_type& operation,
16250                                                       expression_node_ptr (&branch)[2])
16251             {
16252                // (v0 o0 v1) o1 (v2)
16253                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
16254                const Type& v0 = vov->v0();
16255                const Type& v1 = vov->v1();
16256                const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
16257                const details::operator_type o0 = vov->operation();
16258                const details::operator_type o1 = operation;
16259                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16260                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16261                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16262                expression_node_ptr result = error_node();
16263 
16264                if (expr_gen.strength_reduction_enabled())
16265                {
16266                   // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
16267                   if ((details::e_div == o0) && (details::e_div == o1))
16268                   {
16269                      const bool synthesis_result =
16270                         synthesize_sf3ext_expression::
16271                            template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
16272                      return (synthesis_result) ? result : error_node();
16273                   }
16274                }
16275 
16276                if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
16277                   return result;
16278                else if (!expr_gen.valid_operator(o0,f0))
16279                   return error_node();
16280                else if (!expr_gen.valid_operator(o1,f1))
16281                   return error_node();
16282                else
16283                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
16284             }
16285 
16286             static inline std::string id(expression_generator<Type>& expr_gen,
16287                                          const details::operator_type o0, const details::operator_type o1)
16288             {
16289                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16290             }
16291          };
16292 
16293          struct synthesize_vovov_expression1
16294          {
16295             typedef typename vovov_t::type1 node_type;
16296             typedef typename vovov_t::sf3_type sf3_type;
16297             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16298                                                       const details::operator_type& operation,
16299                                                       expression_node_ptr (&branch)[2])
16300             {
16301                // (v0) o0 (v1 o1 v2)
16302                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
16303                const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
16304                const Type& v1 = vov->v0();
16305                const Type& v2 = vov->v1();
16306                const details::operator_type o0 = operation;
16307                const details::operator_type o1 = vov->operation();
16308                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16309                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16310                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16311                expression_node_ptr result = error_node();
16312 
16313                if (expr_gen.strength_reduction_enabled())
16314                {
16315                   // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
16316                   if ((details::e_div == o0) && (details::e_div == o1))
16317                   {
16318                      const bool synthesis_result =
16319                         synthesize_sf3ext_expression::
16320                            template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
16321                      return (synthesis_result) ? result : error_node();
16322                   }
16323                }
16324 
16325                if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
16326                   return result;
16327                else if (!expr_gen.valid_operator(o0,f0))
16328                   return error_node();
16329                else if (!expr_gen.valid_operator(o1,f1))
16330                   return error_node();
16331                else
16332                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
16333             }
16334 
16335             static inline std::string id(expression_generator<Type>& expr_gen,
16336                                          const details::operator_type o0, const details::operator_type o1)
16337             {
16338                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16339             }
16340          };
16341 
16342          struct synthesize_vovoc_expression0
16343          {
16344             typedef typename vovoc_t::type0 node_type;
16345             typedef typename vovoc_t::sf3_type sf3_type;
16346             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16347                                                       const details::operator_type& operation,
16348                                                       expression_node_ptr (&branch)[2])
16349             {
16350                // (v0 o0 v1) o1 (c)
16351                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
16352                const Type& v0 = vov->v0();
16353                const Type& v1 = vov->v1();
16354                const Type   c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
16355                const details::operator_type o0 = vov->operation();
16356                const details::operator_type o1 = operation;
16357                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16358                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16359                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16360                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16361                expression_node_ptr result = error_node();
16362 
16363                if (expr_gen.strength_reduction_enabled())
16364                {
16365                   // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
16366                   if ((details::e_div == o0) && (details::e_div == o1))
16367                   {
16368                      const bool synthesis_result =
16369                         synthesize_sf3ext_expression::
16370                            template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
16371                      return (synthesis_result) ? result : error_node();
16372                   }
16373                }
16374 
16375                if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
16376                   return result;
16377                else if (!expr_gen.valid_operator(o0,f0))
16378                   return error_node();
16379                else if (!expr_gen.valid_operator(o1,f1))
16380                   return error_node();
16381                else
16382                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
16383             }
16384 
16385             static inline std::string id(expression_generator<Type>& expr_gen,
16386                                          const details::operator_type o0, const details::operator_type o1)
16387             {
16388                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16389             }
16390          };
16391 
16392          struct synthesize_vovoc_expression1
16393          {
16394             typedef typename vovoc_t::type1 node_type;
16395             typedef typename vovoc_t::sf3_type sf3_type;
16396             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16397                                                       const details::operator_type& operation,
16398                                                       expression_node_ptr (&branch)[2])
16399             {
16400                // (v0) o0 (v1 o1 c)
16401                const details::voc_base_node<Type>* voc = dynamic_cast<const details::voc_base_node<Type>*>(branch[1]);
16402                const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
16403                const Type& v1 = voc->v();
16404                const Type   c = voc->c();
16405                const details::operator_type o0 = operation;
16406                const details::operator_type o1 = voc->operation();
16407                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16408                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16409                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16410                expression_node_ptr result = error_node();
16411 
16412                if (expr_gen.strength_reduction_enabled())
16413                {
16414                   // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
16415                   if ((details::e_div == o0) && (details::e_div == o1))
16416                   {
16417                      const bool synthesis_result =
16418                         synthesize_sf3ext_expression::
16419                            template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
16420                      return (synthesis_result) ? result : error_node();
16421                   }
16422                }
16423 
16424                if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
16425                   return result;
16426                else if (!expr_gen.valid_operator(o0,f0))
16427                   return error_node();
16428                else if (!expr_gen.valid_operator(o1,f1))
16429                   return error_node();
16430                else
16431                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
16432             }
16433 
16434             static inline std::string id(expression_generator<Type>& expr_gen,
16435                                          const details::operator_type o0, const details::operator_type o1)
16436             {
16437                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16438             }
16439          };
16440 
16441          struct synthesize_vocov_expression0
16442          {
16443             typedef typename vocov_t::type0 node_type;
16444             typedef typename vocov_t::sf3_type sf3_type;
16445             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16446                                                       const details::operator_type& operation,
16447                                                       expression_node_ptr (&branch)[2])
16448             {
16449                // (v0 o0 c) o1 (v1)
16450                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
16451                const Type& v0 = voc->v();
16452                const Type   c = voc->c();
16453                const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
16454                const details::operator_type o0 = voc->operation();
16455                const details::operator_type o1 = operation;
16456                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16457                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16458                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16459                expression_node_ptr result = error_node();
16460 
16461                if (expr_gen.strength_reduction_enabled())
16462                {
16463                   // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
16464                   if ((details::e_div == o0) && (details::e_div == o1))
16465                   {
16466                      const bool synthesis_result =
16467                         synthesize_sf3ext_expression::
16468                            template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
16469                      return (synthesis_result) ? result : error_node();
16470                   }
16471                }
16472 
16473                if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
16474                   return result;
16475                else if (!expr_gen.valid_operator(o0,f0))
16476                   return error_node();
16477                else if (!expr_gen.valid_operator(o1,f1))
16478                   return error_node();
16479                else
16480                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
16481             }
16482 
16483             static inline std::string id(expression_generator<Type>& expr_gen,
16484                                          const details::operator_type o0, const details::operator_type o1)
16485             {
16486                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16487             }
16488          };
16489 
16490          struct synthesize_vocov_expression1
16491          {
16492             typedef typename vocov_t::type1 node_type;
16493             typedef typename vocov_t::sf3_type sf3_type;
16494             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16495                                                       const details::operator_type& operation,
16496                                                       expression_node_ptr (&branch)[2])
16497             {
16498                // (v0) o0 (c o1 v1)
16499                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
16500                const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
16501                const Type   c = cov->c();
16502                const Type& v1 = cov->v();
16503                const details::operator_type o0 = operation;
16504                const details::operator_type o1 = cov->operation();
16505                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16506                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16507                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16508                expression_node_ptr result = error_node();
16509 
16510                if (expr_gen.strength_reduction_enabled())
16511                {
16512                   // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
16513                   if ((details::e_div == o0) && (details::e_div == o1))
16514                   {
16515                      const bool synthesis_result =
16516                         synthesize_sf3ext_expression::
16517                            template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
16518                      return (synthesis_result) ? result : error_node();
16519                   }
16520                }
16521 
16522                if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
16523                   return result;
16524                else if (!expr_gen.valid_operator(o0,f0))
16525                   return error_node();
16526                else if (!expr_gen.valid_operator(o1,f1))
16527                   return error_node();
16528                else
16529                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
16530             }
16531 
16532             static inline std::string id(expression_generator<Type>& expr_gen,
16533                                          const details::operator_type o0, const details::operator_type o1)
16534             {
16535                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16536             }
16537          };
16538 
16539          struct synthesize_covov_expression0
16540          {
16541             typedef typename covov_t::type0 node_type;
16542             typedef typename covov_t::sf3_type sf3_type;
16543             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16544                                                       const details::operator_type& operation,
16545                                                       expression_node_ptr (&branch)[2])
16546             {
16547                // (c o0 v0) o1 (v1)
16548                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
16549                const Type   c = cov->c();
16550                const Type& v0 = cov->v();
16551                const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
16552                const details::operator_type o0 = cov->operation();
16553                const details::operator_type o1 = operation;
16554                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16555                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16556                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16557                expression_node_ptr result = error_node();
16558 
16559                if (expr_gen.strength_reduction_enabled())
16560                {
16561                   // (c / v0) / v1 --> (covov) c / (v0 * v1)
16562                   if ((details::e_div == o0) && (details::e_div == o1))
16563                   {
16564                      const bool synthesis_result =
16565                         synthesize_sf3ext_expression::
16566                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
16567                      return (synthesis_result) ? result : error_node();
16568                   }
16569                }
16570 
16571                if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
16572                   return result;
16573                else if (!expr_gen.valid_operator(o0,f0))
16574                   return error_node();
16575                else if (!expr_gen.valid_operator(o1,f1))
16576                   return error_node();
16577                else
16578                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
16579             }
16580 
16581             static inline std::string id(expression_generator<Type>& expr_gen,
16582                                          const details::operator_type o0, const details::operator_type o1)
16583             {
16584                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16585             }
16586          };
16587 
16588          struct synthesize_covov_expression1
16589          {
16590             typedef typename covov_t::type1 node_type;
16591             typedef typename covov_t::sf3_type sf3_type;
16592             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16593                                                       const details::operator_type& operation,
16594                                                       expression_node_ptr (&branch)[2])
16595             {
16596                // (c) o0 (v0 o1 v1)
16597                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
16598                const Type   c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
16599                const Type& v0 = vov->v0();
16600                const Type& v1 = vov->v1();
16601                const details::operator_type o0 = operation;
16602                const details::operator_type o1 = vov->operation();
16603                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16604                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16605                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16606                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16607                expression_node_ptr result = error_node();
16608 
16609                if (expr_gen.strength_reduction_enabled())
16610                {
16611                   // c / (v0 / v1) --> (covov) (c * v1) / v0
16612                   if ((details::e_div == o0) && (details::e_div == o1))
16613                   {
16614                      const bool synthesis_result =
16615                         synthesize_sf3ext_expression::
16616                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
16617                      return (synthesis_result) ? result : error_node();
16618                   }
16619                }
16620 
16621                if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
16622                   return result;
16623                else if (!expr_gen.valid_operator(o0,f0))
16624                   return error_node();
16625                else if (!expr_gen.valid_operator(o1,f1))
16626                   return error_node();
16627                else
16628                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
16629             }
16630 
16631             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
16632             {
16633                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16634             }
16635          };
16636 
16637          struct synthesize_covoc_expression0
16638          {
16639             typedef typename covoc_t::type0 node_type;
16640             typedef typename covoc_t::sf3_type sf3_type;
16641             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16642                                                       const details::operator_type& operation,
16643                                                       expression_node_ptr (&branch)[2])
16644             {
16645                // (c0 o0 v) o1 (c1)
16646                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
16647                const Type  c0 = cov->c();
16648                const Type&  v = cov->v();
16649                const Type  c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
16650                const details::operator_type o0 = cov->operation();
16651                const details::operator_type o1 = operation;
16652                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16653                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16654                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16655                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16656                expression_node_ptr result = error_node();
16657 
16658                if (expr_gen.strength_reduction_enabled())
16659                {
16660                   // (c0 + v) + c1 --> (cov) (c0 + c1) + v
16661                   if ((details::e_add == o0) && (details::e_add == o1))
16662                   {
16663                      return expr_gen.node_allocator_->
16664                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
16665                   }
16666                   // (c0 + v) - c1 --> (cov) (c0 - c1) + v
16667                   else if ((details::e_add == o0) && (details::e_sub == o1))
16668                   {
16669                      return expr_gen.node_allocator_->
16670                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
16671                   }
16672                   // (c0 - v) + c1 --> (cov) (c0 + c1) - v
16673                   else if ((details::e_sub == o0) && (details::e_add == o1))
16674                   {
16675                      return expr_gen.node_allocator_->
16676                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
16677                   }
16678                   // (c0 - v) - c1 --> (cov) (c0 - c1) - v
16679                   else if ((details::e_sub == o0) && (details::e_sub == o1))
16680                   {
16681                      return expr_gen.node_allocator_->
16682                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
16683                   }
16684                   // (c0 * v) * c1 --> (cov) (c0 * c1) * v
16685                   else if ((details::e_mul == o0) && (details::e_mul == o1))
16686                   {
16687                      return expr_gen.node_allocator_->
16688                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
16689                   }
16690                   // (c0 * v) / c1 --> (cov) (c0 / c1) * v
16691                   else if ((details::e_mul == o0) && (details::e_div == o1))
16692                   {
16693                      return expr_gen.node_allocator_->
16694                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
16695                   }
16696                   // (c0 / v) * c1 --> (cov) (c0 * c1) / v
16697                   else if ((details::e_div == o0) && (details::e_mul == o1))
16698                   {
16699                      return expr_gen.node_allocator_->
16700                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
16701                   }
16702                   // (c0 / v) / c1 --> (cov) (c0 / c1) / v
16703                   else if ((details::e_div == o0) && (details::e_div == o1))
16704                   {
16705                      return expr_gen.node_allocator_->
16706                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
16707                   }
16708                }
16709 
16710                if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
16711                   return result;
16712                else if (!expr_gen.valid_operator(o0,f0))
16713                   return error_node();
16714                else if (!expr_gen.valid_operator(o1,f1))
16715                   return error_node();
16716                else
16717                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
16718             }
16719 
16720             static inline std::string id(expression_generator<Type>& expr_gen,
16721                                          const details::operator_type o0, const details::operator_type o1)
16722             {
16723                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16724             }
16725          };
16726 
16727          struct synthesize_covoc_expression1
16728          {
16729             typedef typename covoc_t::type1 node_type;
16730             typedef typename covoc_t::sf3_type sf3_type;
16731             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16732                                                       const details::operator_type& operation,
16733                                                       expression_node_ptr (&branch)[2])
16734             {
16735                // (c0) o0 (v o1 c1)
16736                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
16737                const Type  c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
16738                const Type&  v = voc->v();
16739                const Type  c1 = voc->c();
16740                const details::operator_type o0 = operation;
16741                const details::operator_type o1 = voc->operation();
16742                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16743                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16744                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16745                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16746                expression_node_ptr result = error_node();
16747 
16748                if (expr_gen.strength_reduction_enabled())
16749                {
16750                   // (c0) + (v + c1) --> (cov) (c0 + c1) + v
16751                   if ((details::e_add == o0) && (details::e_add == o1))
16752                   {
16753                      return expr_gen.node_allocator_->
16754                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
16755                   }
16756                   // (c0) + (v - c1) --> (cov) (c0 - c1) + v
16757                   else if ((details::e_add == o0) && (details::e_sub == o1))
16758                   {
16759                      return expr_gen.node_allocator_->
16760                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
16761                   }
16762                   // (c0) - (v + c1) --> (cov) (c0 - c1) - v
16763                   else if ((details::e_sub == o0) && (details::e_add == o1))
16764                   {
16765                      return expr_gen.node_allocator_->
16766                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
16767                   }
16768                   // (c0) - (v - c1) --> (cov) (c0 + c1) - v
16769                   else if ((details::e_sub == o0) && (details::e_sub == o1))
16770                   {
16771                      return expr_gen.node_allocator_->
16772                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
16773                   }
16774                   // (c0) * (v * c1) --> (voc) v * (c0 * c1)
16775                   else if ((details::e_mul == o0) && (details::e_mul == o1))
16776                   {
16777                      return expr_gen.node_allocator_->
16778                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
16779                   }
16780                   // (c0) * (v / c1) --> (cov) (c0 / c1) * v
16781                   else if ((details::e_mul == o0) && (details::e_div == o1))
16782                   {
16783                      return expr_gen.node_allocator_->
16784                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
16785                   }
16786                   // (c0) / (v * c1) --> (cov) (c0 / c1) / v
16787                   else if ((details::e_div == o0) && (details::e_mul == o1))
16788                   {
16789                      return expr_gen.node_allocator_->
16790                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
16791                   }
16792                   // (c0) / (v / c1) --> (cov) (c0 * c1) / v
16793                   else if ((details::e_div == o0) && (details::e_div == o1))
16794                   {
16795                      return expr_gen.node_allocator_->
16796                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
16797                   }
16798                }
16799 
16800                if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
16801                   return result;
16802                else if (!expr_gen.valid_operator(o0,f0))
16803                   return error_node();
16804                else if (!expr_gen.valid_operator(o1,f1))
16805                   return error_node();
16806                else
16807                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
16808             }
16809 
16810             static inline std::string id(expression_generator<Type>& expr_gen,
16811                                          const details::operator_type o0, const details::operator_type o1)
16812             {
16813                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16814             }
16815          };
16816 
16817          struct synthesize_cocov_expression0
16818          {
16819             typedef typename cocov_t::type0 node_type;
16820             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
16821             {
16822                // (c0 o0 c1) o1 (v) - Not possible.
16823                return error_node();
16824             }
16825          };
16826 
16827          struct synthesize_cocov_expression1
16828          {
16829             typedef typename cocov_t::type1 node_type;
16830             typedef typename cocov_t::sf3_type sf3_type;
16831             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16832                                                       const details::operator_type& operation,
16833                                                       expression_node_ptr (&branch)[2])
16834             {
16835                // (c0) o0 (c1 o1 v)
16836                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
16837                const Type  c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
16838                const Type  c1 = cov->c();
16839                const Type&  v = cov->v();
16840                const details::operator_type o0 = operation;
16841                const details::operator_type o1 = cov->operation();
16842                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16843                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16844                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16845                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16846                expression_node_ptr result = error_node();
16847 
16848                if (expr_gen.strength_reduction_enabled())
16849                {
16850                   // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
16851                   if ((details::e_add == o0) && (details::e_add == o1))
16852                   {
16853                      return expr_gen.node_allocator_->
16854                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
16855                   }
16856                   // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
16857                   else if ((details::e_add == o0) && (details::e_sub == o1))
16858                   {
16859                      return expr_gen.node_allocator_->
16860                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
16861                   }
16862                   // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
16863                   else if ((details::e_sub == o0) && (details::e_add == o1))
16864                   {
16865                      return expr_gen.node_allocator_->
16866                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
16867                   }
16868                   // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
16869                   else if ((details::e_sub == o0) && (details::e_sub == o1))
16870                   {
16871                      return expr_gen.node_allocator_->
16872                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
16873                   }
16874                   // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
16875                   else if ((details::e_mul == o0) && (details::e_mul == o1))
16876                   {
16877                      return expr_gen.node_allocator_->
16878                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
16879                   }
16880                   // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
16881                   else if ((details::e_mul == o0) && (details::e_div == o1))
16882                   {
16883                      return expr_gen.node_allocator_->
16884                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
16885                   }
16886                   // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
16887                   else if ((details::e_div == o0) && (details::e_mul == o1))
16888                   {
16889                      return expr_gen.node_allocator_->
16890                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
16891                   }
16892                   // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
16893                   else if ((details::e_div == o0) && (details::e_div == o1))
16894                   {
16895                      return expr_gen.node_allocator_->
16896                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
16897                   }
16898                }
16899 
16900                if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result))
16901                   return result;
16902                else if (!expr_gen.valid_operator(o0,f0))
16903                   return error_node();
16904                else if (!expr_gen.valid_operator(o1,f1))
16905                   return error_node();
16906                else
16907                   return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1);
16908             }
16909 
16910             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
16911             {
16912                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16913             }
16914          };
16915 
16916          struct synthesize_vococ_expression0
16917          {
16918             typedef typename vococ_t::type0 node_type;
16919             typedef typename vococ_t::sf3_type sf3_type;
16920             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16921                                                       const details::operator_type& operation,
16922                                                       expression_node_ptr (&branch)[2])
16923             {
16924                // (v o0 c0) o1 (c1)
16925                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
16926                const Type&  v = voc->v();
16927                const Type& c0 = voc->c();
16928                const Type& c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
16929                const details::operator_type o0 = voc->operation();
16930                const details::operator_type o1 = operation;
16931                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16932                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16933                details::free_node(*(expr_gen.node_allocator_),branch[0]);
16934                details::free_node(*(expr_gen.node_allocator_),branch[1]);
16935                expression_node_ptr result = error_node();
16936 
16937                if (expr_gen.strength_reduction_enabled())
16938                {
16939                   // (v + c0) + c1 --> (voc) v + (c0 + c1)
16940                   if ((details::e_add == o0) && (details::e_add == o1))
16941                   {
16942                      return expr_gen.node_allocator_->
16943                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1);
16944                   }
16945                   // (v + c0) - c1 --> (voc) v + (c0 - c1)
16946                   else if ((details::e_add == o0) && (details::e_sub == o1))
16947                   {
16948                      return expr_gen.node_allocator_->
16949                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1);
16950                   }
16951                   // (v - c0) + c1 --> (voc) v - (c0 + c1)
16952                   else if ((details::e_sub == o0) && (details::e_add == o1))
16953                   {
16954                      return expr_gen.node_allocator_->
16955                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0);
16956                   }
16957                   // (v - c0) - c1 --> (voc) v - (c0 + c1)
16958                   else if ((details::e_sub == o0) && (details::e_sub == o1))
16959                   {
16960                      return expr_gen.node_allocator_->
16961                                template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1);
16962                   }
16963                   // (v * c0) * c1 --> (voc) v * (c0 * c1)
16964                   else if ((details::e_mul == o0) && (details::e_mul == o1))
16965                   {
16966                      return expr_gen.node_allocator_->
16967                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1);
16968                   }
16969                   // (v * c0) / c1 --> (voc) v * (c0 / c1)
16970                   else if ((details::e_mul == o0) && (details::e_div == o1))
16971                   {
16972                      return expr_gen.node_allocator_->
16973                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1);
16974                   }
16975                   // (v / c0) * c1 --> (voc) v * (c1 / c0)
16976                   else if ((details::e_div == o0) && (details::e_mul == o1))
16977                   {
16978                      return expr_gen.node_allocator_->
16979                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0);
16980                   }
16981                   // (v / c0) / c1 --> (voc) v / (c0 * c1)
16982                   else if ((details::e_div == o0) && (details::e_div == o1))
16983                   {
16984                      return expr_gen.node_allocator_->
16985                                template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
16986                   }
16987                }
16988 
16989                if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
16990                   return result;
16991                else if (!expr_gen.valid_operator(o0,f0))
16992                   return error_node();
16993                else if (!expr_gen.valid_operator(o1,f1))
16994                   return error_node();
16995                else
16996                   return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1);
16997             }
16998 
16999             static inline std::string id(expression_generator<Type>& expr_gen,
17000                                          const details::operator_type o0, const details::operator_type o1)
17001             {
17002                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
17003             }
17004          };
17005 
17006          struct synthesize_vococ_expression1
17007          {
17008             typedef typename vococ_t::type0 node_type;
17009             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
17010             {
17011                // (v) o0 (c0 o1 c1) - Not possible.
17012                return error_node();
17013             }
17014          };
17015 
17016          struct synthesize_vovovov_expression0
17017          {
17018             typedef typename vovovov_t::type0 node_type;
17019             typedef typename vovovov_t::sf4_type sf4_type;
17020             typedef typename node_type::T0 T0;
17021             typedef typename node_type::T1 T1;
17022             typedef typename node_type::T2 T2;
17023             typedef typename node_type::T3 T3;
17024 
17025             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17026                                                       const details::operator_type& operation,
17027                                                       expression_node_ptr (&branch)[2])
17028             {
17029                // (v0 o0 v1) o1 (v2 o2 v3)
17030                const details::vov_base_node<Type>* vov0 = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
17031                const details::vov_base_node<Type>* vov1 = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
17032                const Type& v0 = vov0->v0();
17033                const Type& v1 = vov0->v1();
17034                const Type& v2 = vov1->v0();
17035                const Type& v3 = vov1->v1();
17036                const details::operator_type o0 = vov0->operation();
17037                const details::operator_type o1 = operation;
17038                const details::operator_type o2 = vov1->operation();
17039                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17040                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17041                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17042                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17043                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17044                expression_node_ptr result = error_node();
17045 
17046                if (expr_gen.strength_reduction_enabled())
17047                {
17048                   // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
17049                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17050                   {
17051                      const bool synthesis_result =
17052                         synthesize_sf4ext_expression::
17053                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result);
17054                      return (synthesis_result) ? result : error_node();
17055                   }
17056                   // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
17057                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
17058                   {
17059                      const bool synthesis_result =
17060                         synthesize_sf4ext_expression::
17061                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result);
17062                      return (synthesis_result) ? result : error_node();
17063                   }
17064                }
17065 
17066                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
17067                   return result;
17068                else if (!expr_gen.valid_operator(o0,f0))
17069                   return error_node();
17070                else if (!expr_gen.valid_operator(o1,f1))
17071                   return error_node();
17072                else if (!expr_gen.valid_operator(o2,f2))
17073                   return error_node();
17074                else
17075                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
17076             }
17077 
17078             static inline std::string id(expression_generator<Type>& expr_gen,
17079                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17080             {
17081                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17082             }
17083          };
17084          struct synthesize_vovovoc_expression0
17085          {
17086             typedef typename vovovoc_t::type0 node_type;
17087             typedef typename vovovoc_t::sf4_type sf4_type;
17088             typedef typename node_type::T0 T0;
17089             typedef typename node_type::T1 T1;
17090             typedef typename node_type::T2 T2;
17091             typedef typename node_type::T3 T3;
17092             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17093                                                       const details::operator_type& operation,
17094                                                       expression_node_ptr (&branch)[2])
17095             {
17096                // (v0 o0 v1) o1 (v2 o2 c)
17097                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
17098                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
17099                const Type& v0 = vov->v0();
17100                const Type& v1 = vov->v1();
17101                const Type& v2 = voc->v ();
17102                const Type   c = voc->c ();
17103                const details::operator_type o0 = vov->operation();
17104                const details::operator_type o1 = operation;
17105                const details::operator_type o2 = voc->operation();
17106                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17107                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17108                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17109                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17110                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17111                expression_node_ptr result = error_node();
17112                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
17113                   return result;
17114                else if (!expr_gen.valid_operator(o0,f0))
17115                   return error_node();
17116                else if (!expr_gen.valid_operator(o1,f1))
17117                   return error_node();
17118                else if (!expr_gen.valid_operator(o2,f2))
17119                   return error_node();
17120                else
17121                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
17122             }
17123 
17124             static inline std::string id(expression_generator<Type>& expr_gen,
17125                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17126             {
17127                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17128             }
17129          };
17130 
17131          struct synthesize_vovocov_expression0
17132          {
17133             typedef typename vovocov_t::type0 node_type;
17134             typedef typename vovocov_t::sf4_type sf4_type;
17135             typedef typename node_type::T0 T0;
17136             typedef typename node_type::T1 T1;
17137             typedef typename node_type::T2 T2;
17138             typedef typename node_type::T3 T3;
17139             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17140                                                       const details::operator_type& operation,
17141                                                       expression_node_ptr (&branch)[2])
17142             {
17143                // (v0 o0 v1) o1 (c o2 v2)
17144                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
17145                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
17146                const Type& v0 = vov->v0();
17147                const Type& v1 = vov->v1();
17148                const Type& v2 = cov->v ();
17149                const Type   c = cov->c ();
17150                const details::operator_type o0 = vov->operation();
17151                const details::operator_type o1 = operation;
17152                const details::operator_type o2 = cov->operation();
17153                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17154                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17155                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17156                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17157                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17158                expression_node_ptr result = error_node();
17159                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
17160                   return result;
17161                else if (!expr_gen.valid_operator(o0,f0))
17162                   return error_node();
17163                else if (!expr_gen.valid_operator(o1,f1))
17164                   return error_node();
17165                else if (!expr_gen.valid_operator(o2,f2))
17166                   return error_node();
17167                else
17168                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
17169             }
17170 
17171             static inline std::string id(expression_generator<Type>& expr_gen,
17172                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17173             {
17174                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17175             }
17176          };
17177 
17178          struct synthesize_vocovov_expression0
17179          {
17180             typedef typename vocovov_t::type0 node_type;
17181             typedef typename vocovov_t::sf4_type sf4_type;
17182             typedef typename node_type::T0 T0;
17183             typedef typename node_type::T1 T1;
17184             typedef typename node_type::T2 T2;
17185             typedef typename node_type::T3 T3;
17186             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17187                                                       const details::operator_type& operation,
17188                                                       expression_node_ptr (&branch)[2])
17189             {
17190                // (v0 o0 c) o1 (v1 o2 v2)
17191                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
17192                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
17193                const Type   c = voc->c ();
17194                const Type& v0 = voc->v ();
17195                const Type& v1 = vov->v0();
17196                const Type& v2 = vov->v1();
17197                const details::operator_type o0 = voc->operation();
17198                const details::operator_type o1 = operation;
17199                const details::operator_type o2 = vov->operation();
17200                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17201                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17202                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17203                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17204                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17205                expression_node_ptr result = error_node();
17206                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
17207                   return result;
17208                else if (!expr_gen.valid_operator(o0,f0))
17209                   return error_node();
17210                else if (!expr_gen.valid_operator(o1,f1))
17211                   return error_node();
17212                else if (!expr_gen.valid_operator(o2,f2))
17213                   return error_node();
17214                else
17215                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
17216             }
17217 
17218             static inline std::string id(expression_generator<Type>& expr_gen,
17219                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17220             {
17221                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17222             }
17223          };
17224 
17225          struct synthesize_covovov_expression0
17226          {
17227             typedef typename covovov_t::type0 node_type;
17228             typedef typename covovov_t::sf4_type sf4_type;
17229             typedef typename node_type::T0 T0;
17230             typedef typename node_type::T1 T1;
17231             typedef typename node_type::T2 T2;
17232             typedef typename node_type::T3 T3;
17233             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17234                                                       const details::operator_type& operation,
17235                                                       expression_node_ptr (&branch)[2])
17236             {
17237                // (c o0 v0) o1 (v1 o2 v2)
17238                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
17239                const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
17240                const Type   c = cov->c ();
17241                const Type& v0 = cov->v ();
17242                const Type& v1 = vov->v0();
17243                const Type& v2 = vov->v1();
17244                const details::operator_type o0 = cov->operation();
17245                const details::operator_type o1 = operation;
17246                const details::operator_type o2 = vov->operation();
17247                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17248                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17249                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17250                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17251                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17252                expression_node_ptr result = error_node();
17253                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
17254                   return result;
17255                else if (!expr_gen.valid_operator(o0,f0))
17256                   return error_node();
17257                else if (!expr_gen.valid_operator(o1,f1))
17258                   return error_node();
17259                else if (!expr_gen.valid_operator(o2,f2))
17260                   return error_node();
17261                else
17262                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
17263             }
17264 
17265             static inline std::string id(expression_generator<Type>& expr_gen,
17266                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17267             {
17268                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17269             }
17270          };
17271 
17272          struct synthesize_covocov_expression0
17273          {
17274             typedef typename covocov_t::type0 node_type;
17275             typedef typename covocov_t::sf4_type sf4_type;
17276             typedef typename node_type::T0 T0;
17277             typedef typename node_type::T1 T1;
17278             typedef typename node_type::T2 T2;
17279             typedef typename node_type::T3 T3;
17280             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17281                                                       const details::operator_type& operation,
17282                                                       expression_node_ptr (&branch)[2])
17283             {
17284                // (c0 o0 v0) o1 (c1 o2 v1)
17285                const details::cov_base_node<Type>* cov0 = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
17286                const details::cov_base_node<Type>* cov1 = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
17287                const Type  c0 = cov0->c();
17288                const Type& v0 = cov0->v();
17289                const Type  c1 = cov1->c();
17290                const Type& v1 = cov1->v();
17291                const details::operator_type o0 = cov0->operation();
17292                const details::operator_type o1 = operation;
17293                const details::operator_type o2 = cov1->operation();
17294                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17295                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17296                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17297                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17298                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17299                expression_node_ptr result = error_node();
17300 
17301                if (expr_gen.strength_reduction_enabled())
17302                {
17303                   // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
17304                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17305                   {
17306                      const bool synthesis_result =
17307                         synthesize_sf3ext_expression::
17308                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17309                      return (synthesis_result) ? result : error_node();
17310                   }
17311                   // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
17312                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17313                   {
17314                      const bool synthesis_result =
17315                         synthesize_sf3ext_expression::
17316                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17317                      return (synthesis_result) ? result : error_node();
17318                   }
17319                   // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
17320                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17321                   {
17322                      const bool synthesis_result =
17323                         synthesize_sf3ext_expression::
17324                            template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result);
17325                      return (synthesis_result) ? result : error_node();
17326                   }
17327                   // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
17328                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17329                   {
17330                      const bool synthesis_result =
17331                         synthesize_sf3ext_expression::
17332                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17333                      return (synthesis_result) ? result : error_node();
17334                   }
17335                   // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
17336                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17337                   {
17338                      const bool synthesis_result =
17339                         synthesize_sf3ext_expression::
17340                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17341                      return (synthesis_result) ? result : error_node();
17342                   }
17343                   // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
17344                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17345                   {
17346                      const bool synthesis_result =
17347                         synthesize_sf3ext_expression::
17348                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
17349                      return (synthesis_result) ? result : error_node();
17350                   }
17351                   // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
17352                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
17353                   {
17354                      const bool synthesis_result =
17355                         synthesize_sf3ext_expression::
17356                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
17357                      return (synthesis_result) ? result : error_node();
17358                   }
17359                   // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
17360                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17361                   {
17362                      const bool synthesis_result =
17363                         synthesize_sf3ext_expression::
17364                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
17365                      return (synthesis_result) ? result : error_node();
17366                   }
17367                   // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
17368                   else if (
17369                             (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17370                             ((details::e_add == o1) || (details::e_sub == o1))
17371                           )
17372                   {
17373                      std::string specfunc;
17374                      switch (o1)
17375                      {
17376                         case details::e_add : specfunc = "t*(t+t)"; break;
17377                         case details::e_sub : specfunc = "t*(t-t)"; break;
17378                         default             : return error_node();
17379                      }
17380 
17381                      const bool synthesis_result =
17382                         synthesize_sf3ext_expression::
17383                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17384                      return (synthesis_result) ? result : error_node();
17385                   }
17386                }
17387 
17388                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
17389                   return result;
17390                else if (!expr_gen.valid_operator(o0,f0))
17391                   return error_node();
17392                else if (!expr_gen.valid_operator(o1,f1))
17393                   return error_node();
17394                else if (!expr_gen.valid_operator(o2,f2))
17395                   return error_node();
17396                else
17397                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
17398             }
17399 
17400             static inline std::string id(expression_generator<Type>& expr_gen,
17401                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17402             {
17403                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17404             }
17405          };
17406 
17407          struct synthesize_vocovoc_expression0
17408          {
17409             typedef typename vocovoc_t::type0 node_type;
17410             typedef typename vocovoc_t::sf4_type sf4_type;
17411             typedef typename node_type::T0 T0;
17412             typedef typename node_type::T1 T1;
17413             typedef typename node_type::T2 T2;
17414             typedef typename node_type::T3 T3;
17415             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17416                                                       const details::operator_type& operation,
17417                                                       expression_node_ptr (&branch)[2])
17418             {
17419                // (v0 o0 c0) o1 (v1 o2 c1)
17420                const details::voc_base_node<Type>* voc0 = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
17421                const details::voc_base_node<Type>* voc1 = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
17422                const Type  c0 = voc0->c();
17423                const Type& v0 = voc0->v();
17424                const Type  c1 = voc1->c();
17425                const Type& v1 = voc1->v();
17426                const details::operator_type o0 = voc0->operation();
17427                const details::operator_type o1 = operation;
17428                const details::operator_type o2 = voc1->operation();
17429                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17430                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17431                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17432                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17433                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17434                expression_node_ptr result = error_node();
17435 
17436                if (expr_gen.strength_reduction_enabled())
17437                {
17438                   // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
17439                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17440                   {
17441                      const bool synthesis_result =
17442                         synthesize_sf3ext_expression::
17443                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17444                      return (synthesis_result) ? result : error_node();
17445                   }
17446                   // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
17447                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17448                   {
17449                      const bool synthesis_result =
17450                         synthesize_sf3ext_expression::
17451                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17452                      return (synthesis_result) ? result : error_node();
17453                   }
17454                   // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
17455                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17456                   {
17457                      const bool synthesis_result =
17458                         synthesize_sf3ext_expression::
17459                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
17460                      return (synthesis_result) ? result : error_node();
17461                   }
17462                   // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
17463                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17464                   {
17465                      const bool synthesis_result =
17466                         synthesize_sf3ext_expression::
17467                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17468                      return (synthesis_result) ? result : error_node();
17469                   }
17470                   // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
17471                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17472                   {
17473                      const bool synthesis_result =
17474                         synthesize_sf3ext_expression::
17475                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17476                      return (synthesis_result) ? result : error_node();
17477                   }
17478                   // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
17479                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17480                   {
17481                      const bool synthesis_result =
17482                         synthesize_sf3ext_expression::
17483                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
17484                      return (synthesis_result) ? result : error_node();
17485                   }
17486                   // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
17487                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17488                   {
17489                      const bool synthesis_result =
17490                         synthesize_sf3ext_expression::
17491                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
17492                      return (synthesis_result) ? result : error_node();
17493                   }
17494                   // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
17495                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17496                   {
17497                      const bool synthesis_result =
17498                         synthesize_sf3ext_expression::
17499                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
17500                      return (synthesis_result) ? result : error_node();
17501                   }
17502                   // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
17503                   else if (
17504                             (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17505                             ((details::e_add == o1) || (details::e_sub == o1))
17506                           )
17507                   {
17508                      std::string specfunc;
17509                      switch (o1)
17510                      {
17511                         case details::e_add : specfunc = "t*(t+t)"; break;
17512                         case details::e_sub : specfunc = "t*(t-t)"; break;
17513                         default             : return error_node();
17514                      }
17515 
17516                      const bool synthesis_result =
17517                         synthesize_sf3ext_expression::
17518                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17519                      return (synthesis_result) ? result : error_node();
17520                   }
17521                }
17522 
17523                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
17524                   return result;
17525                else if (!expr_gen.valid_operator(o0,f0))
17526                   return error_node();
17527                else if (!expr_gen.valid_operator(o1,f1))
17528                   return error_node();
17529                else if (!expr_gen.valid_operator(o2,f2))
17530                   return error_node();
17531                else
17532                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
17533             }
17534 
17535             static inline std::string id(expression_generator<Type>& expr_gen,
17536                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17537             {
17538                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17539             }
17540          };
17541 
17542          struct synthesize_covovoc_expression0
17543          {
17544             typedef typename covovoc_t::type0 node_type;
17545             typedef typename covovoc_t::sf4_type sf4_type;
17546             typedef typename node_type::T0 T0;
17547             typedef typename node_type::T1 T1;
17548             typedef typename node_type::T2 T2;
17549             typedef typename node_type::T3 T3;
17550             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17551                                                       const details::operator_type& operation,
17552                                                       expression_node_ptr (&branch)[2])
17553             {
17554                // (c0 o0 v0) o1 (v1 o2 c1)
17555                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
17556                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
17557                const Type  c0 = cov->c();
17558                const Type& v0 = cov->v();
17559                const Type  c1 = voc->c();
17560                const Type& v1 = voc->v();
17561                const details::operator_type o0 = cov->operation();
17562                const details::operator_type o1 = operation;
17563                const details::operator_type o2 = voc->operation();
17564                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17565                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17566                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17567                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17568                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17569                expression_node_ptr result = error_node();
17570 
17571                if (expr_gen.strength_reduction_enabled())
17572                {
17573                   // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
17574                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17575                   {
17576                      const bool synthesis_result =
17577                         synthesize_sf3ext_expression::
17578                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17579                      return (synthesis_result) ? result : error_node();
17580                   }
17581                   // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
17582                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17583                   {
17584                      const bool synthesis_result =
17585                         synthesize_sf3ext_expression::
17586                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17587                      return (synthesis_result) ? result : error_node();
17588                   }
17589                   // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
17590                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17591                   {
17592                      const bool synthesis_result =
17593                         synthesize_sf3ext_expression::
17594                            template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
17595                      return (synthesis_result) ? result : error_node();
17596                   }
17597                   // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
17598                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17599                   {
17600                      const bool synthesis_result =
17601                         synthesize_sf3ext_expression::
17602                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17603                      return (synthesis_result) ? result : error_node();
17604                   }
17605                   // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
17606                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17607                   {
17608                      const bool synthesis_result =
17609                         synthesize_sf3ext_expression::
17610                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17611                      return (synthesis_result) ? result : error_node();
17612                   }
17613                   // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
17614                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17615                   {
17616                      const bool synthesis_result =
17617                         synthesize_sf3ext_expression::
17618                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
17619                      return (synthesis_result) ? result : error_node();
17620                   }
17621                   // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
17622                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
17623                   {
17624                      const bool synthesis_result =
17625                         synthesize_sf3ext_expression::
17626                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
17627                      return (synthesis_result) ? result : error_node();
17628                   }
17629                   // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
17630                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17631                   {
17632                      const bool synthesis_result =
17633                         synthesize_sf3ext_expression::
17634                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
17635                      return (synthesis_result) ? result : error_node();
17636                   }
17637                   // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
17638                   else if (
17639                             (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17640                             ((details::e_add == o1) || (details::e_sub == o1))
17641                           )
17642                   {
17643                      std::string specfunc;
17644                      switch (o1)
17645                      {
17646                         case details::e_add : specfunc = "t*(t+t)"; break;
17647                         case details::e_sub : specfunc = "t*(t-t)"; break;
17648                         default             : return error_node();
17649                      }
17650 
17651                      const bool synthesis_result =
17652                         synthesize_sf3ext_expression::
17653                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17654                      return (synthesis_result) ? result : error_node();
17655                   }
17656                }
17657 
17658                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
17659                   return result;
17660                else if (!expr_gen.valid_operator(o0,f0))
17661                   return error_node();
17662                else if (!expr_gen.valid_operator(o1,f1))
17663                   return error_node();
17664                else if (!expr_gen.valid_operator(o2,f2))
17665                   return error_node();
17666                else
17667                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
17668             }
17669 
17670             static inline std::string id(expression_generator<Type>& expr_gen,
17671                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17672             {
17673                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17674             }
17675          };
17676 
17677          struct synthesize_vococov_expression0
17678          {
17679             typedef typename vococov_t::type0 node_type;
17680             typedef typename vococov_t::sf4_type sf4_type;
17681             typedef typename node_type::T0 T0;
17682             typedef typename node_type::T1 T1;
17683             typedef typename node_type::T2 T2;
17684             typedef typename node_type::T3 T3;
17685             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17686                                                       const details::operator_type& operation,
17687                                                       expression_node_ptr (&branch)[2])
17688             {
17689                // (v0 o0 c0) o1 (c1 o2 v1)
17690                const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
17691                const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
17692                const T  c0 = voc->c();
17693                const T& v0 = voc->v();
17694                const T  c1 = cov->c();
17695                const T& v1 = cov->v();
17696                const details::operator_type o0 = voc->operation();
17697                const details::operator_type o1 = operation;
17698                const details::operator_type o2 = cov->operation();
17699                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17700                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17701                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17702                details::free_node(*(expr_gen.node_allocator_),branch[0]);
17703                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17704                expression_node_ptr result = error_node();
17705 
17706                if (expr_gen.strength_reduction_enabled())
17707                {
17708                   // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
17709                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17710                   {
17711                      const bool synthesis_result =
17712                         synthesize_sf3ext_expression::
17713                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17714                      return (synthesis_result) ? result : error_node();
17715                   }
17716                   // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
17717                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17718                   {
17719                      const bool synthesis_result =
17720                         synthesize_sf3ext_expression::
17721                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17722                      return (synthesis_result) ? result : error_node();
17723                   }
17724                   // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
17725                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17726                   {
17727                      const bool synthesis_result =
17728                         synthesize_sf3ext_expression::
17729                            template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
17730                      return (synthesis_result) ? result : error_node();
17731                   }
17732                   // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
17733                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17734                   {
17735                      const bool synthesis_result =
17736                         synthesize_sf3ext_expression::
17737                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17738                      return (synthesis_result) ? result : error_node();
17739                   }
17740                   // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
17741                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17742                   {
17743                      const bool synthesis_result =
17744                         synthesize_sf3ext_expression::
17745                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17746                      return (synthesis_result) ? result : error_node();
17747                   }
17748                   // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
17749                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17750                   {
17751                      const bool synthesis_result =
17752                         synthesize_sf3ext_expression::
17753                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
17754                      return (synthesis_result) ? result : error_node();
17755                   }
17756                   // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
17757                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17758                   {
17759                      const bool synthesis_result =
17760                         synthesize_sf3ext_expression::
17761                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
17762                      return (synthesis_result) ? result : error_node();
17763                   }
17764                   // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
17765                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17766                   {
17767                      const bool synthesis_result =
17768                         synthesize_sf3ext_expression::
17769                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
17770                      return (synthesis_result) ? result : error_node();
17771                   }
17772                   // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
17773                   else if (
17774                             (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17775                             ((details::e_add == o1) || (details::e_sub == o1))
17776                           )
17777                   {
17778                      std::string specfunc;
17779                      switch (o1)
17780                      {
17781                         case details::e_add : specfunc = "t*(t+t)"; break;
17782                         case details::e_sub : specfunc = "t*(t-t)"; break;
17783                         default             : return error_node();
17784                      }
17785 
17786                      const bool synthesis_result =
17787                         synthesize_sf3ext_expression::
17788                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17789                      return (synthesis_result) ? result : error_node();
17790                   }
17791                }
17792 
17793                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
17794                   return result;
17795                else if (!expr_gen.valid_operator(o0,f0))
17796                   return error_node();
17797                else if (!expr_gen.valid_operator(o1,f1))
17798                   return error_node();
17799                else if (!expr_gen.valid_operator(o2,f2))
17800                   return error_node();
17801                else
17802                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
17803             }
17804 
17805             static inline std::string id(expression_generator<Type>& expr_gen,
17806                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17807             {
17808                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17809             }
17810          };
17811 
17812          struct synthesize_vovovov_expression1
17813          {
17814             typedef typename vovovov_t::type1 node_type;
17815             typedef typename vovovov_t::sf4_type sf4_type;
17816             typedef typename node_type::T0 T0;
17817             typedef typename node_type::T1 T1;
17818             typedef typename node_type::T2 T2;
17819             typedef typename node_type::T3 T3;
17820             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17821                                                       const details::operator_type& operation,
17822                                                       expression_node_ptr (&branch)[2])
17823             {
17824                // v0 o0 (v1 o1 (v2 o2 v3))
17825                typedef typename synthesize_vovov_expression1::node_type vovov_t;
17826                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
17827                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17828                const T& v1 = vovov->t0();
17829                const T& v2 = vovov->t1();
17830                const T& v3 = vovov->t2();
17831                const details::operator_type o0 = operation;
17832                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
17833                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
17834                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17835                binary_functor_t f1 = vovov->f0();
17836                binary_functor_t f2 = vovov->f1();
17837                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17838                expression_node_ptr result = error_node();
17839                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
17840                   return result;
17841                else if (!expr_gen.valid_operator(o0,f0))
17842                   return error_node();
17843                else
17844                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
17845             }
17846 
17847             static inline std::string id(expression_generator<Type>& expr_gen,
17848                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17849             {
17850                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17851             }
17852          };
17853 
17854          struct synthesize_vovovoc_expression1
17855          {
17856             typedef typename vovovoc_t::type1 node_type;
17857             typedef typename vovovoc_t::sf4_type sf4_type;
17858             typedef typename node_type::T0 T0;
17859             typedef typename node_type::T1 T1;
17860             typedef typename node_type::T2 T2;
17861             typedef typename node_type::T3 T3;
17862             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17863                                                       const details::operator_type& operation,
17864                                                       expression_node_ptr (&branch)[2])
17865             {
17866                // v0 o0 (v1 o1 (v2 o2 c))
17867                typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
17868                const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
17869                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17870                const T& v1 = vovoc->t0();
17871                const T& v2 = vovoc->t1();
17872                const T   c = vovoc->t2();
17873                const details::operator_type o0 = operation;
17874                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
17875                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
17876                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17877                binary_functor_t f1 = vovoc->f0();
17878                binary_functor_t f2 = vovoc->f1();
17879                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17880                expression_node_ptr result = error_node();
17881                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
17882                   return result;
17883                else if (!expr_gen.valid_operator(o0,f0))
17884                   return error_node();
17885                else
17886                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
17887             }
17888 
17889             static inline std::string id(expression_generator<Type>& expr_gen,
17890                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17891             {
17892                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17893             }
17894          };
17895 
17896          struct synthesize_vovocov_expression1
17897          {
17898             typedef typename vovocov_t::type1 node_type;
17899             typedef typename vovocov_t::sf4_type sf4_type;
17900             typedef typename node_type::T0 T0;
17901             typedef typename node_type::T1 T1;
17902             typedef typename node_type::T2 T2;
17903             typedef typename node_type::T3 T3;
17904             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17905                                                       const details::operator_type& operation,
17906                                                       expression_node_ptr (&branch)[2])
17907             {
17908                // v0 o0 (v1 o1 (c o2 v2))
17909                typedef typename synthesize_vocov_expression1::node_type vocov_t;
17910                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
17911                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17912                const T& v1 = vocov->t0();
17913                const T   c = vocov->t1();
17914                const T& v2 = vocov->t2();
17915                const details::operator_type o0 = operation;
17916                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
17917                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
17918                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17919                binary_functor_t f1 = vocov->f0();
17920                binary_functor_t f2 = vocov->f1();
17921                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17922                expression_node_ptr result = error_node();
17923                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
17924                   return result;
17925                if (!expr_gen.valid_operator(o0,f0))
17926                   return error_node();
17927                else
17928                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
17929             }
17930 
17931             static inline std::string id(expression_generator<Type>& expr_gen,
17932                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17933             {
17934                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17935             }
17936          };
17937 
17938          struct synthesize_vocovov_expression1
17939          {
17940             typedef typename vocovov_t::type1 node_type;
17941             typedef typename vocovov_t::sf4_type sf4_type;
17942             typedef typename node_type::T0 T0;
17943             typedef typename node_type::T1 T1;
17944             typedef typename node_type::T2 T2;
17945             typedef typename node_type::T3 T3;
17946             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17947                                                       const details::operator_type& operation,
17948                                                       expression_node_ptr (&branch)[2])
17949             {
17950                // v0 o0 (c o1 (v1 o2 v2))
17951                typedef typename synthesize_covov_expression1::node_type covov_t;
17952                const covov_t* covov = dynamic_cast<const covov_t*>(branch[1]);
17953                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17954                const T   c = covov->t0();
17955                const T& v1 = covov->t1();
17956                const T& v2 = covov->t2();
17957                const details::operator_type o0 = operation;
17958                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
17959                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
17960                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17961                binary_functor_t f1 = covov->f0();
17962                binary_functor_t f2 = covov->f1();
17963                details::free_node(*(expr_gen.node_allocator_),branch[1]);
17964                expression_node_ptr result = error_node();
17965                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
17966                   return result;
17967                else if (!expr_gen.valid_operator(o0,f0))
17968                   return error_node();
17969                else
17970                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
17971             }
17972 
17973             static inline std::string id(expression_generator<Type>& expr_gen,
17974                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17975             {
17976                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17977             }
17978          };
17979 
17980          struct synthesize_covovov_expression1
17981          {
17982             typedef typename covovov_t::type1 node_type;
17983             typedef typename covovov_t::sf4_type sf4_type;
17984             typedef typename node_type::T0 T0;
17985             typedef typename node_type::T1 T1;
17986             typedef typename node_type::T2 T2;
17987             typedef typename node_type::T3 T3;
17988             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17989                                                       const details::operator_type& operation,
17990                                                       expression_node_ptr (&branch)[2])
17991             {
17992                // c o0 (v0 o1 (v1 o2 v2))
17993                typedef typename synthesize_vovov_expression1::node_type vovov_t;
17994                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
17995                const T   c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
17996                const T& v0 = vovov->t0();
17997                const T& v1 = vovov->t1();
17998                const T& v2 = vovov->t2();
17999                const details::operator_type o0 = operation;
18000                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
18001                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
18002                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18003                binary_functor_t f1 = vovov->f0();
18004                binary_functor_t f2 = vovov->f1();
18005                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18006                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18007                expression_node_ptr result = error_node();
18008                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
18009                   return result;
18010                if (!expr_gen.valid_operator(o0,f0))
18011                   return error_node();
18012                else
18013                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
18014             }
18015 
18016             static inline std::string id(expression_generator<Type>& expr_gen,
18017                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18018             {
18019                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18020             }
18021          };
18022 
18023          struct synthesize_covocov_expression1
18024          {
18025             typedef typename covocov_t::type1 node_type;
18026             typedef typename covocov_t::sf4_type sf4_type;
18027             typedef typename node_type::T0 T0;
18028             typedef typename node_type::T1 T1;
18029             typedef typename node_type::T2 T2;
18030             typedef typename node_type::T3 T3;
18031             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18032                                                       const details::operator_type& operation,
18033                                                       expression_node_ptr (&branch)[2])
18034             {
18035                // c0 o0 (v0 o1 (c1 o2 v1))
18036                typedef typename synthesize_vocov_expression1::node_type vocov_t;
18037                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
18038                const T  c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18039                const T& v0 = vocov->t0();
18040                const T  c1 = vocov->t1();
18041                const T& v1 = vocov->t2();
18042                const details::operator_type o0 = operation;
18043                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
18044                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
18045                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18046                binary_functor_t f1 = vocov->f0();
18047                binary_functor_t f2 = vocov->f1();
18048                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18049                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18050                expression_node_ptr result = error_node();
18051                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
18052                   return result;
18053                else if (!expr_gen.valid_operator(o0,f0))
18054                   return error_node();
18055                else
18056                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
18057             }
18058 
18059             static inline std::string id(expression_generator<Type>& expr_gen,
18060                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18061             {
18062                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18063             }
18064          };
18065 
18066          struct synthesize_vocovoc_expression1
18067          {
18068             typedef typename vocovoc_t::type1 node_type;
18069             typedef typename vocovoc_t::sf4_type sf4_type;
18070             typedef typename node_type::T0 T0;
18071             typedef typename node_type::T1 T1;
18072             typedef typename node_type::T2 T2;
18073             typedef typename node_type::T3 T3;
18074             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18075                                                       const details::operator_type& operation,
18076                                                       expression_node_ptr (&branch)[2])
18077             {
18078                // v0 o0 (c0 o1 (v1 o2 c2))
18079                typedef typename synthesize_covoc_expression1::node_type covoc_t;
18080                const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[1]);
18081                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18082                const T  c0 = covoc->t0();
18083                const T& v1 = covoc->t1();
18084                const T  c1 = covoc->t2();
18085                const details::operator_type o0 = operation;
18086                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
18087                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
18088                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18089                binary_functor_t f1 = covoc->f0();
18090                binary_functor_t f2 = covoc->f1();
18091                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18092                expression_node_ptr result = error_node();
18093                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
18094                   return result;
18095                else if (!expr_gen.valid_operator(o0,f0))
18096                   return error_node();
18097                else
18098                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
18099             }
18100 
18101             static inline std::string id(expression_generator<Type>& expr_gen,
18102                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18103             {
18104                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18105             }
18106          };
18107 
18108          struct synthesize_covovoc_expression1
18109          {
18110             typedef typename covovoc_t::type1 node_type;
18111             typedef typename covovoc_t::sf4_type sf4_type;
18112             typedef typename node_type::T0 T0;
18113             typedef typename node_type::T1 T1;
18114             typedef typename node_type::T2 T2;
18115             typedef typename node_type::T3 T3;
18116             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18117                                                       const details::operator_type& operation,
18118                                                       expression_node_ptr (&branch)[2])
18119             {
18120                // c0 o0 (v0 o1 (v1 o2 c1))
18121                typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
18122                const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
18123                const T  c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18124                const T& v0 = vovoc->t0();
18125                const T& v1 = vovoc->t1();
18126                const T  c1 = vovoc->t2();
18127                const details::operator_type o0 = operation;
18128                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
18129                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
18130                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18131                binary_functor_t f1 = vovoc->f0();
18132                binary_functor_t f2 = vovoc->f1();
18133                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18134                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18135                expression_node_ptr result = error_node();
18136                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
18137                   return result;
18138                else if (!expr_gen.valid_operator(o0,f0))
18139                   return error_node();
18140                else
18141                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
18142             }
18143 
18144             static inline std::string id(expression_generator<Type>& expr_gen,
18145                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18146             {
18147                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18148             }
18149          };
18150 
18151          struct synthesize_vococov_expression1
18152          {
18153             typedef typename vococov_t::type1 node_type;
18154             typedef typename vococov_t::sf4_type sf4_type;
18155             typedef typename node_type::T0 T0;
18156             typedef typename node_type::T1 T1;
18157             typedef typename node_type::T2 T2;
18158             typedef typename node_type::T3 T3;
18159             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18160                                                       const details::operator_type& operation,
18161                                                       expression_node_ptr (&branch)[2])
18162             {
18163                // v0 o0 (c0 o1 (c1 o2 v1))
18164                typedef typename synthesize_cocov_expression1::node_type cocov_t;
18165                const cocov_t* cocov = dynamic_cast<const cocov_t*>(branch[1]);
18166                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18167                const T  c0 = cocov->t0();
18168                const T  c1 = cocov->t1();
18169                const T& v1 = cocov->t2();
18170                const details::operator_type o0 = operation;
18171                const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
18172                const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
18173                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18174                binary_functor_t f1 = cocov->f0();
18175                binary_functor_t f2 = cocov->f1();
18176                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18177                expression_node_ptr result = error_node();
18178                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
18179                   return result;
18180                else if (!expr_gen.valid_operator(o0,f0))
18181                   return error_node();
18182                else
18183                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
18184             }
18185 
18186             static inline std::string id(expression_generator<Type>& expr_gen,
18187                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18188             {
18189                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18190             }
18191          };
18192 
18193          struct synthesize_vovovov_expression2
18194          {
18195             typedef typename vovovov_t::type2 node_type;
18196             typedef typename vovovov_t::sf4_type sf4_type;
18197             typedef typename node_type::T0 T0;
18198             typedef typename node_type::T1 T1;
18199             typedef typename node_type::T2 T2;
18200             typedef typename node_type::T3 T3;
18201             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18202                                                       const details::operator_type& operation,
18203                                                       expression_node_ptr (&branch)[2])
18204             {
18205                // v0 o0 ((v1 o1 v2) o2 v3)
18206                typedef typename synthesize_vovov_expression0::node_type vovov_t;
18207                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
18208                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18209                const T& v1 = vovov->t0();
18210                const T& v2 = vovov->t1();
18211                const T& v3 = vovov->t2();
18212                const details::operator_type o0 = operation;
18213                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
18214                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
18215                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18216                binary_functor_t f1 = vovov->f0();
18217                binary_functor_t f2 = vovov->f1();
18218                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18219                expression_node_ptr result = error_node();
18220                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
18221                   return result;
18222                else if (!expr_gen.valid_operator(o0,f0))
18223                   return error_node();
18224                else
18225                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
18226             }
18227 
18228             static inline std::string id(expression_generator<Type>& expr_gen,
18229                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18230             {
18231                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18232             }
18233          };
18234 
18235          struct synthesize_vovovoc_expression2
18236          {
18237             typedef typename vovovoc_t::type2 node_type;
18238             typedef typename vovovoc_t::sf4_type sf4_type;
18239             typedef typename node_type::T0 T0;
18240             typedef typename node_type::T1 T1;
18241             typedef typename node_type::T2 T2;
18242             typedef typename node_type::T3 T3;
18243             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18244                                                       const details::operator_type& operation,
18245                                                       expression_node_ptr (&branch)[2])
18246             {
18247                // v0 o0 ((v1 o1 v2) o2 c)
18248                typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
18249                const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
18250                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18251                const T& v1 = vovoc->t0();
18252                const T& v2 = vovoc->t1();
18253                const T   c = vovoc->t2();
18254                const details::operator_type o0 = operation;
18255                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
18256                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
18257                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18258                binary_functor_t f1 = vovoc->f0();
18259                binary_functor_t f2 = vovoc->f1();
18260                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18261                expression_node_ptr result = error_node();
18262                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
18263                   return result;
18264                else if (!expr_gen.valid_operator(o0,f0))
18265                   return error_node();
18266                else
18267                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
18268             }
18269 
18270             static inline std::string id(expression_generator<Type>& expr_gen,
18271                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18272             {
18273                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18274             }
18275          };
18276 
18277          struct synthesize_vovocov_expression2
18278          {
18279             typedef typename vovocov_t::type2 node_type;
18280             typedef typename vovocov_t::sf4_type sf4_type;
18281             typedef typename node_type::T0 T0;
18282             typedef typename node_type::T1 T1;
18283             typedef typename node_type::T2 T2;
18284             typedef typename node_type::T3 T3;
18285             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18286                                                       const details::operator_type& operation,
18287                                                       expression_node_ptr (&branch)[2])
18288             {
18289                // v0 o0 ((v1 o1 c) o2 v2)
18290                typedef typename synthesize_vocov_expression0::node_type vocov_t;
18291                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
18292                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18293                const T& v1 = vocov->t0();
18294                const T   c = vocov->t1();
18295                const T& v2 = vocov->t2();
18296                const details::operator_type o0 = operation;
18297                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
18298                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
18299                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18300                binary_functor_t f1 = vocov->f0();
18301                binary_functor_t f2 = vocov->f1();
18302                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18303                expression_node_ptr result = error_node();
18304                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
18305                   return result;
18306                else if (!expr_gen.valid_operator(o0,f0))
18307                   return error_node();
18308                else
18309                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
18310             }
18311 
18312             static inline std::string id(expression_generator<Type>& expr_gen,
18313                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18314             {
18315                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18316             }
18317          };
18318 
18319          struct synthesize_vocovov_expression2
18320          {
18321             typedef typename vocovov_t::type2 node_type;
18322             typedef typename vocovov_t::sf4_type sf4_type;
18323             typedef typename node_type::T0 T0;
18324             typedef typename node_type::T1 T1;
18325             typedef typename node_type::T2 T2;
18326             typedef typename node_type::T3 T3;
18327             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18328                                                       const details::operator_type& operation,
18329                                                       expression_node_ptr (&branch)[2])
18330             {
18331                // v0 o0 ((c o1 v1) o2 v2)
18332                typedef typename synthesize_covov_expression0::node_type covov_t;
18333                const covov_t* covov = dynamic_cast<const covov_t*>(branch[1]);
18334                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18335                const T   c = covov->t0();
18336                const T& v1 = covov->t1();
18337                const T& v2 = covov->t2();
18338                const details::operator_type o0 = operation;
18339                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
18340                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
18341                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18342                binary_functor_t f1 = covov->f0();
18343                binary_functor_t f2 = covov->f1();
18344                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18345                expression_node_ptr result = error_node();
18346                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
18347                   return result;
18348                else if (!expr_gen.valid_operator(o0,f0))
18349                   return error_node();
18350                else
18351                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
18352             }
18353 
18354             static inline std::string id(expression_generator<Type>& expr_gen,
18355                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18356             {
18357                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18358             }
18359          };
18360 
18361          struct synthesize_covovov_expression2
18362          {
18363             typedef typename covovov_t::type2 node_type;
18364             typedef typename covovov_t::sf4_type sf4_type;
18365             typedef typename node_type::T0 T0;
18366             typedef typename node_type::T1 T1;
18367             typedef typename node_type::T2 T2;
18368             typedef typename node_type::T3 T3;
18369             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18370                                                       const details::operator_type& operation,
18371                                                       expression_node_ptr (&branch)[2])
18372             {
18373                // c o0 ((v1 o1 v2) o2 v3)
18374                typedef typename synthesize_vovov_expression0::node_type vovov_t;
18375                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
18376                const T   c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18377                const T& v0 = vovov->t0();
18378                const T& v1 = vovov->t1();
18379                const T& v2 = vovov->t2();
18380                const details::operator_type o0 = operation;
18381                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
18382                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
18383                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18384                binary_functor_t f1 = vovov->f0();
18385                binary_functor_t f2 = vovov->f1();
18386                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18387                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18388                expression_node_ptr result = error_node();
18389                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
18390                   return result;
18391                else if (!expr_gen.valid_operator(o0,f0))
18392                   return error_node();
18393                else
18394                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
18395             }
18396 
18397             static inline std::string id(expression_generator<Type>& expr_gen,
18398                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18399             {
18400                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18401             }
18402         };
18403 
18404          struct synthesize_covocov_expression2
18405          {
18406             typedef typename covocov_t::type2 node_type;
18407             typedef typename covocov_t::sf4_type sf4_type;
18408             typedef typename node_type::T0 T0;
18409             typedef typename node_type::T1 T1;
18410             typedef typename node_type::T2 T2;
18411             typedef typename node_type::T3 T3;
18412             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18413                                                       const details::operator_type& operation,
18414                                                       expression_node_ptr (&branch)[2])
18415             {
18416                // c0 o0 ((v0 o1 c1) o2 v1)
18417                typedef typename synthesize_vocov_expression0::node_type vocov_t;
18418                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
18419                const T  c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18420                const T& v0 = vocov->t0();
18421                const T  c1 = vocov->t1();
18422                const T& v1 = vocov->t2();
18423                const details::operator_type o0 = operation;
18424                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
18425                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
18426                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18427                binary_functor_t f1 = vocov->f0();
18428                binary_functor_t f2 = vocov->f1();
18429                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18430                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18431                expression_node_ptr result = error_node();
18432                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
18433                   return result;
18434                else if (!expr_gen.valid_operator(o0,f0))
18435                   return error_node();
18436                else
18437                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
18438             }
18439 
18440             static inline std::string id(expression_generator<Type>& expr_gen,
18441                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18442             {
18443                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18444             }
18445          };
18446 
18447          struct synthesize_vocovoc_expression2
18448          {
18449             typedef typename vocovoc_t::type2 node_type;
18450             typedef typename vocovoc_t::sf4_type sf4_type;
18451             typedef typename node_type::T0 T0;
18452             typedef typename node_type::T1 T1;
18453             typedef typename node_type::T2 T2;
18454             typedef typename node_type::T3 T3;
18455             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18456                                                       const details::operator_type& operation,
18457                                                       expression_node_ptr (&branch)[2])
18458             {
18459                // v0 o0 ((c0 o1 v1) o2 c1)
18460                typedef typename synthesize_covoc_expression0::node_type covoc_t;
18461                const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[1]);
18462                const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18463                const T  c0 = covoc->t0();
18464                const T& v1 = covoc->t1();
18465                const T  c1 = covoc->t2();
18466                const details::operator_type o0 = operation;
18467                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
18468                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
18469                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18470                binary_functor_t f1 = covoc->f0();
18471                binary_functor_t f2 = covoc->f1();
18472                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18473                expression_node_ptr result = error_node();
18474                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
18475                   return result;
18476                else if (!expr_gen.valid_operator(o0,f0))
18477                   return error_node();
18478                else
18479                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
18480             }
18481 
18482             static inline std::string id(expression_generator<Type>& expr_gen,
18483                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18484             {
18485                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18486             }
18487          };
18488 
18489          struct synthesize_covovoc_expression2
18490          {
18491             typedef typename covovoc_t::type2 node_type;
18492             typedef typename covovoc_t::sf4_type sf4_type;
18493             typedef typename node_type::T0 T0;
18494             typedef typename node_type::T1 T1;
18495             typedef typename node_type::T2 T2;
18496             typedef typename node_type::T3 T3;
18497             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18498                                                       const details::operator_type& operation,
18499                                                       expression_node_ptr (&branch)[2])
18500             {
18501                // c0 o0 ((v0 o1 v1) o2 c1)
18502                typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
18503                const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
18504                const T  c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18505                const T& v0 = vovoc->t0();
18506                const T& v1 = vovoc->t1();
18507                const T  c1 = vovoc->t2();
18508                const details::operator_type o0 = operation;
18509                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
18510                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
18511                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18512                binary_functor_t f1 = vovoc->f0();
18513                binary_functor_t f2 = vovoc->f1();
18514                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18515                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18516                expression_node_ptr result = error_node();
18517                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
18518                   return result;
18519                else if (!expr_gen.valid_operator(o0,f0))
18520                   return error_node();
18521                else
18522                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
18523             }
18524 
18525             static inline std::string id(expression_generator<Type>& expr_gen,
18526                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18527             {
18528                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18529             }
18530          };
18531 
18532          struct synthesize_vococov_expression2
18533          {
18534             typedef typename vococov_t::type2 node_type;
18535             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
18536             {
18537                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
18538                return error_node();
18539             }
18540 
18541             static inline std::string id(expression_generator<Type>&,
18542                                          const details::operator_type, const details::operator_type, const details::operator_type)
18543             {
18544                return "INVALID";
18545             }
18546          };
18547 
18548          struct synthesize_vovovov_expression3
18549          {
18550             typedef typename vovovov_t::type3 node_type;
18551             typedef typename vovovov_t::sf4_type sf4_type;
18552             typedef typename node_type::T0 T0;
18553             typedef typename node_type::T1 T1;
18554             typedef typename node_type::T2 T2;
18555             typedef typename node_type::T3 T3;
18556             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18557                                                       const details::operator_type& operation,
18558                                                       expression_node_ptr (&branch)[2])
18559             {
18560                // ((v0 o0 v1) o1 v2) o2 v3
18561                typedef typename synthesize_vovov_expression0::node_type vovov_t;
18562                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18563                const T& v0 = vovov->t0();
18564                const T& v1 = vovov->t1();
18565                const T& v2 = vovov->t2();
18566                const T& v3 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18567                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18568                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18569                const details::operator_type o2 = operation;
18570                binary_functor_t f0 = vovov->f0();
18571                binary_functor_t f1 = vovov->f1();
18572                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18573                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18574                expression_node_ptr result = error_node();
18575                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
18576                   return result;
18577                else if (!expr_gen.valid_operator(o2,f2))
18578                   return error_node();
18579                else
18580                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
18581             }
18582 
18583             static inline std::string id(expression_generator<Type>& expr_gen,
18584                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18585             {
18586                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18587             }
18588          };
18589 
18590          struct synthesize_vovovoc_expression3
18591          {
18592             typedef typename vovovoc_t::type3 node_type;
18593             typedef typename vovovoc_t::sf4_type sf4_type;
18594             typedef typename node_type::T0 T0;
18595             typedef typename node_type::T1 T1;
18596             typedef typename node_type::T2 T2;
18597             typedef typename node_type::T3 T3;
18598             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18599                                                       const details::operator_type& operation,
18600                                                       expression_node_ptr (&branch)[2])
18601             {
18602                // ((v0 o0 v1) o1 v2) o2 c
18603                typedef typename synthesize_vovov_expression0::node_type vovov_t;
18604                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18605                const T& v0 = vovov->t0();
18606                const T& v1 = vovov->t1();
18607                const T& v2 = vovov->t2();
18608                const T   c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18609                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18610                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18611                const details::operator_type o2 = operation;
18612                binary_functor_t f0 = vovov->f0();
18613                binary_functor_t f1 = vovov->f1();
18614                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18615                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18616                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18617                expression_node_ptr result = error_node();
18618                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
18619                   return result;
18620                else if (!expr_gen.valid_operator(o2,f2))
18621                   return error_node();
18622                else
18623                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
18624             }
18625 
18626             static inline std::string id(expression_generator<Type>& expr_gen,
18627                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18628             {
18629                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18630             }
18631          };
18632 
18633          struct synthesize_vovocov_expression3
18634          {
18635             typedef typename vovocov_t::type3 node_type;
18636             typedef typename vovocov_t::sf4_type sf4_type;
18637             typedef typename node_type::T0 T0;
18638             typedef typename node_type::T1 T1;
18639             typedef typename node_type::T2 T2;
18640             typedef typename node_type::T3 T3;
18641             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18642                                                       const details::operator_type& operation,
18643                                                       expression_node_ptr (&branch)[2])
18644             {
18645                // ((v0 o0 v1) o1 c) o2 v2
18646                typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
18647                const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[0]);
18648                const T& v0 = vovoc->t0();
18649                const T& v1 = vovoc->t1();
18650                const T   c = vovoc->t2();
18651                const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18652                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
18653                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
18654                const details::operator_type o2 = operation;
18655                binary_functor_t f0 = vovoc->f0();
18656                binary_functor_t f1 = vovoc->f1();
18657                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18658                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18659                expression_node_ptr result = error_node();
18660                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
18661                   return result;
18662                else if (!expr_gen.valid_operator(o2,f2))
18663                   return error_node();
18664                else
18665                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
18666             }
18667 
18668             static inline std::string id(expression_generator<Type>& expr_gen,
18669                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18670             {
18671                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18672             }
18673          };
18674 
18675          struct synthesize_vocovov_expression3
18676          {
18677             typedef typename vocovov_t::type3 node_type;
18678             typedef typename vocovov_t::sf4_type sf4_type;
18679             typedef typename node_type::T0 T0;
18680             typedef typename node_type::T1 T1;
18681             typedef typename node_type::T2 T2;
18682             typedef typename node_type::T3 T3;
18683             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18684                                                       const details::operator_type& operation,
18685                                                       expression_node_ptr (&branch)[2])
18686             {
18687                // ((v0 o0 c) o1 v1) o2 v2
18688                typedef typename synthesize_vocov_expression0::node_type vocov_t;
18689                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
18690                const T& v0 = vocov->t0();
18691                const T   c = vocov->t1();
18692                const T& v1 = vocov->t2();
18693                const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18694                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
18695                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
18696                const details::operator_type o2 = operation;
18697                binary_functor_t f0 = vocov->f0();
18698                binary_functor_t f1 = vocov->f1();
18699                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18700                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18701                expression_node_ptr result = error_node();
18702                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
18703                   return result;
18704                else if (!expr_gen.valid_operator(o2,f2))
18705                   return error_node();
18706                else
18707                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
18708             }
18709 
18710             static inline std::string id(expression_generator<Type>& expr_gen,
18711                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18712             {
18713                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18714             }
18715          };
18716 
18717          struct synthesize_covovov_expression3
18718          {
18719             typedef typename covovov_t::type3 node_type;
18720             typedef typename covovov_t::sf4_type sf4_type;
18721             typedef typename node_type::T0 T0;
18722             typedef typename node_type::T1 T1;
18723             typedef typename node_type::T2 T2;
18724             typedef typename node_type::T3 T3;
18725             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18726                                                       const details::operator_type& operation,
18727                                                       expression_node_ptr (&branch)[2])
18728             {
18729                // ((c o0 v0) o1 v1) o2 v2
18730                typedef typename synthesize_covov_expression0::node_type covov_t;
18731                const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
18732                const T   c = covov->t0();
18733                const T& v0 = covov->t1();
18734                const T& v1 = covov->t2();
18735                const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18736                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
18737                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
18738                const details::operator_type o2 = operation;
18739                binary_functor_t f0 = covov->f0();
18740                binary_functor_t f1 = covov->f1();
18741                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18742                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18743                expression_node_ptr result = error_node();
18744                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
18745                   return result;
18746                else if (!expr_gen.valid_operator(o2,f2))
18747                   return error_node();
18748                else
18749                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
18750             }
18751 
18752             static inline std::string id(expression_generator<Type>& expr_gen,
18753                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18754             {
18755                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18756             }
18757          };
18758 
18759          struct synthesize_covocov_expression3
18760          {
18761             typedef typename covocov_t::type3 node_type;
18762             typedef typename covocov_t::sf4_type sf4_type;
18763             typedef typename node_type::T0 T0;
18764             typedef typename node_type::T1 T1;
18765             typedef typename node_type::T2 T2;
18766             typedef typename node_type::T3 T3;
18767             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18768                                                       const details::operator_type& operation,
18769                                                       expression_node_ptr (&branch)[2])
18770             {
18771                // ((c0 o0 v0) o1 c1) o2 v1
18772                typedef typename synthesize_covoc_expression0::node_type covoc_t;
18773                const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[0]);
18774                const T  c0 = covoc->t0();
18775                const T& v0 = covoc->t1();
18776                const T  c1 = covoc->t2();
18777                const T& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18778                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
18779                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
18780                const details::operator_type o2 = operation;
18781                binary_functor_t f0 = covoc->f0();
18782                binary_functor_t f1 = covoc->f1();
18783                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18784                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18785                expression_node_ptr result = error_node();
18786                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
18787                   return result;
18788                else if (!expr_gen.valid_operator(o2,f2))
18789                   return error_node();
18790                else
18791                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
18792             }
18793 
18794             static inline std::string id(expression_generator<Type>& expr_gen,
18795                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18796             {
18797                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18798             }
18799          };
18800 
18801          struct synthesize_vocovoc_expression3
18802          {
18803             typedef typename vocovoc_t::type3 node_type;
18804             typedef typename vocovoc_t::sf4_type sf4_type;
18805             typedef typename node_type::T0 T0;
18806             typedef typename node_type::T1 T1;
18807             typedef typename node_type::T2 T2;
18808             typedef typename node_type::T3 T3;
18809             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18810                                                       const details::operator_type& operation,
18811                                                       expression_node_ptr (&branch)[2])
18812             {
18813                // ((v0 o0 c0) o1 v1) o2 c1
18814                typedef typename synthesize_vocov_expression0::node_type vocov_t;
18815                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
18816                const T& v0 = vocov->t0();
18817                const T  c0 = vocov->t1();
18818                const T& v1 = vocov->t2();
18819                const T  c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18820                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
18821                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
18822                const details::operator_type o2 = operation;
18823                binary_functor_t f0 = vocov->f0();
18824                binary_functor_t f1 = vocov->f1();
18825                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18826                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18827                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18828                expression_node_ptr result = error_node();
18829                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
18830                   return result;
18831                else if (!expr_gen.valid_operator(o2,f2))
18832                   return error_node();
18833                else
18834                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
18835             }
18836 
18837             static inline std::string id(expression_generator<Type>& expr_gen,
18838                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18839             {
18840                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18841             }
18842          };
18843 
18844          struct synthesize_covovoc_expression3
18845          {
18846             typedef typename covovoc_t::type3 node_type;
18847             typedef typename covovoc_t::sf4_type sf4_type;
18848             typedef typename node_type::T0 T0;
18849             typedef typename node_type::T1 T1;
18850             typedef typename node_type::T2 T2;
18851             typedef typename node_type::T3 T3;
18852             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18853                                                       const details::operator_type& operation,
18854                                                       expression_node_ptr (&branch)[2])
18855             {
18856                // ((c0 o0 v0) o1 v1) o2 c1
18857                typedef typename synthesize_covov_expression0::node_type covov_t;
18858                const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
18859                const T  c0 = covov->t0();
18860                const T& v0 = covov->t1();
18861                const T& v1 = covov->t2();
18862                const T  c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18863                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
18864                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
18865                const details::operator_type o2 = operation;
18866                binary_functor_t f0 = covov->f0();
18867                binary_functor_t f1 = covov->f1();
18868                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18869                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18870                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18871                expression_node_ptr result = error_node();
18872                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
18873                   return result;
18874                else if (!expr_gen.valid_operator(o2,f2))
18875                   return error_node();
18876                else
18877                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
18878             }
18879 
18880             static inline std::string id(expression_generator<Type>& expr_gen,
18881                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18882             {
18883                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18884             }
18885          };
18886 
18887          struct synthesize_vococov_expression3
18888          {
18889             typedef typename vococov_t::type3 node_type;
18890             typedef typename vococov_t::sf4_type sf4_type;
18891             typedef typename node_type::T0 T0;
18892             typedef typename node_type::T1 T1;
18893             typedef typename node_type::T2 T2;
18894             typedef typename node_type::T3 T3;
18895             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18896                                                       const details::operator_type& operation,
18897                                                       expression_node_ptr (&branch)[2])
18898             {
18899                // ((v0 o0 c0) o1 c1) o2 v1
18900                typedef typename synthesize_vococ_expression0::node_type vococ_t;
18901                const vococ_t* vococ = dynamic_cast<const vococ_t*>(branch[0]);
18902                const T& v0 = vococ->t0();
18903                const T  c0 = vococ->t1();
18904                const T  c1 = vococ->t2();
18905                const T& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18906                const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
18907                const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
18908                const details::operator_type o2 = operation;
18909                binary_functor_t f0 = vococ->f0();
18910                binary_functor_t f1 = vococ->f1();
18911                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18912                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18913                expression_node_ptr result = error_node();
18914                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
18915                   return result;
18916                else if (!expr_gen.valid_operator(o2,f2))
18917                   return error_node();
18918                else
18919                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
18920             }
18921 
18922             static inline std::string id(expression_generator<Type>& expr_gen,
18923                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18924             {
18925                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18926             }
18927          };
18928 
18929          struct synthesize_vovovov_expression4
18930          {
18931             typedef typename vovovov_t::type4 node_type;
18932             typedef typename vovovov_t::sf4_type sf4_type;
18933             typedef typename node_type::T0 T0;
18934             typedef typename node_type::T1 T1;
18935             typedef typename node_type::T2 T2;
18936             typedef typename node_type::T3 T3;
18937             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18938                                                       const details::operator_type& operation,
18939                                                       expression_node_ptr (&branch)[2])
18940             {
18941                // (v0 o0 (v1 o1 v2)) o2 v3
18942                typedef typename synthesize_vovov_expression1::node_type vovov_t;
18943                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18944                const T& v0 = vovov->t0();
18945                const T& v1 = vovov->t1();
18946                const T& v2 = vovov->t2();
18947                const T& v3 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18948                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18949                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18950                const details::operator_type o2 = operation;
18951                binary_functor_t f0 = vovov->f0();
18952                binary_functor_t f1 = vovov->f1();
18953                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18954                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18955                expression_node_ptr result = error_node();
18956                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
18957                   return result;
18958                else if (!expr_gen.valid_operator(o2,f2))
18959                   return error_node();
18960                else
18961                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
18962             }
18963 
18964             static inline std::string id(expression_generator<Type>& expr_gen,
18965                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18966             {
18967                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18968             }
18969          };
18970 
18971          struct synthesize_vovovoc_expression4
18972          {
18973             typedef typename vovovoc_t::type4 node_type;
18974             typedef typename vovovoc_t::sf4_type sf4_type;
18975             typedef typename node_type::T0 T0;
18976             typedef typename node_type::T1 T1;
18977             typedef typename node_type::T2 T2;
18978             typedef typename node_type::T3 T3;
18979             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18980                                                       const details::operator_type& operation,
18981                                                       expression_node_ptr (&branch)[2])
18982             {
18983                // ((v0 o0 (v1 o1 v2)) o2 c)
18984                typedef typename synthesize_vovov_expression1::node_type vovov_t;
18985                const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18986                const T& v0 = vovov->t0();
18987                const T& v1 = vovov->t1();
18988                const T& v2 = vovov->t2();
18989                const T   c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18990                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18991                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18992                const details::operator_type o2 = operation;
18993                binary_functor_t f0 = vovov->f0();
18994                binary_functor_t f1 = vovov->f1();
18995                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18996                details::free_node(*(expr_gen.node_allocator_),branch[0]);
18997                details::free_node(*(expr_gen.node_allocator_),branch[1]);
18998                expression_node_ptr result = error_node();
18999                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
19000                   return result;
19001                else if (!expr_gen.valid_operator(o2,f2))
19002                   return error_node();
19003                else
19004                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
19005             }
19006 
19007             static inline std::string id(expression_generator<Type>& expr_gen,
19008                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19009             {
19010                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19011             }
19012          };
19013 
19014          struct synthesize_vovocov_expression4
19015          {
19016             typedef typename vovocov_t::type4 node_type;
19017             typedef typename vovocov_t::sf4_type sf4_type;
19018             typedef typename node_type::T0 T0;
19019             typedef typename node_type::T1 T1;
19020             typedef typename node_type::T2 T2;
19021             typedef typename node_type::T3 T3;
19022             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19023                                                       const details::operator_type& operation,
19024                                                       expression_node_ptr (&branch)[2])
19025             {
19026                // ((v0 o0 (v1 o1 c)) o2 v1)
19027                typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
19028                const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[0]);
19029                const T& v0 = vovoc->t0();
19030                const T& v1 = vovoc->t1();
19031                const T   c = vovoc->t2();
19032                const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19033                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
19034                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
19035                const details::operator_type o2 = operation;
19036                binary_functor_t f0 = vovoc->f0();
19037                binary_functor_t f1 = vovoc->f1();
19038                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19039                details::free_node(*(expr_gen.node_allocator_),branch[0]);
19040                expression_node_ptr result = error_node();
19041                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
19042                   return result;
19043                else if (!expr_gen.valid_operator(o2,f2))
19044                   return error_node();
19045                else
19046                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
19047             }
19048 
19049             static inline std::string id(expression_generator<Type>& expr_gen,
19050                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19051             {
19052                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19053             }
19054          };
19055 
19056          struct synthesize_vocovov_expression4
19057          {
19058             typedef typename vocovov_t::type4 node_type;
19059             typedef typename vocovov_t::sf4_type sf4_type;
19060             typedef typename node_type::T0 T0;
19061             typedef typename node_type::T1 T1;
19062             typedef typename node_type::T2 T2;
19063             typedef typename node_type::T3 T3;
19064             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19065                                                       const details::operator_type& operation,
19066                                                       expression_node_ptr (&branch)[2])
19067             {
19068                // ((v0 o0 (c o1 v1)) o2 v2)
19069                typedef typename synthesize_vocov_expression1::node_type vocov_t;
19070                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
19071                const T& v0 = vocov->t0();
19072                const T   c = vocov->t1();
19073                const T& v1 = vocov->t2();
19074                const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19075                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
19076                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
19077                const details::operator_type o2 = operation;
19078                binary_functor_t f0 = vocov->f0();
19079                binary_functor_t f1 = vocov->f1();
19080                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19081                details::free_node(*(expr_gen.node_allocator_),branch[0]);
19082                expression_node_ptr result = error_node();
19083                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
19084                   return result;
19085                else if (!expr_gen.valid_operator(o2,f2))
19086                   return error_node();
19087                else
19088                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
19089             }
19090 
19091             static inline std::string id(expression_generator<Type>& expr_gen,
19092                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19093             {
19094                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19095             }
19096          };
19097 
19098          struct synthesize_covovov_expression4
19099          {
19100             typedef typename covovov_t::type4 node_type;
19101             typedef typename covovov_t::sf4_type sf4_type;
19102             typedef typename node_type::T0 T0;
19103             typedef typename node_type::T1 T1;
19104             typedef typename node_type::T2 T2;
19105             typedef typename node_type::T3 T3;
19106             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19107                                                       const details::operator_type& operation,
19108                                                       expression_node_ptr (&branch)[2])
19109             {
19110                // ((c o0 (v0 o1 v1)) o2 v2)
19111                typedef typename synthesize_covov_expression1::node_type covov_t;
19112                const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
19113                const T   c = covov->t0();
19114                const T& v0 = covov->t1();
19115                const T& v1 = covov->t2();
19116                const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19117                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
19118                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
19119                const details::operator_type o2 = operation;
19120                binary_functor_t f0 = covov->f0();
19121                binary_functor_t f1 = covov->f1();
19122                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19123                details::free_node(*(expr_gen.node_allocator_),branch[0]);
19124                expression_node_ptr result = error_node();
19125                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
19126                   return result;
19127                else if (!expr_gen.valid_operator(o2,f2))
19128                   return error_node();
19129                else
19130                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
19131             }
19132 
19133             static inline std::string id(expression_generator<Type>& expr_gen,
19134                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19135             {
19136                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19137             }
19138          };
19139 
19140          struct synthesize_covocov_expression4
19141          {
19142             typedef typename covocov_t::type4 node_type;
19143             typedef typename covocov_t::sf4_type sf4_type;
19144             typedef typename node_type::T0 T0;
19145             typedef typename node_type::T1 T1;
19146             typedef typename node_type::T2 T2;
19147             typedef typename node_type::T3 T3;
19148             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19149                                                       const details::operator_type& operation,
19150                                                       expression_node_ptr (&branch)[2])
19151             {
19152                // ((c0 o0 (v0 o1 c1)) o2 v1)
19153                typedef typename synthesize_covoc_expression1::node_type covoc_t;
19154                const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[0]);
19155                const T  c0 = covoc->t0();
19156                const T& v0 = covoc->t1();
19157                const T  c1 = covoc->t2();
19158                const T& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19159                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
19160                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
19161                const details::operator_type o2 = operation;
19162                binary_functor_t f0 = covoc->f0();
19163                binary_functor_t f1 = covoc->f1();
19164                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19165                details::free_node(*(expr_gen.node_allocator_),branch[0]);
19166                expression_node_ptr result = error_node();
19167                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
19168                   return result;
19169                else if (!expr_gen.valid_operator(o2,f2))
19170                   return error_node();
19171                else
19172                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
19173             }
19174 
19175             static inline std::string id(expression_generator<Type>& expr_gen,
19176                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19177             {
19178                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19179             }
19180          };
19181 
19182          struct synthesize_vocovoc_expression4
19183          {
19184             typedef typename vocovoc_t::type4 node_type;
19185             typedef typename vocovoc_t::sf4_type sf4_type;
19186             typedef typename node_type::T0 T0;
19187             typedef typename node_type::T1 T1;
19188             typedef typename node_type::T2 T2;
19189             typedef typename node_type::T3 T3;
19190             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19191                                                       const details::operator_type& operation,
19192                                                       expression_node_ptr (&branch)[2])
19193             {
19194                // ((v0 o0 (c0 o1 v1)) o2 c1)
19195                typedef typename synthesize_vocov_expression1::node_type vocov_t;
19196                const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
19197                const T& v0 = vocov->t0();
19198                const T  c0 = vocov->t1();
19199                const T& v1 = vocov->t2();
19200                const T  c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
19201                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
19202                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
19203                const details::operator_type o2 = operation;
19204                binary_functor_t f0 = vocov->f0();
19205                binary_functor_t f1 = vocov->f1();
19206                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19207                details::free_node(*(expr_gen.node_allocator_),branch[0]);
19208                details::free_node(*(expr_gen.node_allocator_),branch[1]);
19209                expression_node_ptr result = error_node();
19210                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
19211                   return result;
19212                else if (!expr_gen.valid_operator(o2,f2))
19213                   return error_node();
19214                else
19215                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
19216             }
19217 
19218             static inline std::string id(expression_generator<Type>& expr_gen,
19219                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19220             {
19221                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19222             }
19223          };
19224 
19225          struct synthesize_covovoc_expression4
19226          {
19227             typedef typename covovoc_t::type4 node_type;
19228             typedef typename covovoc_t::sf4_type sf4_type;
19229             typedef typename node_type::T0 T0;
19230             typedef typename node_type::T1 T1;
19231             typedef typename node_type::T2 T2;
19232             typedef typename node_type::T3 T3;
19233             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19234                                                       const details::operator_type& operation,
19235                                                       expression_node_ptr (&branch)[2])
19236             {
19237                // ((c0 o0 (v0 o1 v1)) o2 c1)
19238                typedef typename synthesize_covov_expression1::node_type covov_t;
19239                const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
19240                const T  c0 = covov->t0();
19241                const T& v0 = covov->t1();
19242                const T& v1 = covov->t2();
19243                const T  c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
19244                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
19245                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
19246                const details::operator_type o2 = operation;
19247                binary_functor_t f0 = covov->f0();
19248                binary_functor_t f1 = covov->f1();
19249                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19250                details::free_node(*(expr_gen.node_allocator_),branch[0]);
19251                details::free_node(*(expr_gen.node_allocator_),branch[1]);
19252                expression_node_ptr result = error_node();
19253                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
19254                   return result;
19255                else if (!expr_gen.valid_operator(o2,f2))
19256                   return error_node();
19257                else
19258                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
19259             }
19260 
19261             static inline std::string id(expression_generator<Type>& expr_gen,
19262                                          const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19263             {
19264                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19265             }
19266          };
19267 
19268          struct synthesize_vococov_expression4
19269          {
19270             typedef typename vococov_t::type4 node_type;
19271             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
19272             {
19273                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
19274                return error_node();
19275             }
19276 
19277             static inline std::string id(expression_generator<Type>&,
19278                                          const details::operator_type, const details::operator_type, const details::operator_type)
19279             {
19280                return "INVALID";
19281             }
19282          };
19283 
19284          inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
19285          {
19286             // Definition: uv o uv
19287             details::operator_type o0 = dynamic_cast<details::uv_base_node<Type>*>(branch[0])->operation();
19288             details::operator_type o1 = dynamic_cast<details::uv_base_node<Type>*>(branch[1])->operation();
19289             const Type& v0 = dynamic_cast<details::uv_base_node<Type>*>(branch[0])->v();
19290             const Type& v1 = dynamic_cast<details::uv_base_node<Type>*>(branch[1])->v();
19291             unary_functor_t u0 = reinterpret_cast<unary_functor_t>(0);
19292             unary_functor_t u1 = reinterpret_cast<unary_functor_t>(0);
19293             binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
19294 
19295             if (!valid_operator(o0,u0))
19296                return error_node();
19297             else if (!valid_operator(o1,u1))
19298                return error_node();
19299             else if (!valid_operator(operation,f))
19300                return error_node();
19301 
19302             expression_node_ptr result = error_node();
19303             result = node_allocator_->allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f);
19304 
19305             details::free_all_nodes(*node_allocator_,branch);
19306             return result;
19307          }
19308 
19309          #undef basic_opr_switch_statements
19310          #undef extended_opr_switch_statements
19311          #undef unary_opr_switch_statements
19312 
19313          #ifndef exprtk_disable_string_capabilities
19314 
19315          #define string_opr_switch_statements          \
19316          case_stmt(details::  e_lt ,details::   lt_op) \
19317          case_stmt(details:: e_lte ,details::  lte_op) \
19318          case_stmt(details::  e_gt ,details::   gt_op) \
19319          case_stmt(details:: e_gte ,details::  gte_op) \
19320          case_stmt(details::  e_eq ,details::   eq_op) \
19321          case_stmt(details::  e_ne ,details::   ne_op) \
19322          case_stmt(details::e_in   ,details::   in_op) \
19323          case_stmt(details::e_like ,details:: like_op) \
19324          case_stmt(details::e_ilike,details::ilike_op) \
19325 
19326          template <typename T0, typename T1>
19327          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0)
19328          {
19329             switch (opr)
19330             {
19331                #define case_stmt(op0,op1)                                                                                 \
19332                case op0 : return node_allocator_->                                                                        \
19333                                     allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
19334                                        (s0,s1,rp0);                                                                       \
19335 
19336                string_opr_switch_statements
19337                #undef case_stmt
19338                default : return error_node();
19339             }
19340          }
19341 
19342          template <typename T0, typename T1>
19343          inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp1)
19344          {
19345             switch (opr)
19346             {
19347                #define case_stmt(op0,op1)                                                                                 \
19348                case op0 : return node_allocator_->                                                                        \
19349                                     allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
19350                                        (s0,s1,rp1);                                                                       \
19351 
19352                string_opr_switch_statements
19353                #undef case_stmt
19354                default : return error_node();
19355             }
19356          }
19357 
19358          template <typename T0, typename T1>
19359          inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0, range_pack rp1)
19360          {
19361             switch (opr)
19362             {
19363                #define case_stmt(op0,op1)                                                                                   \
19364                case op0 : return node_allocator_->                                                                          \
19365                                     allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
19366                                        (s0,s1,rp0,rp1);                                                                     \
19367 
19368                string_opr_switch_statements
19369                #undef case_stmt
19370                default : return error_node();
19371             }
19372          }
19373 
19374          template <typename T0, typename T1>
19375          inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
19376          {
19377             switch (opr)
19378             {
19379                #define case_stmt(op0,op1)                                                                        \
19380                case op0 : return node_allocator_->                                                               \
19381                                     allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \
19382 
19383                string_opr_switch_statements
19384                #undef case_stmt
19385                default : return error_node();
19386             }
19387          }
19388 
19389          inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19390          {
19391             std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19392             std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
19393             return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
19394          }
19395 
19396          inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19397          {
19398             std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
19399             std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
19400             range_pack rp0  = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
19401             dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19402             free_node(*node_allocator_,branch[0]);
19403             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0);
19404          }
19405 
19406          inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19407          {
19408             std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19409             std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref();
19410             range_pack rp1  = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
19411             dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19412             free_node(*node_allocator_,branch[1]);
19413             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1);
19414          }
19415 
19416 
19417          inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19418          {
19419             std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19420             std::string  s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19421             range_pack rp1  = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19422             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19423             free_node(*node_allocator_,branch[1]);
19424             return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1);
19425          }
19426 
19427          inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19428          {
19429             std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
19430             std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref();
19431             range_pack rp0  = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
19432             range_pack rp1  = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
19433             dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19434             dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19435             details::free_node(*node_allocator_,branch[0]);
19436             details::free_node(*node_allocator_,branch[1]);
19437             return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1);
19438          }
19439 
19440          inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19441          {
19442             std::string& s0 = dynamic_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
19443             std::string  s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19444             details::free_node(*node_allocator_,branch[1]);
19445             return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1);
19446          }
19447 
19448          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19449          {
19450             std::string  s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19451             std::string& s1 = dynamic_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
19452             details::free_node(*node_allocator_,branch[0]);
19453             return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
19454          }
19455 
19456          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19457          {
19458             std::string  s0 = dynamic_cast<details::string_literal_node<Type>*>         (branch[0])->str();
19459             std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref();
19460             range_pack rp1  = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
19461             dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19462             details::free_node(*node_allocator_,branch[0]);
19463             details::free_node(*node_allocator_,branch[1]);
19464             return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1);
19465          }
19466 
19467          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19468          {
19469             std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
19470             std::string  s1 = dynamic_cast<details::string_literal_node<Type>*>         (branch[1])->str();
19471             range_pack rp0  = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
19472             dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19473             details::free_node(*node_allocator_,branch[0]);
19474             details::free_node(*node_allocator_,branch[1]);
19475             return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0);
19476          }
19477 
19478          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19479          {
19480             std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>      (branch[0])->ref();
19481             std::string  s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19482             range_pack rp0  = dynamic_cast<details::string_range_node<Type,range_pack>*>      (branch[0])->range();
19483             range_pack rp1  = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19484             dynamic_cast<details::string_range_node<Type,range_pack>*>      (branch[0])->range_ref().clear();
19485             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19486             details::free_node(*node_allocator_,branch[0]);
19487             details::free_node(*node_allocator_,branch[1]);
19488             return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1);
19489          }
19490 
19491          inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19492          {
19493             const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19494             const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19495             expression_node_ptr result = error_node();
19496 
19497             if (details::e_add == opr)
19498                result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
19499             else if (details::e_in == opr)
19500                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
19501             else if (details::e_like == opr)
19502                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
19503             else if (details::e_ilike == opr)
19504                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
19505             else
19506             {
19507                expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1);
19508                Type v = temp->value();
19509                details::free_node(*node_allocator_,temp);
19510                result = node_allocator_->allocate<literal_node_t>(v);
19511             }
19512             details::free_all_nodes(*node_allocator_,branch);
19513             return result;
19514          }
19515 
19516          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19517          {
19518             const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>               (branch[0])->str();
19519                   std::string s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19520             range_pack rp1       = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19521             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19522             free_node(*node_allocator_,branch[0]);
19523             free_node(*node_allocator_,branch[1]);
19524             return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1);
19525          }
19526 
19527          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19528          {
19529             std::string  s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19530             std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>                    (branch[1])->ref();
19531             range_pack rp0  = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19532             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19533             free_node(*node_allocator_,branch[0]);
19534             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0);
19535          }
19536 
19537          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19538          {
19539             const std::string  s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19540                   std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>      (branch[1])->ref();
19541             range_pack rp0        = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19542             range_pack rp1        = dynamic_cast<details::string_range_node<Type,range_pack>*>      (branch[1])->range();
19543             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19544             dynamic_cast<details::string_range_node<Type,range_pack>*>      (branch[1])->range_ref().clear();
19545             free_node(*node_allocator_,branch[0]);
19546             free_node(*node_allocator_,branch[1]);
19547             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1);
19548          }
19549 
19550          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19551          {
19552             std::string       s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19553             const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>               (branch[1])->str();
19554             range_pack rp0  = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19555             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19556             details::free_all_nodes(*node_allocator_,branch);
19557             return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0);
19558          }
19559 
19560          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19561          {
19562             std::string s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19563             std::string s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19564             range_pack rp0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19565             range_pack rp1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19566             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19567             dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19568             details::free_all_nodes(*node_allocator_,branch);
19569             return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1);
19570          }
19571          #endif
19572 
19573          #ifndef exprtk_disable_string_capabilities
19574          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19575          {
19576             if ((0 == branch[0]) || (0 == branch[1]))
19577             {
19578                details::free_all_nodes(*node_allocator_,branch);
19579                return error_node();
19580             }
19581 
19582             const bool b0_is_s   = details::is_string_node            (branch[0]);
19583             const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
19584             const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
19585             const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
19586             const bool b1_is_s   = details::is_string_node            (branch[1]);
19587             const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
19588             const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
19589             const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
19590 
19591             if (b0_is_s)
19592             {
19593                     if (b1_is_s  ) return synthesize_sos_expression  (opr,branch);
19594                else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
19595                else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
19596                else if (b1_is_csr) return synthesize_socsr_expression(opr,branch);
19597             }
19598             else if (b0_is_cs)
19599             {
19600                     if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
19601                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
19602                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
19603                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
19604             }
19605             else if (b0_is_sr)
19606             {
19607                     if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
19608                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
19609                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
19610                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
19611             }
19612             else if (b0_is_csr)
19613             {
19614                     if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
19615                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
19616                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
19617                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
19618             }
19619             return error_node();
19620          }
19621          #else
19622          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[2])
19623          {
19624             details::free_all_nodes(*node_allocator_,branch);
19625             return error_node();
19626          }
19627          #endif
19628 
19629          #ifndef exprtk_disable_string_capabilities
19630          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
19631          {
19632             if (details::e_inrange != opr)
19633                return error_node();
19634             else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
19635             {
19636                details::free_all_nodes(*node_allocator_,branch);
19637                return error_node();
19638             }
19639             else if (
19640                       details::is_const_string_node(branch[0]) &&
19641                       details::is_const_string_node(branch[1]) &&
19642                       details::is_const_string_node(branch[2])
19643                     )
19644             {
19645                const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19646                const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19647                const std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
19648                Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
19649                details::free_all_nodes(*node_allocator_,branch);
19650                return node_allocator_->allocate_c<details::literal_node<Type> >(v);
19651             }
19652             else if (
19653                       details::is_string_node(branch[0]) &&
19654                       details::is_string_node(branch[1]) &&
19655                       details::is_string_node(branch[2])
19656                     )
19657             {
19658                std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19659                std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
19660                std::string& s2 = dynamic_cast<details::stringvar_node<Type>*>(branch[2])->ref();
19661                typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
19662                return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
19663             }
19664             else if (
19665                       details::is_const_string_node(branch[0]) &&
19666                             details::is_string_node(branch[1]) &&
19667                       details::is_const_string_node(branch[2])
19668                     )
19669             {
19670                std::string  s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19671                std::string& s1 = dynamic_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
19672                std::string  s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
19673                typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
19674                details::free_node(*node_allocator_,branch[0]);
19675                details::free_node(*node_allocator_,branch[2]);
19676                return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
19677             }
19678             else if (
19679                             details::is_string_node(branch[0]) &&
19680                       details::is_const_string_node(branch[1]) &&
19681                             details::is_string_node(branch[2])
19682                     )
19683             {
19684                std::string&  s0 = dynamic_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
19685                std::string   s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19686                std::string&  s2 = dynamic_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
19687                typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
19688                details::free_node(*node_allocator_,branch[1]);
19689                return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
19690             }
19691             else if (
19692                       details::is_string_node(branch[0]) &&
19693                       details::is_string_node(branch[1]) &&
19694                       details::is_const_string_node(branch[2])
19695                     )
19696             {
19697                std::string& s0 = dynamic_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
19698                std::string& s1 = dynamic_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
19699                std::string  s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
19700                typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
19701                details::free_node(*node_allocator_,branch[2]);
19702                return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
19703             }
19704             else if (
19705                       details::is_const_string_node(branch[0]) &&
19706                       details::      is_string_node(branch[1]) &&
19707                       details::      is_string_node(branch[2])
19708                     )
19709             {
19710                std::string  s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19711                std::string& s1 = dynamic_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
19712                std::string& s2 = dynamic_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
19713                typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
19714                details::free_node(*node_allocator_,branch[0]);
19715                return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
19716             }
19717             else
19718                return error_node();
19719          }
19720          #else
19721          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[3])
19722          {
19723             details::free_all_nodes(*node_allocator_,branch);
19724             return error_node();
19725          }
19726          #endif
19727 
19728          inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
19729          {
19730             /*
19731              Note: The following are the type promotion rules
19732              that relate to operations that include 'null':
19733              0. null ==/!=     null --> true false
19734              1. null operation null --> null
19735              2. x    ==/!=     null --> true/false
19736              3. null ==/!=     x    --> true/false
19737              4. x   operation  null --> x
19738              5. null operation x    --> x
19739             */
19740 
19741             typedef typename details::null_eq_node<T> nulleq_node_t;
19742 
19743             bool b0_null = details::is_null_node(branch[0]);
19744             bool b1_null = details::is_null_node(branch[1]);
19745 
19746             if (b0_null && b1_null)
19747             {
19748                expression_node_ptr result = error_node();
19749 
19750                if (details::e_eq == operation)
19751                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
19752                else if (details::e_ne == operation)
19753                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
19754 
19755                if (result)
19756                {
19757                   details::free_node(*node_allocator_,branch[0]);
19758                   details::free_node(*node_allocator_,branch[1]);
19759                   return result;
19760                }
19761 
19762                details::free_node(*node_allocator_,branch[1]);
19763                return branch[0];
19764             }
19765             else if (details::e_eq == operation)
19766             {
19767                expression_node_ptr result =
19768                                       node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
19769                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
19770                return result;
19771             }
19772             else if (details::e_ne == operation)
19773             {
19774                expression_node_ptr result =
19775                                       node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
19776                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
19777                return result;
19778             }
19779             else if (b0_null)
19780             {
19781                details::free_node(*node_allocator_,branch[0]);
19782                branch[0] = branch[1];
19783                branch[1] = error_node();
19784             }
19785             else if (b1_null)
19786             {
19787                details::free_node(*node_allocator_,branch[1]);
19788                branch[1] = error_node();
19789             }
19790 
19791             if (
19792                  (details::e_add  == operation) || (details::e_sub  == operation) ||
19793                  (details::e_mul  == operation) || (details::e_div  == operation) ||
19794                  (details::e_mod  == operation) || (details::e_pow  == operation)
19795                )
19796             {
19797                return branch[0];
19798             }
19799             else if (
19800                       (details::e_lt    == operation) || (details::e_lte  == operation) ||
19801                       (details::e_gt    == operation) || (details::e_gte  == operation) ||
19802                       (details::e_and   == operation) || (details::e_nand == operation) ||
19803                       (details::e_or    == operation) || (details::e_nor  == operation) ||
19804                       (details::e_xor   == operation) || (details::e_xnor == operation) ||
19805                       (details::e_in    == operation) || (details::e_like == operation) ||
19806                       (details::e_ilike == operation)
19807                     )
19808             {
19809                return node_allocator_->allocate_c<literal_node_t>(T(0));
19810             }
19811             details::free_node(*node_allocator_,branch[0]);
19812             return node_allocator_->allocate<details::null_node<Type> >();
19813          }
19814 
19815          template <typename NodeType, std::size_t N>
19816          inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
19817          {
19818             if (
19819                  (details::e_in    == operation) ||
19820                  (details::e_like  == operation) ||
19821                  (details::e_ilike == operation)
19822                )
19823                return error_node();
19824             else if (!details::all_nodes_valid<N>(branch))
19825             {
19826                free_all_nodes(*node_allocator_,branch);
19827                return error_node();
19828             }
19829             else if ((details::e_default != operation))
19830             {
19831                // Attempt simple constant folding optimization.
19832                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
19833                if (is_constant_foldable<N>(branch))
19834                {
19835                   Type v = expression_point->value();
19836                   details::free_node(*node_allocator_,expression_point);
19837                   return node_allocator_->allocate<literal_node_t>(v);
19838                }
19839                else
19840                   return expression_point;
19841             }
19842             else
19843                return error_node();
19844          }
19845 
19846          template <typename NodeType, std::size_t N>
19847          inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
19848          {
19849             if (!details::all_nodes_valid<N>(branch))
19850             {
19851                free_all_nodes(*node_allocator_,branch);
19852                return error_node();
19853             }
19854             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
19855             // Attempt simple constant folding optimization.
19856             expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
19857             dynamic_cast<function_N_node_t*>(expression_point)->init_branches(branch);
19858             if (is_constant_foldable<N>(branch) && !f->has_side_effects)
19859             {
19860                Type v = expression_point->value();
19861                details::free_node(*node_allocator_,expression_point);
19862                return node_allocator_->allocate<literal_node_t>(v);
19863             }
19864             else
19865                return expression_point;
19866          }
19867 
19868          bool strength_reduction_enabled_;
19869          details::node_allocator* node_allocator_;
19870          synthesize_map_t synthesize_map_;
19871          unary_op_map_t* unary_op_map_;
19872          binary_op_map_t* binary_op_map_;
19873          inv_binary_op_map_t* inv_binary_op_map_;
19874          sf3_map_t* sf3_map_;
19875          sf4_map_t* sf4_map_;
19876          parser_t* parser_;
19877       };
19878 
19879       inline void set_error(const parser_error::type& error_type)
19880       {
19881          error_list_.push_back(error_type);
19882       }
19883 
19884       inline void remove_last_error()
19885       {
19886          if (!error_list_.empty())
19887          {
19888             error_list_.pop_back();
19889          }
19890       }
19891 
19892       inline void set_synthesis_error(const std::string& synthesis_error_message)
19893       {
19894          if (synthesis_error_.empty())
19895          {
19896             synthesis_error_ = synthesis_error_message;
19897          }
19898       }
19899 
19900       inline void register_local_var(expression_node_ptr var)
19901       {
19902          local_var_set_.insert(var);
19903       }
19904 
19905       inline void clear_local_vars()
19906       {
19907          if (!local_var_set_.empty())
19908          {
19909             typedef std::set<expression_node_ptr> set_t;
19910             typename set_t::iterator itr = local_var_set_.begin();
19911             while (local_var_set_.end() != itr)
19912             {
19913                delete *itr;
19914                ++itr;
19915             }
19916             local_var_set_.clear();
19917          }
19918       }
19919 
19920       inline void register_local_vars(expression<T>& e)
19921       {
19922          if (!local_var_set_.empty())
19923          {
19924             typedef std::set<expression_node_ptr> set_t;
19925             typename set_t::iterator itr = local_var_set_.begin();
19926             while (local_var_set_.end() != itr)
19927             {
19928                e.register_local_var(*itr);
19929                ++itr;
19930             }
19931             local_var_set_.clear();
19932          }
19933       }
19934 
19935       inline void load_unary_operations_map(unary_op_map_t& m)
19936       {
19937          #define register_unary_op(Op,UnaryFunctor)             \
19938          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
19939 
19940          register_unary_op(details::  e_abs,details::  abs_op)
19941          register_unary_op(details:: e_acos,details:: acos_op)
19942          register_unary_op(details::e_acosh,details::acosh_op)
19943          register_unary_op(details:: e_asin,details:: asin_op)
19944          register_unary_op(details::e_asinh,details::asinh_op)
19945          register_unary_op(details::e_atanh,details::atanh_op)
19946          register_unary_op(details:: e_ceil,details:: ceil_op)
19947          register_unary_op(details::  e_cos,details::  cos_op)
19948          register_unary_op(details:: e_cosh,details:: cosh_op)
19949          register_unary_op(details::  e_exp,details::  exp_op)
19950          register_unary_op(details::e_expm1,details::expm1_op)
19951          register_unary_op(details::e_floor,details::floor_op)
19952          register_unary_op(details::  e_log,details::  log_op)
19953          register_unary_op(details::e_log10,details::log10_op)
19954          register_unary_op(details:: e_log2,details:: log2_op)
19955          register_unary_op(details::e_log1p,details::log1p_op)
19956          register_unary_op(details::  e_neg,details::  neg_op)
19957          register_unary_op(details::  e_pos,details::  pos_op)
19958          register_unary_op(details::e_round,details::round_op)
19959          register_unary_op(details::  e_sin,details::  sin_op)
19960          register_unary_op(details:: e_sinc,details:: sinc_op)
19961          register_unary_op(details:: e_sinh,details:: sinh_op)
19962          register_unary_op(details:: e_sqrt,details:: sqrt_op)
19963          register_unary_op(details::  e_tan,details::  tan_op)
19964          register_unary_op(details:: e_tanh,details:: tanh_op)
19965          register_unary_op(details::  e_cot,details::  cot_op)
19966          register_unary_op(details::  e_sec,details::  sec_op)
19967          register_unary_op(details::  e_csc,details::  csc_op)
19968          register_unary_op(details::  e_r2d,details::  r2d_op)
19969          register_unary_op(details::  e_d2r,details::  d2r_op)
19970          register_unary_op(details::  e_d2g,details::  d2g_op)
19971          register_unary_op(details::  e_g2d,details::  g2d_op)
19972          register_unary_op(details:: e_notl,details:: notl_op)
19973          register_unary_op(details::  e_sgn,details::  sgn_op)
19974          register_unary_op(details::  e_erf,details::  erf_op)
19975          register_unary_op(details:: e_erfc,details:: erfc_op)
19976          register_unary_op(details:: e_frac,details:: frac_op)
19977          register_unary_op(details::e_trunc,details::trunc_op)
19978          #undef register_unary_op
19979       }
19980 
19981       inline void load_binary_operations_map(binary_op_map_t& m)
19982       {
19983          #define register_binary_op(Op,BinaryFunctor)                                  \
19984          m.insert(typename binary_op_map_t::value_type(Op,BinaryFunctor<T>::process)); \
19985 
19986          register_binary_op(details:: e_add,details:: add_op)
19987          register_binary_op(details:: e_sub,details:: sub_op)
19988          register_binary_op(details:: e_mul,details:: mul_op)
19989          register_binary_op(details:: e_div,details:: div_op)
19990          register_binary_op(details:: e_mod,details:: mod_op)
19991          register_binary_op(details:: e_pow,details:: pow_op)
19992          register_binary_op(details::  e_lt,details::  lt_op)
19993          register_binary_op(details:: e_lte,details:: lte_op)
19994          register_binary_op(details::  e_gt,details::  gt_op)
19995          register_binary_op(details:: e_gte,details:: gte_op)
19996          register_binary_op(details::  e_eq,details::  eq_op)
19997          register_binary_op(details::  e_ne,details::  ne_op)
19998          register_binary_op(details:: e_and,details:: and_op)
19999          register_binary_op(details::e_nand,details::nand_op)
20000          register_binary_op(details::  e_or,details::  or_op)
20001          register_binary_op(details:: e_nor,details:: nor_op)
20002          register_binary_op(details:: e_xor,details:: xor_op)
20003          register_binary_op(details::e_xnor,details::xnor_op)
20004          #undef register_binary_op
20005       }
20006 
20007       inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
20008       {
20009          #define register_binary_op(Op,BinaryFunctor)                                      \
20010          m.insert(typename inv_binary_op_map_t::value_type(BinaryFunctor<T>::process,Op)); \
20011 
20012          register_binary_op(details:: e_add,details:: add_op)
20013          register_binary_op(details:: e_sub,details:: sub_op)
20014          register_binary_op(details:: e_mul,details:: mul_op)
20015          register_binary_op(details:: e_div,details:: div_op)
20016          register_binary_op(details:: e_mod,details:: mod_op)
20017          register_binary_op(details:: e_pow,details:: pow_op)
20018          register_binary_op(details::  e_lt,details::  lt_op)
20019          register_binary_op(details:: e_lte,details:: lte_op)
20020          register_binary_op(details::  e_gt,details::  gt_op)
20021          register_binary_op(details:: e_gte,details:: gte_op)
20022          register_binary_op(details::  e_eq,details::  eq_op)
20023          register_binary_op(details::  e_ne,details::  ne_op)
20024          register_binary_op(details:: e_and,details:: and_op)
20025          register_binary_op(details::e_nand,details::nand_op)
20026          register_binary_op(details::  e_or,details::  or_op)
20027          register_binary_op(details:: e_nor,details:: nor_op)
20028          register_binary_op(details:: e_xor,details:: xor_op)
20029          register_binary_op(details::e_xnor,details::xnor_op)
20030          #undef register_binary_op
20031       }
20032 
20033       inline void load_sf3_map(sf3_map_t& sf3_map)
20034       {
20035          typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
20036 
20037          #define register_sf3(Op)                                                                             \
20038          sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
20039 
20040          register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
20041          register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
20042          register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
20043          register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
20044          register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
20045          register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
20046          register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
20047          register_sf3(28) register_sf3(29) register_sf3(30)
20048          #undef register_sf3
20049       }
20050 
20051       inline void load_sf4_map(sf4_map_t& sf4_map)
20052       {
20053          typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
20054 
20055          #define register_sf4(Op)                                                                             \
20056          sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
20057 
20058          register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
20059          register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
20060          register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
20061          register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
20062          register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
20063          register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
20064          register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
20065          register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
20066          register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
20067          #undef register_sf4
20068 
20069          #define register_sf4ext(Op)                                                                                    \
20070          sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
20071 
20072          register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
20073          register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
20074          register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
20075          register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
20076          register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
20077          register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
20078          register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
20079          register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
20080          register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
20081          register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
20082          register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
20083          register_sf4ext(44) register_sf4ext(45)
20084          #undef register_sf4ext
20085       }
20086 
20087    private:
20088 
20089       parser(const parser<T>&);
20090       parser<T>& operator=(const parser<T>&);
20091 
20092       lexer::generator lexer_;
20093       lexer::token current_token_;
20094       lexer::token store_current_token_;
20095       expression_generator<T> expression_generator_;
20096       details::node_allocator node_allocator_;
20097       symbol_table_t symbol_table_;
20098       symbol_table_t local_symbol_table_;
20099       bool symbol_name_caching_;
20100       std::size_t compile_options_;
20101       std::set<expression_node_ptr> local_var_set_;
20102       std::deque<std::string> symbol_name_cache_;
20103       std::deque<parser_error::type> error_list_;
20104       std::deque<bool> brkcnt_list_;
20105       bool resolve_unknown_symbol_;
20106       unknown_symbol_resolver* unknown_symbol_resolver_;
20107       unknown_symbol_resolver default_usr_;
20108       base_ops_map_t base_ops_map_;
20109       unary_op_map_t unary_op_map_;
20110       binary_op_map_t binary_op_map_;
20111       inv_binary_op_map_t inv_binary_op_map_;
20112       sf3_map_t sf3_map_;
20113       sf4_map_t sf4_map_;
20114       std::string synthesis_error_;
20115 
20116       lexer::helper::helper_assembly helper_assembly_;
20117 
20118       lexer::helper::commutative_inserter commutative_inserter_;
20119       lexer::helper::operator_joiner      operator_joiner_2_;
20120       lexer::helper::operator_joiner      operator_joiner_3_;
20121       lexer::helper::symbol_replacer      symbol_replacer_;
20122       lexer::helper::bracket_checker      bracket_checker_;
20123       lexer::helper::numeric_checker      numeric_checker_;
20124       lexer::helper::sequence_validator   sequence_validator_;
20125    };
20126 
20127    template <typename T>
20128    inline T integrate(expression<T>& e,
20129                       T& x,
20130                       const T& r0, const T& r1,
20131                       const std::size_t number_of_intervals = 1000000)
20132    {
20133       if (r0 > r1) return T(0);
20134       T h = (r1 - r0) / (T(2) * number_of_intervals);
20135       T total_area = T(0);
20136       for (std::size_t i = 0; i < number_of_intervals; ++i)
20137       {
20138          x = r0 + T(2) * i * h;
20139          T y0 = e.value(); x += h;
20140          T y1 = e.value(); x += h;
20141          T y2 = e.value(); x += h;
20142          total_area += h * (y0 + T(4) * y1 + y2) / T(3);
20143       }
20144       return total_area;
20145    }
20146 
20147    template <typename T>
20148    inline T integrate(expression<T>& e,
20149                       const std::string& variable_name,
20150                       const T& r0, const T& r1,
20151                       const std::size_t number_of_intervals = 1000000)
20152    {
20153       symbol_table<T>& sym_table = e.get_symbol_table();
20154       if (!sym_table.valid())
20155          return std::numeric_limits<T>::quiet_NaN();
20156       details::variable_node<T>* var = sym_table.get_variable(variable_name);
20157       if (var)
20158       {
20159          T& x = var->ref();
20160          T  x_original = x;
20161          T result = integrate(e,x,r0,r1,number_of_intervals);
20162          x = x_original;
20163          return result;
20164       }
20165       else
20166          return std::numeric_limits<T>::quiet_NaN();
20167    }
20168 
20169    template <typename T>
20170    inline T derivative(expression<T>& e,
20171                        T& x,
20172                        const T& h = T(0.00000001))
20173    {
20174       T x_init = x;
20175       x = x_init + T(2) * h;
20176       T y0 = e.value();
20177       x = x_init + h;
20178       T y1 = e.value();
20179       x = x_init - h;
20180       T y2 = e.value();
20181       x = x_init - T(2) * h;
20182       T y3 = e.value();
20183       x = x_init;
20184       return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
20185    }
20186 
20187    template <typename T>
20188    inline T second_derivative(expression<T>& e,
20189                               T& x,
20190                               const T& h = T(0.00001))
20191    {
20192       T y = e.value();
20193       T x_init = x;
20194       x = x_init + T(2) * h;
20195       T y0 = e.value();
20196       x = x_init + h;
20197       T y1 = e.value();
20198       x = x_init - h;
20199       T y2 = e.value();
20200       x = x_init - T(2) * h;
20201       T y3 = e.value();
20202       x = x_init;
20203       return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
20204    }
20205 
20206    template <typename T>
20207    inline T third_derivative(expression<T>& e,
20208                              T& x,
20209                              const T& h = T(0.0001))
20210    {
20211       T x_init = x;
20212       x = x_init + T(2) * h;
20213       T y0 = e.value();
20214       x = x_init + h;
20215       T y1 = e.value();
20216       x = x_init - h;
20217       T y2 = e.value();
20218       x = x_init - T(2) * h;
20219       T y3 = e.value();
20220       x = x_init;
20221       return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
20222    }
20223 
20224    template <typename T>
20225    inline T derivative(expression<T>& e,
20226                        const std::string& variable_name,
20227                        const T& h = T(0.00000001))
20228    {
20229       symbol_table<T>& sym_table = e.get_symbol_table();
20230       if (!sym_table.valid())
20231          return std::numeric_limits<T>::quiet_NaN();
20232       details::variable_node<T>* var = sym_table.get_variable(variable_name);
20233       if (var)
20234       {
20235          T& x = var->ref();
20236          T x_original = x;
20237          T result = derivative(e,x,h);
20238          x = x_original;
20239          return result;
20240       }
20241       else
20242          return std::numeric_limits<T>::quiet_NaN();
20243    }
20244 
20245    template <typename T>
20246    inline T second_derivative(expression<T>& e,
20247                               const std::string& variable_name,
20248                               const T& h = T(0.00001))
20249    {
20250       symbol_table<T>& sym_table = e.get_symbol_table();
20251       if (!sym_table.valid())
20252          return std::numeric_limits<T>::quiet_NaN();
20253       details::variable_node<T>* var = sym_table.get_variable(variable_name);
20254       if (var)
20255       {
20256          T& x = var->ref();
20257          T x_original = x;
20258          T result = second_derivative(e,x,h);
20259          x = x_original;
20260          return result;
20261       }
20262       else
20263          return std::numeric_limits<T>::quiet_NaN();
20264    }
20265 
20266    template <typename T>
20267    inline T third_derivative(expression<T>& e,
20268                              const std::string& variable_name,
20269                              const T& h = T(0.0001))
20270    {
20271       symbol_table<T>& sym_table = e.get_symbol_table();
20272       if (!sym_table.valid())
20273          return std::numeric_limits<T>::quiet_NaN();
20274       details::variable_node<T>* var = sym_table.get_variable(variable_name);
20275       if (var)
20276       {
20277          T& x = var->ref();
20278          T x_original = x;
20279          T result = third_derivative(e,x,h);
20280          x = x_original;
20281          return result;
20282       }
20283       else
20284          return std::numeric_limits<T>::quiet_NaN();
20285    }
20286 
20287    /*
20288       Note: The following 'compute' routines are very simple helpers,
20289       for quickly setting up the required pieces of code in order to
20290       evaluate an expression. By virtue of how they operate there will
20291       be an overhead with regards to their setup and teardown and hence
20292       should not be used in time critical sections of code.
20293       Furthermore they only assume a small sub set of variables - no
20294       string variables or user defined functions.
20295    */
20296    template <typename T>
20297    inline bool compute(const std::string& expression_string, T& result)
20298    {
20299       // No variables
20300       symbol_table<T> symbol_table;
20301       symbol_table.add_constants();
20302 
20303       expression<T> expression;
20304       parser<T> parser;
20305 
20306       if (parser.compile(expression_string,expression))
20307       {
20308          result = expression.value();
20309          return true;
20310       }
20311       else
20312          return false;
20313    }
20314 
20315    template <typename T>
20316    inline bool compute(const std::string& expression_string,
20317                        const T& x,
20318                        T& result)
20319    {
20320       // Only 'x'
20321       static const std::string x_var("x");
20322       symbol_table<T> symbol_table;
20323       symbol_table.add_constants();
20324       symbol_table.add_variable(x_var,x);
20325       expression<T> expression;
20326       parser<T> parser;
20327       if (parser.compile(expression_string,expression))
20328       {
20329          result = expression.value();
20330          return true;
20331       }
20332       else
20333          return false;
20334    }
20335 
20336    template <typename T>
20337    inline bool compute(const std::string& expression_string,
20338                        const T&x, const T& y,
20339                        T& result)
20340    {
20341       // Only 'x' and 'y'
20342       static const std::string x_var("x");
20343       static const std::string y_var("y");
20344       symbol_table<T> symbol_table;
20345       symbol_table.add_constants();
20346       symbol_table.add_variable(x_var,x);
20347       symbol_table.add_variable(y_var,y);
20348       expression<T> expression;
20349       parser<T> parser;
20350       if (parser.compile(expression_string,expression))
20351       {
20352          result = expression.value();
20353          return true;
20354       }
20355       else
20356          return false;
20357    }
20358 
20359    template <typename T>
20360    inline bool compute(const std::string& expression_string,
20361                        const T& x, const T& y, const T& z,
20362                        T& result)
20363    {
20364       // Only 'x', 'y' or 'z'
20365       static const std::string x_var("x");
20366       static const std::string y_var("y");
20367       static const std::string z_var("z");
20368       symbol_table<T> symbol_table;
20369       symbol_table.add_constants();
20370       symbol_table.add_variable(x_var,x);
20371       symbol_table.add_variable(y_var,y);
20372       symbol_table.add_variable(z_var,z);
20373       expression<T> expression;
20374       parser<T> parser;
20375       if (parser.compile(expression_string,expression))
20376       {
20377          result = expression.value();
20378          return true;
20379       }
20380       else
20381          return false;
20382    }
20383 
20384    template <typename T, std::size_t N>
20385    class polynomial : public ifunction<T>
20386    {
20387    private:
20388 
20389       template <typename Type, std::size_t NumberOfCoefficients>
20390       struct poly_impl { };
20391 
20392       template <typename Type>
20393       struct poly_impl <Type,12>
20394       {
20395          static inline T evaluate(const Type x,
20396                                   const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
20397                                   const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
20398                                   const Type  c2, const Type  c1, const Type  c0)
20399          {
20400             // 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
20401             return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20402          }
20403       };
20404 
20405       template <typename Type>
20406       struct poly_impl <Type,11>
20407       {
20408          static inline T evaluate(const Type x,
20409                                   const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
20410                                   const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
20411                                   const Type c1,  const Type  c0)
20412          {
20413             // 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
20414             return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20415          }
20416       };
20417 
20418       template <typename Type>
20419       struct poly_impl <Type,10>
20420       {
20421          static inline T evaluate(const Type x,
20422                                   const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
20423                                   const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
20424                                   const Type c0)
20425          {
20426             // 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
20427             return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20428          }
20429       };
20430 
20431       template <typename Type>
20432       struct poly_impl <Type,9>
20433       {
20434          static inline T evaluate(const Type x,
20435                                   const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
20436                                   const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
20437          {
20438             // 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
20439             return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20440          }
20441       };
20442 
20443       template <typename Type>
20444       struct poly_impl <Type,8>
20445       {
20446          static inline T evaluate(const Type x,
20447                                   const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
20448                                   const Type c3, const Type c2, const Type c1, const Type c0)
20449          {
20450             // 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
20451             return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20452          }
20453       };
20454 
20455       template <typename Type>
20456       struct poly_impl <Type,7>
20457       {
20458          static inline T evaluate(const Type x,
20459                                   const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
20460                                   const Type c2, const Type c1, const Type c0)
20461          {
20462             // 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
20463             return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20464          }
20465       };
20466 
20467       template <typename Type>
20468       struct poly_impl <Type,6>
20469       {
20470          static inline T evaluate(const Type x,
20471                                   const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
20472                                   const Type c1, const Type c0)
20473          {
20474             // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
20475             return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20476          }
20477       };
20478 
20479       template <typename Type>
20480       struct poly_impl <Type,5>
20481       {
20482          static inline T evaluate(const Type x,
20483                                   const Type c5, const Type c4, const Type c3, const Type c2,
20484                                   const Type c1, const Type c0)
20485          {
20486             // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
20487             return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20488          }
20489       };
20490 
20491       template <typename Type>
20492       struct poly_impl <Type,4>
20493       {
20494          static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
20495          {
20496             // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
20497             return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
20498          }
20499       };
20500 
20501       template <typename Type>
20502       struct poly_impl <Type,3>
20503       {
20504          static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
20505          {
20506             // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
20507             return (((c3 * x + c2) * x + c1) * x + c0);
20508          }
20509       };
20510 
20511       template <typename Type>
20512       struct poly_impl <Type,2>
20513       {
20514          static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
20515          {
20516             // p(x) = c_2x^2 + c_1x^1 + c_0x^0
20517             return ((c2 * x + c1) * x + c0);
20518          }
20519       };
20520 
20521       template <typename Type>
20522       struct poly_impl <Type,1>
20523       {
20524          static inline T evaluate(const Type x, const Type c1, const Type c0)
20525          {
20526             // p(x) = c_1x^1 + c_0x^0
20527             return (c1 * x + c0);
20528          }
20529       };
20530 
20531    public:
20532 
20533       polynomial()
20534       : exprtk::ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max(),false)
20535       {}
20536 
20537       inline virtual T operator()(const T& x, const T& c1, const T& c0)
20538       {
20539          return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20540       }
20541 
20542       inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
20543       {
20544          return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20545       }
20546 
20547       inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
20548       {
20549          return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20550       }
20551 
20552       inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20553       {
20554          return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20555       }
20556 
20557       inline virtual T operator()(const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20558       {
20559          return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20560       }
20561 
20562       inline virtual T operator()(const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20563       {
20564          return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20565       }
20566 
20567       inline virtual T operator()(const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20568       {
20569          return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20570       }
20571 
20572       inline virtual T operator()(const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20573       {
20574          return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20575       }
20576 
20577       inline virtual T operator()(const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20578       {
20579          return ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20580       }
20581 
20582       inline virtual T operator()(const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20583       {
20584          return ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20585       }
20586 
20587       inline virtual T operator()(const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20588       {
20589          return ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20590       }
20591 
20592       inline virtual T operator()(const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20593       {
20594          return ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20595       }
20596 
20597       inline virtual T operator()()
20598       {
20599          return std::numeric_limits<T>::quiet_NaN();
20600       }
20601 
20602       inline virtual T operator()(const T&)
20603       {
20604          return std::numeric_limits<T>::quiet_NaN();
20605       }
20606 
20607       inline virtual T operator()(const T&, const T&)
20608       {
20609          return std::numeric_limits<T>::quiet_NaN();
20610       }
20611 
20612    };
20613 
20614    template <typename T>
20615    class function_compositor
20616    {
20617    public:
20618 
20619       typedef exprtk::expression<T>   expression_t;
20620       typedef exprtk::symbol_table<T> symbol_table_t;
20621       typedef exprtk::parser<T>       parser_t;
20622 
20623       struct function
20624       {
20625          function(const std::string& n)
20626          : name_(n)
20627          {}
20628 
20629          inline function& name(const std::string& n)
20630          {
20631             name_ = n;
20632             return (*this);
20633          }
20634 
20635          inline function& expression(const std::string& e)
20636          {
20637             expression_ = e;
20638             return (*this);
20639          }
20640 
20641          inline function& var(const std::string& v)
20642          {
20643             v_.push_back(v);
20644             return (*this);
20645          }
20646 
20647          std::string name_;
20648          std::string expression_;
20649          std::deque<std::string> v_;
20650       };
20651 
20652    private:
20653 
20654       struct base_func : public exprtk::ifunction<T>
20655       {
20656          typedef const T& type;
20657          typedef exprtk::ifunction<T> function_t;
20658          typedef std::vector<T*> varref_t;
20659          typedef std::vector<T>  var_t;
20660 
20661          base_func(const std::size_t& param_count = 0)
20662          : exprtk::ifunction<T>(param_count),
20663            stack_depth(0)
20664          {
20665             v.resize(param_count);
20666          }
20667 
20668          inline void update(const T& v0)
20669          {
20670             (*v[0]) = v0;
20671          }
20672 
20673          inline void update(const T& v0, const T& v1)
20674          {
20675             (*v[0]) = v0; (*v[1]) = v1;
20676          }
20677 
20678          inline void update(const T& v0, const T& v1, const T& v2)
20679          {
20680             (*v[0]) = v0; (*v[1]) = v1;
20681             (*v[2]) = v2;
20682          }
20683 
20684          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
20685          {
20686             (*v[0]) = v0; (*v[1]) = v1;
20687             (*v[2]) = v2; (*v[3]) = v3;
20688          }
20689 
20690          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
20691          {
20692             (*v[0]) = v0; (*v[1]) = v1;
20693             (*v[2]) = v2; (*v[3]) = v3;
20694             (*v[4]) = v4;
20695          }
20696 
20697          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
20698          {
20699             (*v[0]) = v0; (*v[1]) = v1;
20700             (*v[2]) = v2; (*v[3]) = v3;
20701             (*v[4]) = v4; (*v[5]) = v5;
20702          }
20703 
20704          inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2, T& v3, T& v4, T& v5)
20705          {
20706             expression = expr;
20707             v[0] = &v0; v[1] = &v1;
20708             v[2] = &v2; v[3] = &v3;
20709             v[4] = &v4; v[5] = &v5;
20710             clear_stack();
20711             return (*this);
20712          }
20713 
20714          inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2, T& v3, T& v4)
20715          {
20716             expression = expr;
20717             v[0] = &v0; v[1] = &v1;
20718             v[2] = &v2; v[3] = &v3;
20719             v[4] = &v4;
20720             clear_stack();
20721             return (*this);
20722          }
20723 
20724          inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2, T& v3)
20725          {
20726             expression = expr;
20727             v[0] = &v0; v[1] = &v1;
20728             v[2] = &v2; v[3] = &v3;
20729             clear_stack();
20730             return (*this);
20731          }
20732 
20733          inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2)
20734          {
20735             expression = expr;
20736             v[0] = &v0; v[1] = &v1;
20737             v[2] = &v2;
20738             clear_stack();
20739             return (*this);
20740          }
20741 
20742          inline function_t& setup(expression_t& expr, T& v0, T& v1)
20743          {
20744             expression = expr;
20745             v[0] = &v0; v[1] = &v1;
20746             clear_stack();
20747             return (*this);
20748          }
20749 
20750          inline function_t& setup(expression_t& expr, T& v0)
20751          {
20752             expression = expr;
20753             v[0] = &v0;
20754             clear_stack();
20755             return (*this);
20756          }
20757 
20758          inline function_t& setup(expression_t& expr)
20759          {
20760             expression = expr;
20761             return (*this);
20762          }
20763 
20764          inline void pre()
20765          {
20766             if (stack_depth++)
20767             {
20768                var_t var_stack(v.size(),T(0));
20769                copy(v,var_stack);
20770                stack.push_back(var_stack);
20771             }
20772          }
20773 
20774          inline void post()
20775          {
20776             if (--stack_depth)
20777             {
20778                copy(stack.back(),v);
20779                stack.pop_back();
20780             }
20781          }
20782 
20783          void copy(const varref_t& src_v, var_t& dest_v)
20784          {
20785             for (std::size_t i = 0; i < src_v.size(); ++i)
20786             {
20787                dest_v[i] = (*src_v[i]);
20788             }
20789          }
20790 
20791          void copy(const var_t& src_v, varref_t& dest_v)
20792          {
20793             for (std::size_t i = 0; i < src_v.size(); ++i)
20794             {
20795                (*dest_v[i]) = src_v[i];
20796             }
20797          }
20798 
20799          inline void clear_stack()
20800          {
20801             for (std::size_t i = 0; i < v.size(); ++i)
20802             {
20803                (*v[i]) = 0;
20804             }
20805          }
20806 
20807          expression_t expression;
20808          varref_t v;
20809          std::size_t stack_depth;
20810          std::deque<var_t> stack;
20811       };
20812 
20813       struct func_0param : public base_func
20814       {
20815          func_0param() : base_func(0) {}
20816 
20817          inline T operator()()
20818          {
20819             return base_func::expression.value();
20820          }
20821       };
20822 
20823       typedef const T& type;
20824 
20825       struct func_1param : public base_func
20826       {
20827          func_1param() : base_func(1) {}
20828 
20829          inline T operator()(type v0)
20830          {
20831             base_func::pre();
20832             base_func::update(v0);
20833             T result = base_func::expression.value();
20834             base_func::post();
20835             return result;
20836          }
20837       };
20838 
20839       struct func_2param : public base_func
20840       {
20841          func_2param() : base_func(2) {}
20842 
20843          inline T operator()(type v0, type v1)
20844          {
20845             base_func::pre();
20846             base_func::update(v0,v1);
20847             T result = base_func::expression.value();
20848             base_func::post();
20849             return result;
20850          }
20851       };
20852 
20853       struct func_3param : public base_func
20854       {
20855          func_3param() : base_func(3) {}
20856 
20857          inline T operator()(type v0, type v1, type v2)
20858          {
20859             base_func::pre();
20860             base_func::update(v0,v1,v2);
20861             T result = base_func::expression.value();
20862             base_func::post();
20863             return result;
20864          }
20865       };
20866 
20867       struct func_4param : public base_func
20868       {
20869          func_4param() : base_func(4) {}
20870 
20871          inline T operator()(type v0, type v1, type v2, type v3)
20872          {
20873             base_func::pre();
20874             base_func::update(v0,v1,v2,v3);
20875             T result = base_func::expression.value();
20876             base_func::post();
20877             return result;
20878          }
20879       };
20880 
20881       struct func_5param : public base_func
20882       {
20883          func_5param() : base_func(5) {}
20884 
20885          inline T operator()(type v0, type v1, type v2, type v3, type v4)
20886          {
20887             base_func::pre();
20888             base_func::update(v0,v1,v2,v3,v4);
20889             T result = base_func::expression.value();
20890             base_func::post();
20891             return result;
20892          }
20893       };
20894 
20895       struct func_6param : public base_func
20896       {
20897          func_6param() : base_func(6) {}
20898 
20899          inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
20900          {
20901             base_func::pre();
20902             base_func::update(v0,v1,v2,v3,v4,v5);
20903             T result = base_func::expression.value();
20904             base_func::post();
20905             return result;
20906          }
20907       };
20908 
20909    public:
20910 
20911       function_compositor()
20912       : suffix_index_(1),
20913         id_(get_id())
20914       {}
20915 
20916       function_compositor(const symbol_table_t& st)
20917       : symbol_table_(st),
20918         suffix_index_(1),
20919         id_(get_id())
20920       {}
20921 
20922       inline symbol_table_t& symbol_table()
20923       {
20924          return symbol_table_;
20925       }
20926 
20927       void clear()
20928       {
20929          symbol_table_.clear();
20930          expr_map_.clear();
20931          f0p_map_.clear();
20932          f1p_map_.clear();
20933          f2p_map_.clear();
20934          f3p_map_.clear();
20935          f4p_map_.clear();
20936          f5p_map_.clear();
20937          f6p_map_.clear();
20938          suffix_index_ = 1;
20939       }
20940 
20941       inline bool add(const function& f)
20942       {
20943          switch (f.v_.size())
20944          {
20945             case 0  : return add(f.name_,f.expression_);
20946             case 1  : return add(f.name_,f.expression_,f.v_[0]);
20947             case 2  : return add(f.name_,f.expression_,f.v_[0],f.v_[1]);
20948             case 3  : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2]);
20949             case 4  : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3]);
20950             case 5  : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3],f.v_[4]);
20951             case 6  : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3],f.v_[4],f.v_[5]);
20952             default : return false;
20953          }
20954       }
20955 
20956       inline bool add(const std::string& name,
20957                       const std::string& expression)
20958       {
20959          if (expr_map_.end() != expr_map_.find(name))
20960             return false;
20961          else if (!forward(name,0))
20962             return false;
20963          std::vector<std::pair<std::string,std::string> > var_transform_list;
20964          if (compile_expression(name,expression,var_transform_list))
20965          {
20966             f0p_map_[name].setup(expr_map_[name]);
20967             return true;
20968          }
20969          else
20970          {
20971             remove(name,0);
20972             return false;
20973          }
20974       }
20975 
20976       inline bool add(const std::string& name,
20977                       const std::string& expression,
20978                       const std::string& v0)
20979       {
20980          const std::size_t n = 1;
20981          T* v[n] = { 0 };
20982          std::string sv[n];
20983          if (expr_map_.end() != expr_map_.find(name))
20984             return false;
20985          else if (!forward(name,1))
20986             return false;
20987          else if (!add_variable(v0,v[0],sv[0]))
20988             return false;
20989          std::vector<std::pair<std::string,std::string> > var_transform_list;
20990          var_transform_list.push_back(std::make_pair(v0,sv[0]));
20991          if (compile_expression(name,expression,var_transform_list))
20992          {
20993             f1p_map_[name].setup(expr_map_[name],(*v[0]));
20994             return true;
20995          }
20996          else
20997          {
20998             remove(name,sv);
20999             return false;
21000          }
21001       }
21002 
21003       inline bool add(const std::string& name,
21004                       const std::string& expression,
21005                       const std::string& v0, const std::string& v1)
21006       {
21007          const std::size_t n = 2;
21008          T* v[n] = { 0 };
21009          std::string sv[n];
21010          if (expr_map_.end() != expr_map_.find(name))
21011             return false;
21012          else if (!forward(name,2))
21013             return false;
21014          else if (!add_variable(v0,v[0],sv[0])) return false;
21015          else if (!add_variable(v1,v[1],sv[1])) return false;
21016          std::vector<std::pair<std::string,std::string> > var_transform_list;
21017          var_transform_list.push_back(std::make_pair(v0,sv[0]));
21018          var_transform_list.push_back(std::make_pair(v1,sv[1]));
21019          if (compile_expression(name,expression,var_transform_list))
21020          {
21021             f2p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]));
21022             return true;
21023          }
21024          else
21025          {
21026             remove(name,sv);
21027             return false;
21028          }
21029       }
21030 
21031       inline bool add(const std::string& name,
21032                       const std::string& expression,
21033                       const std::string& v0, const std::string& v1, const std::string& v2)
21034       {
21035          const std::size_t n = 3;
21036          T* v[n] = { 0 };
21037          std::string sv[n];
21038          if (expr_map_.end() != expr_map_.find(name))
21039             return false;
21040          else if (!forward(name,3))
21041             return false;
21042          else if (!add_variable(v0,v[0],sv[0])) return false;
21043          else if (!add_variable(v1,v[1],sv[1])) return false;
21044          else if (!add_variable(v2,v[2],sv[2])) return false;
21045          std::vector<std::pair<std::string,std::string> > var_transform_list;
21046          var_transform_list.push_back(std::make_pair(v0,sv[0]));
21047          var_transform_list.push_back(std::make_pair(v1,sv[1]));
21048          var_transform_list.push_back(std::make_pair(v2,sv[2]));
21049          if (compile_expression(name,expression,var_transform_list))
21050          {
21051             f3p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]));
21052             return true;
21053          }
21054          else
21055          {
21056             remove(name,sv);
21057             return false;
21058          }
21059       }
21060 
21061       inline bool add(const std::string& name,
21062                       const std::string& expression,
21063                       const std::string& v0, const std::string& v1, const std::string& v2,
21064                       const std::string& v3)
21065       {
21066          const std::size_t n = 4;
21067          T* v[n] = { 0 };
21068          std::string sv[n];
21069          if (expr_map_.end() != expr_map_.find(name))
21070             return false;
21071          else if (!forward(name,4))
21072             return false;
21073          else if (!add_variable(v0,v[0],sv[0])) return false;
21074          else if (!add_variable(v1,v[1],sv[1])) return false;
21075          else if (!add_variable(v2,v[2],sv[2])) return false;
21076          else if (!add_variable(v3,v[3],sv[3])) return false;
21077          std::vector<std::pair<std::string,std::string> > var_transform_list;
21078          var_transform_list.push_back(std::make_pair(v0,sv[0]));
21079          var_transform_list.push_back(std::make_pair(v1,sv[1]));
21080          var_transform_list.push_back(std::make_pair(v2,sv[2]));
21081          var_transform_list.push_back(std::make_pair(v3,sv[3]));
21082          if (compile_expression(name,expression,var_transform_list))
21083          {
21084             f4p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]));
21085             return true;
21086          }
21087          else
21088          {
21089             remove(name,sv);
21090             return false;
21091          }
21092       }
21093 
21094       inline bool add(const std::string& name,
21095                       const std::string& expression,
21096                       const std::string& v0, const std::string& v1, const std::string& v2,
21097                       const std::string& v3, const std::string& v4)
21098       {
21099          const std::size_t n = 5;
21100          T* v[n] = { 0 };
21101          std::string sv[n];
21102          if (expr_map_.end() != expr_map_.find(name))
21103             return false;
21104          else if (!forward(name,5))
21105             return false;
21106          else if (!add_variable(v0,v[0],sv[0])) return false;
21107          else if (!add_variable(v1,v[1],sv[1])) return false;
21108          else if (!add_variable(v2,v[2],sv[2])) return false;
21109          else if (!add_variable(v3,v[3],sv[3])) return false;
21110          else if (!add_variable(v3,v[4],sv[4])) return false;
21111          std::vector<std::pair<std::string,std::string> > var_transform_list;
21112          var_transform_list.push_back(std::make_pair(v0,sv[0]));
21113          var_transform_list.push_back(std::make_pair(v1,sv[1]));
21114          var_transform_list.push_back(std::make_pair(v2,sv[2]));
21115          var_transform_list.push_back(std::make_pair(v3,sv[3]));
21116          var_transform_list.push_back(std::make_pair(v4,sv[4]));
21117          if (compile_expression(name,expression,var_transform_list))
21118          {
21119             f5p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]),(*v[4]));
21120             return true;
21121          }
21122          else
21123          {
21124             remove(name,sv);
21125             return false;
21126          }
21127       }
21128 
21129       inline bool add(const std::string& name,
21130                       const std::string& expression,
21131                       const std::string& v0, const std::string& v1, const std::string& v2,
21132                       const std::string& v3, const std::string& v4, const std::string& v5)
21133       {
21134          const std::size_t n = 6;
21135          T* v[n] = { 0 };
21136          std::string sv[n];
21137          if (expr_map_.end() != expr_map_.find(name))
21138             return false;
21139          else if (!forward(name,6))
21140             return false;
21141          else if (!add_variable(v0,v[0],sv[0])) return false;
21142          else if (!add_variable(v1,v[1],sv[1])) return false;
21143          else if (!add_variable(v2,v[2],sv[2])) return false;
21144          else if (!add_variable(v3,v[3],sv[3])) return false;
21145          else if (!add_variable(v4,v[4],sv[4])) return false;
21146          else if (!add_variable(v5,v[5],sv[5])) return false;
21147          std::vector<std::pair<std::string,std::string> > var_transform_list;
21148          var_transform_list.push_back(std::make_pair(v0,sv[0]));
21149          var_transform_list.push_back(std::make_pair(v1,sv[1]));
21150          var_transform_list.push_back(std::make_pair(v2,sv[2]));
21151          var_transform_list.push_back(std::make_pair(v3,sv[3]));
21152          var_transform_list.push_back(std::make_pair(v4,sv[4]));
21153          var_transform_list.push_back(std::make_pair(v5,sv[5]));
21154          if (compile_expression(name,expression,var_transform_list))
21155          {
21156             f6p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]),(*v[4]),(*v[5]));
21157             return true;
21158          }
21159          else
21160          {
21161             remove(name,sv);
21162             return false;
21163          }
21164       }
21165 
21166    private:
21167 
21168       template <typename Allocator,
21169                 template <typename,typename> class Sequence>
21170       bool compile_expression(const std::string& name,
21171                               const std::string& expression,
21172                               const Sequence<std::pair<std::string,std::string>,Allocator>& var_transform_list)
21173       {
21174          expression_t compiled_expression;
21175          compiled_expression.register_symbol_table(symbol_table_);
21176 
21177          for (std::size_t i = 0; i < var_transform_list.size(); ++i)
21178          {
21179             parser_.remove_replace_symbol(var_transform_list[i].first);
21180             if (!parser_.replace_symbol(var_transform_list[i].first,var_transform_list[i].second))
21181                return false;
21182          }
21183 
21184          if (!parser_.compile(expression,compiled_expression))
21185          {
21186             return false;
21187          }
21188 
21189          for (std::size_t i = 0; i < var_transform_list.size(); ++i)
21190          {
21191             parser_.remove_replace_symbol(var_transform_list[i].first);
21192          }
21193 
21194          expr_map_[name] = compiled_expression;
21195          return true;
21196       }
21197 
21198       bool add_variable(const std::string& v, T*& t, std::string& new_var)
21199       {
21200          static const unsigned int max_suffix_index = 1000000000;
21201          while (suffix_index_ < max_suffix_index)
21202          {
21203             new_var = generate_name(v);
21204             if (!symbol_used(new_var))
21205             {
21206                symbol_table_.create_variable(new_var,T(0));
21207                t = 0;
21208                t = &symbol_table_.get_variable(new_var)->ref();
21209                return (0 != t);
21210             }
21211             else
21212                ++suffix_index_;
21213          }
21214          return false;
21215       }
21216 
21217       std::string generate_name(const std::string v)
21218       {
21219          //eg: x --> function_compositor_1__x_123
21220          return std::string("function_compositor") + exprtk::details::to_str(id_) + "__" +
21221                 v + "_" +
21222                 exprtk::details::to_str(static_cast<int>(suffix_index_));
21223       }
21224 
21225       unsigned int get_id()
21226       {
21227          static unsigned int base_id = 1;
21228          return ++base_id;
21229       }
21230 
21231       inline bool symbol_used(const std::string& symbol)
21232       {
21233          return (
21234                   symbol_table_.is_variable       (symbol) ||
21235                   symbol_table_.is_stringvar      (symbol) ||
21236                   symbol_table_.is_function       (symbol) ||
21237                   symbol_table_.is_vararg_function(symbol)
21238                 );
21239       }
21240 
21241       inline bool forward(const std::string& name, const std::size_t& arg_count)
21242       {
21243          if (symbol_used(name))
21244             return false;
21245          else
21246          {
21247             switch (arg_count)
21248             {
21249                case 0 : { if (f0p_map_.end() != f0p_map_.find(name)) return false; } break;
21250                case 1 : { if (f1p_map_.end() != f1p_map_.find(name)) return false; } break;
21251                case 2 : { if (f2p_map_.end() != f2p_map_.find(name)) return false; } break;
21252                case 3 : { if (f3p_map_.end() != f3p_map_.find(name)) return false; } break;
21253                case 4 : { if (f4p_map_.end() != f4p_map_.find(name)) return false; } break;
21254                case 5 : { if (f5p_map_.end() != f5p_map_.find(name)) return false; } break;
21255                case 6 : { if (f6p_map_.end() != f6p_map_.find(name)) return false; } break;
21256             }
21257 
21258             switch (arg_count)
21259             {
21260                case 0  : { f0p_map_[name] = func_0param(); return symbol_table_.add_function(name,f0p_map_[name]); }
21261                case 1  : { f1p_map_[name] = func_1param(); return symbol_table_.add_function(name,f1p_map_[name]); }
21262                case 2  : { f2p_map_[name] = func_2param(); return symbol_table_.add_function(name,f2p_map_[name]); }
21263                case 3  : { f3p_map_[name] = func_3param(); return symbol_table_.add_function(name,f3p_map_[name]); }
21264                case 4  : { f4p_map_[name] = func_4param(); return symbol_table_.add_function(name,f4p_map_[name]); }
21265                case 5  : { f5p_map_[name] = func_5param(); return symbol_table_.add_function(name,f5p_map_[name]); }
21266                case 6  : { f6p_map_[name] = func_6param(); return symbol_table_.add_function(name,f6p_map_[name]); }
21267                default : return false;
21268             }
21269          }
21270       }
21271 
21272       template <std::size_t N>
21273       inline void remove(const std::string& name, const std::string (&v)[N])
21274       {
21275          symbol_table_.remove_function(name);
21276          for (std::size_t i = 0; i < N; ++i)
21277          {
21278             symbol_table_.remove_variable(v[i]);
21279          }
21280          remove(name,N);
21281       }
21282 
21283       inline void remove(const std::string& name, const std::size_t& arg_count)
21284       {
21285          typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
21286          if (expr_map_.end() != em_itr)
21287          {
21288             expr_map_.erase(em_itr);
21289          }
21290 
21291          switch (arg_count)
21292          {
21293             case 0 : { if (f0p_map_.end() == f0p_map_.find(name)) return; }
21294             case 1 : { if (f1p_map_.end() == f1p_map_.find(name)) return; }
21295             case 2 : { if (f2p_map_.end() == f2p_map_.find(name)) return; }
21296             case 3 : { if (f3p_map_.end() == f3p_map_.find(name)) return; }
21297             case 4 : { if (f4p_map_.end() == f4p_map_.find(name)) return; }
21298             case 5 : { if (f5p_map_.end() == f5p_map_.find(name)) return; }
21299             case 6 : { if (f6p_map_.end() == f6p_map_.find(name)) return; }
21300          }
21301 
21302          switch (arg_count)
21303          {
21304             case 0 : { f0p_map_.erase(f0p_map_.find(name)); return; }
21305             case 1 : { f1p_map_.erase(f1p_map_.find(name)); return; }
21306             case 2 : { f2p_map_.erase(f2p_map_.find(name)); return; }
21307             case 3 : { f3p_map_.erase(f3p_map_.find(name)); return; }
21308             case 4 : { f4p_map_.erase(f4p_map_.find(name)); return; }
21309             case 5 : { f5p_map_.erase(f5p_map_.find(name)); return; }
21310             case 6 : { f6p_map_.erase(f6p_map_.find(name)); return; }
21311          }
21312       }
21313 
21314    private:
21315 
21316       symbol_table_t symbol_table_;
21317       parser_t parser_;
21318       std::map<std::string,expression_t> expr_map_;
21319       std::map<std::string,func_0param>  f0p_map_;
21320       std::map<std::string,func_1param>  f1p_map_;
21321       std::map<std::string,func_2param>  f2p_map_;
21322       std::map<std::string,func_3param>  f3p_map_;
21323       std::map<std::string,func_4param>  f4p_map_;
21324       std::map<std::string,func_5param>  f5p_map_;
21325       std::map<std::string,func_6param>  f6p_map_;
21326       unsigned int suffix_index_;
21327       unsigned int id_;
21328    };
21329 
21330    template <typename T>
21331    inline bool pgo_primer()
21332    {
21333       static const std::string expression_list[]
21334                                         = {
21335                                              "(y + x)",
21336                                              "2 * (y + x)",
21337                                              "(2 * y + 2 * x)",
21338                                              "(y + x / y) * (x - y / x)",
21339                                              "x / ((x + y) * (x - y)) / y",
21340                                              "1 - ((x * y) + (y / x)) - 3",
21341                                              "sin(2 * x) + cos(pi / y)",
21342                                              "1 - sin(2 * x) + cos(pi / y)",
21343                                              "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
21344                                              "(x^2 / sin(2 * pi / y)) -x / 2",
21345                                              "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
21346                                              "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
21347                                              "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
21348                                              "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
21349                                              "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
21350                                              "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
21351                                              "(yy + xx)",
21352                                              "2 * (yy + xx)",
21353                                              "(2 * yy + 2 * xx)",
21354                                              "(yy + xx / yy) * (xx - yy / xx)",
21355                                              "xx / ((xx + yy) * (xx - yy)) / yy",
21356                                              "1 - ((xx * yy) + (yy / xx)) - 3",
21357                                              "sin(2 * xx) + cos(pi / yy)",
21358                                              "1 - sin(2 * xx) + cos(pi / yy)",
21359                                              "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
21360                                              "(xx^2 / sin(2 * pi / yy)) -xx / 2",
21361                                              "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
21362                                              "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
21363                                              "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
21364                                              "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
21365                                              "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
21366                                              "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
21367                                              "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
21368                                              "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
21369                                              "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
21370                                              "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
21371                                              "(x + 2) * 3", "x + (2 * 3)",
21372                                              "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
21373                                              "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
21374                                              "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
21375                                              "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
21376                                              "2 + (x * (y / 3))", "x + (2 * (3 / y))",
21377                                              "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
21378                                              "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
21379                                              "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
21380                                              "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
21381                                              "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
21382                                              "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
21383                                              "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
21384                                              "((x + (2 * 3)) / y)",
21385                                              "(xx + yy) * zz", "xx + (yy * zz)",
21386                                              "(xx + yy) * 7", "xx + (yy * 7)",
21387                                              "(xx + 7) * yy", "xx + (7 * yy)",
21388                                              "(7 + xx) * yy", "7 + (xx * yy)",
21389                                              "(2 + x) * 3", "2 + (x * 3)",
21390                                              "(2 + 3) * x", "2 + (3 * x)",
21391                                              "(x + 2) * 3", "x + (2 * 3)",
21392                                              "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
21393                                              "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
21394                                              "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
21395                                              "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
21396                                              "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
21397                                              "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
21398                                              "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
21399                                              "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
21400                                              "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
21401                                              "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
21402                                              "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
21403                                              "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
21404                                              "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
21405                                              "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
21406                                              "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
21407                                              "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
21408                                              "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
21409                                              "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
21410                                              "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
21411                                              "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
21412                                              "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
21413                                              "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
21414                                              "((xx + (2 * 3)) / yy)"
21415                                           };
21416       static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
21417 
21418       T  x = T(0);
21419       T  y = T(0);
21420       T  z = T(0);
21421       T  w = T(0);
21422       T xx = T(0);
21423       T yy = T(0);
21424       T zz = T(0);
21425       T ww = T(0);
21426 
21427       exprtk::symbol_table<T> symbol_table;
21428       symbol_table.add_constants();
21429       symbol_table.add_variable( "x", x);
21430       symbol_table.add_variable( "y", y);
21431       symbol_table.add_variable( "z", z);
21432       symbol_table.add_variable( "w", w);
21433       symbol_table.add_variable("xx",xx);
21434       symbol_table.add_variable("yy",yy);
21435       symbol_table.add_variable("zz",zz);
21436       symbol_table.add_variable("ww",ww);
21437 
21438       typedef typename std::deque<exprtk::expression<T> > expr_list_t;
21439       expr_list_t expr_list;
21440 
21441       const std::size_t rounds = 50;
21442 
21443       {
21444          for (std::size_t r = 0; r < rounds; ++r)
21445          {
21446             expr_list.clear();
21447             exprtk::parser<T> parser;
21448             for (std::size_t i = 0; i < expression_list_size; ++i)
21449             {
21450                exprtk::expression<T> expression;
21451                expression.register_symbol_table(symbol_table);
21452                if (!parser.compile(expression_list[i],expression))
21453                {
21454                   return false;
21455                }
21456                expr_list.push_back(expression);
21457             }
21458          }
21459       }
21460 
21461       struct execute
21462       {
21463          static inline T process(T& x, T& y, expression<T>& expression)
21464          {
21465             static const T lower_bound = T(-20);
21466             static const T upper_bound = T(+20);
21467             T delta = T(0.1);
21468             T total = T(0);
21469             for (x = lower_bound; x <= upper_bound; x += delta)
21470             {
21471                for (y = lower_bound; y <= upper_bound; y += delta)
21472                {
21473                   total += expression.value();
21474                }
21475             }
21476             return total;
21477          }
21478       };
21479 
21480       for (std::size_t i = 0; i < expr_list.size(); ++i)
21481       {
21482          execute::process( x, y,  expr_list[i]);
21483          execute::process(xx,yy,  expr_list[i]);
21484       }
21485 
21486       {
21487          for (std::size_t i = 0; i < 10000; ++i)
21488          {
21489             T v = T(123.456 + i);
21490                  if (details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),std::pow(v,T( 1)))) return false;
21491             else if (details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),std::pow(v,T( 2)))) return false;
21492             else if (details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),std::pow(v,T( 3)))) return false;
21493             else if (details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),std::pow(v,T( 4)))) return false;
21494             else if (details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),std::pow(v,T( 5)))) return false;
21495             else if (details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),std::pow(v,T( 6)))) return false;
21496             else if (details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),std::pow(v,T( 7)))) return false;
21497             else if (details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),std::pow(v,T( 8)))) return false;
21498             else if (details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),std::pow(v,T( 9)))) return false;
21499             else if (details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),std::pow(v,T(10)))) return false;
21500             else if (details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),std::pow(v,T(11)))) return false;
21501             else if (details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),std::pow(v,T(12)))) return false;
21502             else if (details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),std::pow(v,T(13)))) return false;
21503             else if (details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),std::pow(v,T(14)))) return false;
21504             else if (details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),std::pow(v,T(15)))) return false;
21505             else if (details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),std::pow(v,T(16)))) return false;
21506             else if (details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),std::pow(v,T(17)))) return false;
21507             else if (details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),std::pow(v,T(18)))) return false;
21508             else if (details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),std::pow(v,T(19)))) return false;
21509             else if (details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),std::pow(v,T(20)))) return false;
21510             else if (details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),std::pow(v,T(21)))) return false;
21511             else if (details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),std::pow(v,T(22)))) return false;
21512             else if (details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),std::pow(v,T(23)))) return false;
21513             else if (details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),std::pow(v,T(24)))) return false;
21514             else if (details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),std::pow(v,T(25)))) return false;
21515             else if (details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),std::pow(v,T(26)))) return false;
21516             else if (details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),std::pow(v,T(27)))) return false;
21517             else if (details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),std::pow(v,T(28)))) return false;
21518             else if (details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),std::pow(v,T(29)))) return false;
21519             else if (details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),std::pow(v,T(30)))) return false;
21520             else if (details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),std::pow(v,T(31)))) return false;
21521             else if (details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),std::pow(v,T(32)))) return false;
21522             else if (details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),std::pow(v,T(33)))) return false;
21523             else if (details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),std::pow(v,T(34)))) return false;
21524             else if (details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),std::pow(v,T(35)))) return false;
21525             else if (details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),std::pow(v,T(36)))) return false;
21526             else if (details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),std::pow(v,T(37)))) return false;
21527             else if (details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),std::pow(v,T(38)))) return false;
21528             else if (details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),std::pow(v,T(39)))) return false;
21529             else if (details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),std::pow(v,T(40)))) return false;
21530             else if (details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),std::pow(v,T(41)))) return false;
21531             else if (details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),std::pow(v,T(42)))) return false;
21532             else if (details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),std::pow(v,T(43)))) return false;
21533             else if (details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),std::pow(v,T(44)))) return false;
21534             else if (details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),std::pow(v,T(45)))) return false;
21535             else if (details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),std::pow(v,T(46)))) return false;
21536             else if (details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),std::pow(v,T(47)))) return false;
21537             else if (details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),std::pow(v,T(48)))) return false;
21538             else if (details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),std::pow(v,T(49)))) return false;
21539             else if (details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),std::pow(v,T(50)))) return false;
21540             else if (details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),std::pow(v,T(51)))) return false;
21541             else if (details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),std::pow(v,T(52)))) return false;
21542             else if (details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),std::pow(v,T(53)))) return false;
21543             else if (details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),std::pow(v,T(54)))) return false;
21544             else if (details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),std::pow(v,T(55)))) return false;
21545             else if (details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),std::pow(v,T(56)))) return false;
21546             else if (details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),std::pow(v,T(57)))) return false;
21547             else if (details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),std::pow(v,T(58)))) return false;
21548             else if (details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),std::pow(v,T(59)))) return false;
21549             else if (details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),std::pow(v,T(60)))) return false;
21550             else
21551                return true;
21552          }
21553       }
21554       return true;
21555    }
21556 
21557 }
21558 
21559 #ifdef WIN32
21560 #   ifndef NOMINMAX
21561 #      define NOMINMAX
21562 #   endif
21563 #   ifndef WIN32_LEAN_AND_MEAN
21564 #      define WIN32_LEAN_AND_MEAN
21565 #   endif
21566 #   include <windows.h>
21567 #else
21568 #   include <sys/time.h>
21569 #   include <sys/types.h>
21570 #endif
21571 
21572 namespace exprtk
21573 {
21574 
21575    class timer
21576    {
21577    public:
21578 
21579       #ifdef WIN32
21580          timer()
21581          : in_use_(false)
21582          {
21583             QueryPerformanceFrequency(&clock_frequency_);
21584          }
21585 
21586          inline void start()
21587          {
21588             in_use_ = true;
21589             QueryPerformanceCounter(&start_time_);
21590          }
21591 
21592          inline void stop()
21593          {
21594             QueryPerformanceCounter(&stop_time_);
21595             in_use_ = false;
21596          }
21597 
21598          inline double time() const
21599          {
21600             return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
21601          }
21602 
21603       #else
21604 
21605          timer()
21606          : in_use_(false)
21607          {
21608             start_time_.tv_sec  = 0;
21609             start_time_.tv_usec = 0;
21610             stop_time_.tv_sec   = 0;
21611             stop_time_.tv_usec  = 0;
21612          }
21613 
21614          inline void start()
21615          {
21616             in_use_ = true;
21617             gettimeofday(&start_time_,0);
21618          }
21619 
21620          inline void stop()
21621          {
21622             gettimeofday(&stop_time_, 0);
21623             in_use_ = false;
21624          }
21625 
21626          inline unsigned long long int usec_time() const
21627          {
21628             if (!in_use_)
21629             {
21630                if (stop_time_.tv_sec >= start_time_.tv_sec)
21631                {
21632                   return 1000000 * (stop_time_.tv_sec  - start_time_.tv_sec ) +
21633                                    (stop_time_.tv_usec - start_time_.tv_usec);
21634                }
21635                else
21636                   return std::numeric_limits<unsigned long long int>::max();
21637             }
21638             else
21639                return std::numeric_limits<unsigned long long int>::max();
21640          }
21641 
21642          inline double time() const
21643          {
21644             return usec_time() * 0.000001;
21645          }
21646 
21647       #endif
21648 
21649          inline bool in_use() const
21650          {
21651             return in_use_;
21652          }
21653 
21654    private:
21655 
21656          bool in_use_;
21657 
21658       #ifdef WIN32
21659          LARGE_INTEGER start_time_;
21660          LARGE_INTEGER stop_time_;
21661          LARGE_INTEGER clock_frequency_;
21662       #else
21663          struct timeval start_time_;
21664          struct timeval stop_time_;
21665       #endif
21666    };
21667 
21668    namespace information
21669    {
21670       static const char* library = "Mathematical Expression Toolkit";
21671       static const char* version = "2.71828182845904523536028747135266249775724709";
21672       static const char* date    = "20140420";
21673 
21674       static inline std::string data()
21675       {
21676          static const std::string info_str = std::string(library) +
21677                                              std::string(" v") + std::string(version) +
21678                                              std::string(" (") + date + std::string(")");
21679          return info_str;
21680       }
21681 
21682    } // namespace information
21683 
21684 } // namespace exprtk
21685 
21686 #endif


labust_mission
Author(s): Filip Mandic
autogenerated on Fri Aug 28 2015 11:23:04