Exprtk Code Coverage Report
Current view: exprtk.hpp Hit Total Coverage
Lines: 13087 17291 75.7 %
Functions: 12496 21636 57.8 %

          Line data    Source code
       1             : /*
       2             :  ******************************************************************
       3             :  *           C++ Mathematical Expression Toolkit Library          *
       4             :  *                                                                *
       5             :  * Author: Arash Partow (1999-2024)                               *
       6             :  * URL: https://www.partow.net/programming/exprtk/index.html      *
       7             :  *                                                                *
       8             :  * Copyright notice:                                              *
       9             :  * Free use of the C++ Mathematical Expression Toolkit Library is *
      10             :  * permitted under the guidelines and in accordance with the most *
      11             :  * current version of the MIT License.                            *
      12             :  * https://www.opensource.org/licenses/MIT                        *
      13             :  * SPDX-License-Identifier: MIT                                   *
      14             :  *                                                                *
      15             :  * Example expressions:                                           *
      16             :  * (00) (y + x / y) * (x - y / x)                                 *
      17             :  * (01) (x^2 / sin(2 * pi / y)) - x / 2                           *
      18             :  * (02) sqrt(1 - (x^2))                                           *
      19             :  * (03) 1 - sin(2 * x) + cos(pi / y)                              *
      20             :  * (04) a * exp(2 * t) + c                                        *
      21             :  * (05) if(((x + 2) == 3) and ((y + 5) <= 9), 1 + w, 2 / z)       *
      22             :  * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x          *
      23             :  * (07) z := x + sin(2 * pi / y)                                  *
      24             :  * (08) u := 2 * (pi * z) / (w := x + cos(y / pi))                *
      25             :  * (09) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)          *
      26             :  * (10) inrange(-2, m, +2) == if(({-2 <= m} and [m <= +2]), 1, 0) *
      27             :  * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1)  *
      28             :  * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *
      29             :  *                                                                *
      30             :  ******************************************************************
      31             : */
      32             : 
      33             : 
      34             : #ifndef INCLUDE_EXPRTK_HPP
      35             : #define INCLUDE_EXPRTK_HPP
      36             : 
      37             : 
      38             : #include <algorithm>
      39             : #include <cassert>
      40             : #include <cctype>
      41             : #include <cmath>
      42             : #include <cstdio>
      43             : #include <cstdlib>
      44             : #include <cstring>
      45             : #include <deque>
      46             : #include <functional>
      47             : #include <iterator>
      48             : #include <limits>
      49             : #include <list>
      50             : #include <map>
      51             : #include <set>
      52             : #include <stack>
      53             : #include <stdexcept>
      54             : #include <string>
      55             : #include <utility>
      56             : #include <vector>
      57             : 
      58             : 
      59             : namespace exprtk
      60             : {
      61             :    #ifdef exprtk_enable_debugging
      62             :      #define exprtk_debug(params) printf params
      63             :    #else
      64             :      #define exprtk_debug(params) (void)0
      65             :    #endif
      66             : 
      67             :    #define exprtk_error_location             \
      68             :    "exprtk.hpp:" + details::to_str(__LINE__) \
      69             : 
      70             :    #if __cplusplus >= 201103L
      71             :       #define exprtk_override override
      72             :       #define exprtk_final    final
      73             :       #define exprtk_delete   = delete
      74             :    #else
      75             :       #define exprtk_override
      76             :       #define exprtk_final
      77             :       #define exprtk_delete
      78             :    #endif
      79             : 
      80             :    #if __cplusplus >= 201603L
      81             :       #define exprtk_fallthrough [[fallthrough]];
      82             :    #else
      83             :       #define exprtk_fallthrough
      84             :    #endif
      85             : 
      86             :    namespace details
      87             :    {
      88             :       typedef char                   char_t;
      89             :       typedef char_t*                char_ptr;
      90             :       typedef char_t const*          char_cptr;
      91             :       typedef unsigned char          uchar_t;
      92             :       typedef uchar_t*               uchar_ptr;
      93             :       typedef uchar_t const*         uchar_cptr;
      94             :       typedef unsigned long long int _uint64_t;
      95             :       typedef long long int          _int64_t;
      96             : 
      97    49678579 :       inline bool is_whitespace(const char_t c)
      98             :       {
      99    46002143 :          return (' '  == c) || ('\n' == c) ||
     100    45996315 :                 ('\r' == c) || ('\t' == c) ||
     101    95680722 :                 ('\b' == c) || ('\v' == c) ||
     102    49678579 :                 ('\f' == c) ;
     103             :       }
     104             : 
     105    15982123 :       inline bool is_operator_char(const char_t c)
     106             :       {
     107    14907277 :          return ('+' == c) || ('-' == c) ||
     108    13352295 :                 ('*' == c) || ('/' == c) ||
     109    12559482 :                 ('^' == c) || ('<' == c) ||
     110    12539338 :                 ('>' == c) || ('=' == c) ||
     111    11998035 :                 (',' == c) || ('!' == c) ||
     112     8977512 :                 ('(' == c) || (')' == c) ||
     113     5873106 :                 ('[' == c) || (']' == c) ||
     114     5730731 :                 ('{' == c) || ('}' == c) ||
     115     5686659 :                 ('%' == c) || (':' == c) ||
     116     5553912 :                 ('?' == c) || ('&' == c) ||
     117    30889400 :                 ('|' == c) || (';' == c) ;
     118             :       }
     119             : 
     120    34242041 :       inline bool is_letter(const char_t c)
     121             :       {
     122    34824690 :          return (('a' <= c) && (c <= 'z')) ||
     123    34824690 :                 (('A' <= c) && (c <= 'Z')) ;
     124             :       }
     125             : 
     126    24011547 :       inline bool is_digit(const char_t c)
     127             :       {
     128    24011547 :          return ('0' <= c) && (c <= '9');
     129             :       }
     130             : 
     131    11834450 :       inline bool is_letter_or_digit(const char_t c)
     132             :       {
     133    11834450 :          return is_letter(c) || is_digit(c);
     134             :       }
     135             : 
     136    34012410 :       inline bool is_left_bracket(const char_t c)
     137             :       {
     138    34012410 :          return ('(' == c) || ('[' == c) || ('{' == c);
     139             :       }
     140             : 
     141    38015437 :       inline bool is_right_bracket(const char_t c)
     142             :       {
     143    38015437 :          return (')' == c) || (']' == c) || ('}' == c);
     144             :       }
     145             : 
     146    12484572 :       inline bool is_bracket(const char_t c)
     147             :       {
     148    12484572 :          return is_left_bracket(c) || is_right_bracket(c);
     149             :       }
     150             : 
     151        2622 :       inline bool is_sign(const char_t c)
     152             :       {
     153        2622 :          return ('+' == c) || ('-' == c);
     154             :       }
     155             : 
     156             :       inline bool is_invalid(const char_t c)
     157             :       {
     158             :          return !is_whitespace   (c) &&
     159             :                 !is_operator_char(c) &&
     160             :                 !is_letter       (c) &&
     161             :                 !is_digit        (c) &&
     162             :                 ('.'  != c)          &&
     163             :                 ('_'  != c)          &&
     164             :                 ('$'  != c)          &&
     165             :                 ('~'  != c)          &&
     166             :                 ('\'' != c);
     167             :       }
     168             : 
     169      386183 :       inline bool is_valid_string_char(const char_t c)
     170             :       {
     171      386483 :          return std::isprint(static_cast<uchar_t>(c)) ||
     172      386483 :                 is_whitespace(c);
     173             :       }
     174             : 
     175             :       #ifndef exprtk_disable_caseinsensitivity
     176          24 :       inline void case_normalise(std::string& s)
     177             :       {
     178          56 :          for (std::size_t i = 0; i < s.size(); ++i)
     179             :          {
     180          32 :             s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
     181             :          }
     182          24 :       }
     183             : 
     184        8490 :       inline bool imatch(const char_t c1, const char_t c2)
     185             :       {
     186        8490 :          return std::tolower(c1) == std::tolower(c2);
     187             :       }
     188             : 
     189    63175754 :       inline bool imatch(const std::string& s1, const std::string& s2)
     190             :       {
     191    63175754 :          if (s1.size() == s2.size())
     192             :          {
     193     6839715 :             for (std::size_t i = 0; i < s1.size(); ++i)
     194             :             {
     195     6151685 :                if (std::tolower(s1[i]) != std::tolower(s2[i]))
     196             :                {
     197     4702457 :                   return false;
     198             :                }
     199             :             }
     200             : 
     201      688030 :             return true;
     202             :          }
     203             : 
     204    57785267 :          return false;
     205             :       }
     206             : 
     207             :       struct ilesscompare
     208             :       {
     209   173015998 :          inline bool operator() (const std::string& s1, const std::string& s2) const
     210             :          {
     211   173015998 :             const std::size_t length = std::min(s1.size(),s2.size());
     212             : 
     213   265342376 :             for (std::size_t i = 0; i < length; ++i)
     214             :             {
     215   222302178 :                const char_t c1 = static_cast<char_t>(std::tolower(s1[i]));
     216   222302178 :                const char_t c2 = static_cast<char_t>(std::tolower(s2[i]));
     217             : 
     218   222302178 :                if (c1 < c2)
     219    71663625 :                   return true;
     220   150638553 :                else if (c2 < c1)
     221    58312175 :                   return false;
     222             :             }
     223             : 
     224    43040198 :             return s1.size() < s2.size();
     225             :          }
     226             :       };
     227             : 
     228             :       #else
     229             :       inline void case_normalise(std::string&)
     230             :       {}
     231             : 
     232             :       inline bool imatch(const char_t c1, const char_t c2)
     233             :       {
     234             :          return c1 == c2;
     235             :       }
     236             : 
     237             :       inline bool imatch(const std::string& s1, const std::string& s2)
     238             :       {
     239             :          return s1 == s2;
     240             :       }
     241             : 
     242             :       struct ilesscompare
     243             :       {
     244             :          inline bool operator() (const std::string& s1, const std::string& s2) const
     245             :          {
     246             :             return s1 < s2;
     247             :          }
     248             :       };
     249             :       #endif
     250             : 
     251     2144061 :       inline bool is_valid_sf_symbol(const std::string& symbol)
     252             :       {
     253             :          // Special function: $f12 or $F34
     254     2144061 :          return (4 == symbol.size())  &&
     255       11692 :                 ('$' == symbol[0])    &&
     256        8490 :                 imatch('f',symbol[1]) &&
     257     2155753 :                 is_digit(symbol[2])   &&
     258     2148306 :                 is_digit(symbol[3]);
     259             :       }
     260             : 
     261         727 :       inline const char_t& front(const std::string& s)
     262             :       {
     263         727 :          return s[0];
     264             :       }
     265             : 
     266           0 :       inline const char_t& back(const std::string& s)
     267             :       {
     268           0 :          return s[s.size() - 1];
     269             :       }
     270             : 
     271       43680 :       inline std::string to_str(int i)
     272             :       {
     273       43680 :          if (0 == i)
     274           0 :             return std::string("0");
     275             : 
     276       43680 :          std::string result;
     277             : 
     278       43680 :          const int sign = (i < 0) ? -1 : 1;
     279             : 
     280      262080 :          for ( ; i; i /= 10)
     281             :          {
     282      218400 :             result += '0' + static_cast<char_t>(sign * (i % 10));
     283             :          }
     284             : 
     285       43680 :          if (sign < 0)
     286             :          {
     287           0 :             result += '-';
     288             :          }
     289             : 
     290       43680 :          std::reverse(result.begin(), result.end());
     291             : 
     292       43680 :          return result;
     293       43680 :       }
     294             : 
     295           0 :       inline std::string to_str(std::size_t i)
     296             :       {
     297           0 :          return to_str(static_cast<int>(i));
     298             :       }
     299             : 
     300        8400 :       inline bool is_hex_digit(const uchar_t digit)
     301             :       {
     302        8400 :          return (('0' <= digit) && (digit <= '9')) ||
     303       16800 :                 (('A' <= digit) && (digit <= 'F')) ||
     304        8400 :                 (('a' <= digit) && (digit <= 'f')) ;
     305             :       }
     306             : 
     307        4200 :       inline uchar_t hex_to_bin(uchar_t h)
     308             :       {
     309        4200 :          if (('0' <= h) && (h <= '9'))
     310        4200 :             return (h - '0');
     311             :          else
     312           0 :             return static_cast<uchar_t>(std::toupper(h) - 'A');
     313             :       }
     314             : 
     315             :       template <typename Iterator>
     316        3050 :       inline bool parse_hex(Iterator& itr, Iterator end,
     317             :                             char_t& result)
     318             :       {
     319        3050 :          if (
     320        6100 :               (end ==  (itr    ))               ||
     321        6100 :               (end ==  (itr + 1))               ||
     322        5900 :               (end ==  (itr + 2))               ||
     323        2850 :               (end ==  (itr + 3))               ||
     324        2850 :               ('0' != *(itr    ))               ||
     325        2100 :               ('X' != std::toupper(*(itr + 1))) ||
     326        8200 :               (!is_hex_digit(*(itr + 2)))       ||
     327        5150 :               (!is_hex_digit(*(itr + 3)))
     328             :             )
     329             :          {
     330         950 :             return false;
     331             :          }
     332             : 
     333        2100 :          result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
     334        2100 :                   hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
     335             : 
     336        2100 :          return true;
     337             :       }
     338             : 
     339        1350 :       inline bool cleanup_escapes(std::string& s)
     340             :       {
     341             :          typedef std::string::iterator str_itr_t;
     342             : 
     343        1350 :          str_itr_t itr1 = s.begin();
     344        1350 :          str_itr_t itr2 = s.begin();
     345        1350 :          str_itr_t end  = s.end  ();
     346             : 
     347        1350 :          std::size_t removal_count  = 0;
     348             : 
     349        7500 :          while (end != itr1)
     350             :          {
     351        6150 :             if ('\\' == (*itr1))
     352             :             {
     353        3050 :                if (end == ++itr1)
     354             :                {
     355           0 :                   return false;
     356             :                }
     357        3050 :                else if (parse_hex(itr1, end, *itr2))
     358             :                {
     359        2100 :                   itr1 += 4;
     360        2100 :                   itr2 += 1;
     361        2100 :                   removal_count += 4;
     362             :                }
     363         950 :                else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; }
     364         950 :                else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; }
     365         950 :                else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; }
     366         950 :                else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; }
     367         650 :                else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; }
     368         650 :                else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; }
     369         650 :                else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; }
     370         650 :                else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; }
     371             :                else
     372             :                {
     373         650 :                   (*itr2++) = (*itr1++);
     374         650 :                   ++removal_count;
     375             :                }
     376             : 
     377        3050 :                continue;
     378             :             }
     379             :             else
     380        3100 :                (*itr2++) = (*itr1++);
     381             :          }
     382             : 
     383        1350 :          if ((removal_count > s.size()) || (0 == removal_count))
     384           0 :             return false;
     385             : 
     386        1350 :          s.resize(s.size() - removal_count);
     387             : 
     388        1350 :          return true;
     389             :       }
     390             : 
     391             :       class build_string
     392             :       {
     393             :       public:
     394             : 
     395           0 :          explicit build_string(const std::size_t& initial_size = 64)
     396      396166 :          {
     397      396166 :             data_.reserve(initial_size);
     398      396166 :          }
     399             : 
     400      853493 :          inline build_string& operator << (const std::string& s)
     401             :          {
     402      853493 :             data_ += s;
     403      853493 :             return (*this);
     404             :          }
     405             : 
     406     1249659 :          inline build_string& operator << (char_cptr s)
     407             :          {
     408     1249659 :             data_ += std::string(s);
     409     1249659 :             return (*this);
     410             :          }
     411             : 
     412      396166 :          inline operator std::string () const
     413             :          {
     414      396166 :             return data_;
     415             :          }
     416             : 
     417             :          inline std::string as_string() const
     418             :          {
     419             :             return data_;
     420             :          }
     421             : 
     422             :       private:
     423             : 
     424             :          std::string data_;
     425             :       };
     426             : 
     427             :       static const std::string reserved_words[] =
     428             :       {
     429             :          "assert",  "break", "case", "continue", "const",  "default",
     430             :          "false", "for", "if", "else", "ilike", "in", "like",  "and",
     431             :          "nand",  "nor",  "not",  "null",  "or",  "repeat", "return",
     432             :          "shl",  "shr",  "swap",  "switch",  "true",  "until", "var",
     433             :          "while", "xnor", "xor", "&", "|"
     434             :       };
     435             : 
     436             :       static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
     437             : 
     438             :       static const std::string reserved_symbols[] =
     439             :       {
     440             :          "abs", "acos",  "acosh", "and",  "asin", "asinh",  "assert",
     441             :          "atan", "atanh",  "atan2", "avg",  "break", "case",  "ceil",
     442             :          "clamp", "continue", "const",  "cos", "cosh", "cot",  "csc",
     443             :          "default",  "deg2grad", "deg2rad",  "equal", "erf",  "erfc",
     444             :          "exp", "expm1", "false", "floor", "for", "frac", "grad2deg",
     445             :          "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
     446             :          "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
     447             :          "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
     448             :          "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
     449             :          "repeat", "return", "root", "round", "roundn", "sec", "sgn",
     450             :          "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum",  "swap",
     451             :          "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
     452             :          "while", "xnor", "xor", "&", "|"
     453             :       };
     454             : 
     455             :       static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
     456             : 
     457             :       static const std::string base_function_list[] =
     458             :       {
     459             :          "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
     460             :          "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
     461             :          "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
     462             :          "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
     463             :          "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
     464             :          "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
     465             :          "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
     466             :          "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
     467             :          "rad2deg", "grad2deg"
     468             :       };
     469             : 
     470             :       static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
     471             : 
     472             :       static const std::string logic_ops_list[] =
     473             :       {
     474             :          "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
     475             :       };
     476             : 
     477             :       static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
     478             : 
     479             :       static const std::string cntrl_struct_list[] =
     480             :       {
     481             :          "if", "switch", "for", "while", "repeat", "return"
     482             :       };
     483             : 
     484             :       static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
     485             : 
     486             :       static const std::string arithmetic_ops_list[] =
     487             :       {
     488             :          "+", "-", "*", "/", "%", "^"
     489             :       };
     490             : 
     491             :       static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
     492             : 
     493             :       static const std::string assignment_ops_list[] =
     494             :       {
     495             :          ":=", "+=", "-=",
     496             :          "*=", "/=", "%="
     497             :       };
     498             : 
     499             :       static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
     500             : 
     501             :       static const std::string inequality_ops_list[] =
     502             :       {
     503             :          "<",  "<=", "==",
     504             :          "=",  "!=", "<>",
     505             :          ">=",  ">"
     506             :       };
     507             : 
     508             :       static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
     509             : 
     510        3200 :       inline bool is_reserved_word(const std::string& symbol)
     511             :       {
     512      108800 :          for (std::size_t i = 0; i < reserved_words_size; ++i)
     513             :          {
     514      105600 :             if (imatch(symbol, reserved_words[i]))
     515             :             {
     516           0 :                return true;
     517             :             }
     518             :          }
     519             : 
     520        3200 :          return false;
     521             :       }
     522             : 
     523       98139 :       inline bool is_reserved_symbol(const std::string& symbol)
     524             :       {
     525     8832464 :          for (std::size_t i = 0; i < reserved_symbols_size; ++i)
     526             :          {
     527     8734348 :             if (imatch(symbol, reserved_symbols[i]))
     528             :             {
     529          23 :                return true;
     530             :             }
     531             :          }
     532             : 
     533       98116 :          return false;
     534             :       }
     535             : 
     536           0 :       inline bool is_base_function(const std::string& function_name)
     537             :       {
     538           0 :          for (std::size_t i = 0; i < base_function_list_size; ++i)
     539             :          {
     540           0 :             if (imatch(function_name, base_function_list[i]))
     541             :             {
     542           0 :                return true;
     543             :             }
     544             :          }
     545             : 
     546           0 :          return false;
     547             :       }
     548             : 
     549             :       inline bool is_control_struct(const std::string& cntrl_strct)
     550             :       {
     551             :          for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
     552             :          {
     553             :             if (imatch(cntrl_strct, cntrl_struct_list[i]))
     554             :             {
     555             :                return true;
     556             :             }
     557             :          }
     558             : 
     559             :          return false;
     560             :       }
     561             : 
     562             :       inline bool is_logic_opr(const std::string& lgc_opr)
     563             :       {
     564             :          for (std::size_t i = 0; i < logic_ops_list_size; ++i)
     565             :          {
     566             :             if (imatch(lgc_opr, logic_ops_list[i]))
     567             :             {
     568             :                return true;
     569             :             }
     570             :          }
     571             : 
     572             :          return false;
     573             :       }
     574             : 
     575             :       struct cs_match
     576             :       {
     577       16290 :          static inline bool cmp(const char_t c0, const char_t c1)
     578             :          {
     579       16290 :             return (c0 == c1);
     580             :          }
     581             :       };
     582             : 
     583             :       struct cis_match
     584             :       {
     585       17340 :          static inline bool cmp(const char_t c0, const char_t c1)
     586             :          {
     587       17340 :             return (std::tolower(c0) == std::tolower(c1));
     588             :          }
     589             :       };
     590             : 
     591             :       template <typename Iterator, typename Compare>
     592        6315 :       inline bool match_impl(const Iterator pattern_begin,
     593             :                              const Iterator pattern_end  ,
     594             :                              const Iterator data_begin   ,
     595             :                              const Iterator data_end     ,
     596             :                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
     597             :                              const typename std::iterator_traits<Iterator>::value_type& exactly_one )
     598             :       {
     599             :          typedef typename std::iterator_traits<Iterator>::value_type type;
     600             : 
     601        6315 :          const Iterator null_itr(0);
     602             : 
     603        6315 :          Iterator p_itr  = pattern_begin;
     604        6315 :          Iterator d_itr  = data_begin;
     605        6315 :          Iterator np_itr = null_itr;
     606        6315 :          Iterator nd_itr = null_itr;
     607             : 
     608       26020 :          for ( ; ; )
     609             :          {
     610       32335 :             if (p_itr != pattern_end)
     611             :             {
     612       25970 :                const type c = *(p_itr);
     613             : 
     614       25970 :                if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c)))
     615             :                {
     616       20800 :                   ++d_itr;
     617       20800 :                   ++p_itr;
     618       20800 :                   continue;
     619             :                }
     620        5170 :                else if (zero_or_more == c)
     621             :                {
     622       10280 :                   while ((pattern_end != p_itr) && (zero_or_more == *(p_itr)))
     623             :                   {
     624        5470 :                      ++p_itr;
     625             :                   }
     626             : 
     627        4810 :                   const type d = *(p_itr);
     628             : 
     629        9420 :                   while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d)))
     630             :                   {
     631        4610 :                      ++d_itr;
     632             :                   }
     633             : 
     634             :                   // set backtrack iterators
     635        4810 :                   np_itr = p_itr - 1;
     636        4810 :                   nd_itr = d_itr + 1;
     637             : 
     638        4810 :                   continue;
     639        4810 :                }
     640             :             }
     641        6365 :             else if (data_end == d_itr)
     642        6205 :                break;
     643             : 
     644         520 :             if ((data_end == d_itr) || (null_itr == nd_itr))
     645         110 :                 return false;
     646             : 
     647         410 :             p_itr = np_itr;
     648         410 :             d_itr = nd_itr;
     649             :          }
     650             : 
     651        6205 :          return true;
     652             :       }
     653             : 
     654        3070 :       inline bool wc_match(const std::string& wild_card,
     655             :                            const std::string& str)
     656             :       {
     657             :          return match_impl<char_cptr,cs_match>
     658        6140 :                 (
     659             :                    wild_card.data(),
     660        3070 :                    wild_card.data() + wild_card.size(),
     661             :                    str.data(),
     662        3070 :                    str.data() + str.size(),
     663        6140 :                    '*', '?'
     664        3070 :                 );
     665             :       }
     666             : 
     667        3245 :       inline bool wc_imatch(const std::string& wild_card,
     668             :                             const std::string& str)
     669             :       {
     670             :          return match_impl<char_cptr,cis_match>
     671        6490 :                 (
     672             :                    wild_card.data(),
     673        3245 :                    wild_card.data() + wild_card.size(),
     674             :                    str.data(),
     675        3245 :                    str.data() + str.size(),
     676        6490 :                    '*', '?'
     677        3245 :                 );
     678             :       }
     679             : 
     680        5662 :       inline bool sequence_match(const std::string& pattern,
     681             :                                  const std::string& str,
     682             :                                  std::size_t&       diff_index,
     683             :                                  char_t&            diff_value)
     684             :       {
     685        5662 :          if (str.empty())
     686             :          {
     687          15 :             return ("Z" == pattern);
     688             :          }
     689        5647 :          else if ('*' == pattern[0])
     690           0 :             return false;
     691             : 
     692             :          typedef std::string::const_iterator itr_t;
     693             : 
     694        5647 :          itr_t p_itr = pattern.begin();
     695        5647 :          itr_t s_itr = str    .begin();
     696             : 
     697        5647 :          const itr_t p_end = pattern.end();
     698        5647 :          const itr_t s_end = str    .end();
     699             : 
     700       17462 :          while ((s_end != s_itr) && (p_end != p_itr))
     701             :          {
     702       12376 :             if ('*' == (*p_itr))
     703             :             {
     704          30 :                const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1)));
     705             : 
     706          30 :                if ('*' == target)
     707             :                {
     708           0 :                   diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
     709           0 :                   diff_value = static_cast<char_t>(std::toupper(*p_itr));
     710             : 
     711           0 :                   return false;
     712             :                }
     713             :                else
     714          30 :                   ++p_itr;
     715             : 
     716          86 :                while (s_itr != s_end)
     717             :                {
     718          64 :                   if (target != std::toupper(*s_itr))
     719           8 :                      break;
     720             :                   else
     721          56 :                      ++s_itr;
     722             :                }
     723             : 
     724          30 :                continue;
     725          30 :             }
     726       12346 :             else if (
     727       24692 :                       ('?' != *p_itr) &&
     728       12346 :                       std::toupper(*p_itr) != std::toupper(*s_itr)
     729             :                     )
     730             :             {
     731         561 :                diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
     732         561 :                diff_value = static_cast<char_t>(std::toupper(*p_itr));
     733             : 
     734         561 :                return false;
     735             :             }
     736             : 
     737       11785 :             ++p_itr;
     738       11785 :             ++s_itr;
     739             :          }
     740             : 
     741             :          return (
     742        8716 :                   (s_end == s_itr) &&
     743             :                   (
     744        3603 :                     (p_end ==  p_itr) ||
     745          27 :                     ('*'   == *p_itr)
     746             :                   )
     747        5086 :                 );
     748             :       }
     749             : 
     750             :       template<typename T>
     751             :       struct set_zero_value_impl
     752             :       {
     753             :          static inline void process(T* base_ptr, const std::size_t size)
     754             :          {
     755             :             const T zero = T(0);
     756             :             for (std::size_t i = 0; i < size; ++i)
     757             :             {
     758             :                base_ptr[i] = zero;
     759             :             }
     760             :          }
     761             :       };
     762             : 
     763             :       #define pod_set_zero_value(T)                                      \
     764             :       template <>                                                        \
     765             :       struct set_zero_value_impl<T>                                      \
     766             :       {                                                                  \
     767             :          static inline void process(T* base_ptr, const std::size_t size) \
     768             :          { std::memset(base_ptr, 0x00, size * sizeof(T)); }              \
     769             :       };                                                                 \
     770             : 
     771             :       pod_set_zero_value(float      )
     772        2011 :       pod_set_zero_value(double     )
     773             :       pod_set_zero_value(long double)
     774             : 
     775             :       #ifdef pod_set_zero_value
     776             :       #undef pod_set_zero_value
     777             :       #endif
     778             : 
     779             :       template<typename T>
     780        2011 :       inline void set_zero_value(T* data, const std::size_t size)
     781             :       {
     782        2011 :          set_zero_value_impl<T>::process(data,size);
     783        2011 :       }
     784             : 
     785             :       template<typename T>
     786             :       inline void set_zero_value(std::vector<T>& v)
     787             :       {
     788             :          set_zero_value(v.data(),v.size());
     789             :       }
     790             : 
     791             :       static const double pow10[] =
     792             :       {
     793             :          1.0,
     794             :          1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
     795             :          1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
     796             :          1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
     797             :          1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
     798             :       };
     799             : 
     800             :       static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
     801             : 
     802             :       namespace numeric
     803             :       {
     804             :          namespace constant
     805             :          {
     806             :             static const double e       =  2.71828182845904523536028747135266249775724709369996;
     807             :             static const double pi      =  3.14159265358979323846264338327950288419716939937510;
     808             :             static const double pi_2    =  1.57079632679489661923132169163975144209858469968755;
     809             :             static const double pi_4    =  0.78539816339744830961566084581987572104929234984378;
     810             :             static const double pi_180  =  0.01745329251994329576923690768488612713442871888542;
     811             :             static const double _1_pi   =  0.31830988618379067153776752674502872406891929148091;
     812             :             static const double _2_pi   =  0.63661977236758134307553505349005744813783858296183;
     813             :             static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
     814             :             static const double log2    =  0.69314718055994530941723212145817656807550013436026;
     815             :             static const double sqrt2   =  1.41421356237309504880168872420969807856967187537695;
     816             :          }
     817             : 
     818             :          namespace details
     819             :          {
     820             :             struct unknown_type_tag { unknown_type_tag() {} };
     821   317158419 :             struct real_type_tag    { real_type_tag   () {} };
     822             :             struct int_type_tag     { int_type_tag    () {} };
     823             : 
     824             :             template <typename T>
     825             :             struct number_type
     826             :             {
     827             :                typedef unknown_type_tag type;
     828             :                number_type() {}
     829             :             };
     830             : 
     831             :             #define exprtk_register_real_type_tag(T)          \
     832             :             template <> struct number_type<T>                 \
     833             :             { typedef real_type_tag type; number_type() {} }; \
     834             : 
     835             :             #define exprtk_register_int_type_tag(T)           \
     836             :             template <> struct number_type<T>                 \
     837             :             { typedef int_type_tag type; number_type() {} };  \
     838             : 
     839             :             exprtk_register_real_type_tag(float      )
     840             :             exprtk_register_real_type_tag(double     )
     841             :             exprtk_register_real_type_tag(long double)
     842             : 
     843             :             exprtk_register_int_type_tag(short         )
     844             :             exprtk_register_int_type_tag(int           )
     845             :             exprtk_register_int_type_tag(_int64_t      )
     846             :             exprtk_register_int_type_tag(unsigned short)
     847             :             exprtk_register_int_type_tag(unsigned int  )
     848             :             exprtk_register_int_type_tag(_uint64_t     )
     849             : 
     850             :             #undef exprtk_register_real_type_tag
     851             :             #undef exprtk_register_int_type_tag
     852             : 
     853             :             template <typename T>
     854             :             struct epsilon_type {};
     855             : 
     856             :             #define exprtk_define_epsilon_type(Type, Epsilon)      \
     857             :             template <> struct epsilon_type<Type>                  \
     858             :             {                                                      \
     859             :                static inline Type value()                          \
     860             :                {                                                   \
     861             :                   const Type epsilon = static_cast<Type>(Epsilon); \
     862             :                   return epsilon;                                  \
     863             :                }                                                   \
     864             :             };                                                     \
     865             : 
     866             :             exprtk_define_epsilon_type(float      , 0.00000100000f)
     867      267144 :             exprtk_define_epsilon_type(double     , 0.000000000100)
     868             :             exprtk_define_epsilon_type(long double, 0.000000000001)
     869             : 
     870             :             #undef exprtk_define_epsilon_type
     871             : 
     872             :             template <typename T>
     873         195 :             inline bool is_nan_impl(const T v, real_type_tag)
     874             :             {
     875         195 :                return std::not_equal_to<T>()(v,v);
     876             :             }
     877             : 
     878             :             template <typename T>
     879      112698 :             inline int to_int32_impl(const T v, real_type_tag)
     880             :             {
     881      112698 :                return static_cast<int>(v);
     882             :             }
     883             : 
     884             :             template <typename T>
     885       57228 :             inline _int64_t to_int64_impl(const T v, real_type_tag)
     886             :             {
     887       57228 :                return static_cast<_int64_t>(v);
     888             :             }
     889             : 
     890             :             template <typename T>
     891    32864168 :             inline _uint64_t to_uint64_impl(const T v, real_type_tag)
     892             :             {
     893    32864168 :                return static_cast<_uint64_t>(v);
     894             :             }
     895             : 
     896             :             template <typename T>
     897        1570 :             inline bool is_true_impl(const T v)
     898             :             {
     899        1570 :                return std::not_equal_to<T>()(T(0),v);
     900             :             }
     901             : 
     902             :             template <typename T>
     903        2330 :             inline bool is_false_impl(const T v)
     904             :             {
     905        2330 :                return std::equal_to<T>()(T(0),v);
     906             :             }
     907             : 
     908             :             template <typename T>
     909    22979206 :             inline T abs_impl(const T v, real_type_tag)
     910             :             {
     911    22979206 :                return ((v < T(0)) ? -v : v);
     912             :             }
     913             : 
     914             :             template <typename T>
     915             :             inline T min_impl(const T v0, const T v1, real_type_tag)
     916             :             {
     917             :                return std::min<T>(v0,v1);
     918             :             }
     919             : 
     920             :             template <typename T>
     921             :             inline T max_impl(const T v0, const T v1, real_type_tag)
     922             :             {
     923             :                return std::max<T>(v0,v1);
     924             :             }
     925             : 
     926             :             template <typename T>
     927      267123 :             inline T equal_impl(const T v0, const T v1, real_type_tag)
     928             :             {
     929      267123 :                const T epsilon = epsilon_type<T>::value();
     930      267123 :                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);
     931             :             }
     932             : 
     933             :             inline float equal_impl(const float v0, const float v1, real_type_tag)
     934             :             {
     935             :                const float epsilon = epsilon_type<float>::value();
     936             :                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;
     937             :             }
     938             : 
     939             :             template <typename T>
     940             :             inline T equal_impl(const T v0, const T v1, int_type_tag)
     941             :             {
     942             :                return (v0 == v1) ? 1 : 0;
     943             :             }
     944             : 
     945             :             template <typename T>
     946           0 :             inline T expm1_impl(const T v, real_type_tag)
     947             :             {
     948             :                // return std::expm1<T>(v);
     949           0 :                if (abs_impl(v,real_type_tag()) < T(0.00001))
     950           0 :                   return v + (T(0.5) * v * v);
     951             :                else
     952           0 :                   return std::exp(v) - T(1);
     953             :             }
     954             : 
     955             :             template <typename T>
     956             :             inline T expm1_impl(const T v, int_type_tag)
     957             :             {
     958             :                return T(std::exp<double>(v)) - T(1);
     959             :             }
     960             : 
     961             :             template <typename T>
     962          20 :             inline T nequal_impl(const T v0, const T v1, real_type_tag)
     963             :             {
     964             :                typedef real_type_tag rtg;
     965          20 :                const T epsilon = epsilon_type<T>::value();
     966          20 :                return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
     967             :             }
     968             : 
     969             :             inline float nequal_impl(const float v0, const float v1, real_type_tag)
     970             :             {
     971             :                typedef real_type_tag rtg;
     972             :                const float epsilon = epsilon_type<float>::value();
     973             :                return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
     974             :             }
     975             : 
     976             :             template <typename T>
     977             :             inline T nequal_impl(const T v0, const T v1, int_type_tag)
     978             :             {
     979             :                return (v0 != v1) ? 1 : 0;
     980             :             }
     981             : 
     982             :             template <typename T>
     983      118489 :             inline T modulus_impl(const T v0, const T v1, real_type_tag)
     984             :             {
     985      118489 :                return std::fmod(v0,v1);
     986             :             }
     987             : 
     988             :             template <typename T>
     989             :             inline T modulus_impl(const T v0, const T v1, int_type_tag)
     990             :             {
     991             :                return v0 % v1;
     992             :             }
     993             : 
     994             :             template <typename T>
     995        7664 :             inline T pow_impl(const T v0, const T v1, real_type_tag)
     996             :             {
     997        7664 :                return std::pow(v0,v1);
     998             :             }
     999             : 
    1000             :             template <typename T>
    1001             :             inline T pow_impl(const T v0, const T v1, int_type_tag)
    1002             :             {
    1003             :                return std::pow(static_cast<double>(v0),static_cast<double>(v1));
    1004             :             }
    1005             : 
    1006             :             template <typename T>
    1007           0 :             inline T logn_impl(const T v0, const T v1, real_type_tag)
    1008             :             {
    1009           0 :                return std::log(v0) / std::log(v1);
    1010             :             }
    1011             : 
    1012             :             template <typename T>
    1013             :             inline T logn_impl(const T v0, const T v1, int_type_tag)
    1014             :             {
    1015             :                return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
    1016             :             }
    1017             : 
    1018             :             template <typename T>
    1019           0 :             inline T log1p_impl(const T v, real_type_tag)
    1020             :             {
    1021           0 :                if (v > T(-1))
    1022             :                {
    1023           0 :                   if (abs_impl(v,real_type_tag()) > T(0.0001))
    1024             :                   {
    1025           0 :                      return std::log(T(1) + v);
    1026             :                   }
    1027             :                   else
    1028           0 :                      return (T(-0.5) * v + T(1)) * v;
    1029             :                }
    1030             : 
    1031           0 :                return std::numeric_limits<T>::quiet_NaN();
    1032             :             }
    1033             : 
    1034             :             template <typename T>
    1035             :             inline T log1p_impl(const T v, int_type_tag)
    1036             :             {
    1037             :                if (v > T(-1))
    1038             :                {
    1039             :                   return std::log(T(1) + v);
    1040             :                }
    1041             : 
    1042             :                return std::numeric_limits<T>::quiet_NaN();
    1043             :             }
    1044             : 
    1045             :             template <typename T>
    1046         160 :             inline T root_impl(const T v0, const T v1, real_type_tag)
    1047             :             {
    1048         160 :                if (v1 < T(0))
    1049           0 :                   return std::numeric_limits<T>::quiet_NaN();
    1050             : 
    1051         160 :                const std::size_t n = static_cast<std::size_t>(v1);
    1052             : 
    1053         160 :                if ((v0 < T(0)) && (0 == (n % 2)))
    1054           0 :                   return std::numeric_limits<T>::quiet_NaN();
    1055             : 
    1056         160 :                return std::pow(v0, T(1) / n);
    1057             :             }
    1058             : 
    1059             :             template <typename T>
    1060             :             inline T root_impl(const T v0, const T v1, int_type_tag)
    1061             :             {
    1062             :                return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
    1063             :             }
    1064             : 
    1065             :             template <typename T>
    1066          60 :             inline T round_impl(const T v, real_type_tag)
    1067             :             {
    1068          60 :                return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
    1069             :             }
    1070             : 
    1071             :             template <typename T>
    1072         120 :             inline T roundn_impl(const T v0, const T v1, real_type_tag)
    1073             :             {
    1074         120 :                const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1))));
    1075         120 :                const T p10 = T(pow10[index]);
    1076             : 
    1077         120 :                if (v0 < T(0))
    1078           0 :                   return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
    1079             :                else
    1080         120 :                   return T(std::floor((v0 * p10) + T(0.5)) / p10);
    1081             :             }
    1082             : 
    1083             :             template <typename T>
    1084             :             inline T roundn_impl(const T v0, const T, int_type_tag)
    1085             :             {
    1086             :                return v0;
    1087             :             }
    1088             : 
    1089             :             template <typename T>
    1090          30 :             inline T hypot_impl(const T v0, const T v1, real_type_tag)
    1091             :             {
    1092          30 :                return std::sqrt((v0 * v0) + (v1 * v1));
    1093             :             }
    1094             : 
    1095             :             template <typename T>
    1096             :             inline T hypot_impl(const T v0, const T v1, int_type_tag)
    1097             :             {
    1098             :                return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
    1099             :             }
    1100             : 
    1101             :             template <typename T>
    1102           0 :             inline T atan2_impl(const T v0, const T v1, real_type_tag)
    1103             :             {
    1104           0 :                return std::atan2(v0,v1);
    1105             :             }
    1106             : 
    1107             :             template <typename T>
    1108             :             inline T atan2_impl(const T, const T, int_type_tag)
    1109             :             {
    1110             :                return 0;
    1111             :             }
    1112             : 
    1113             :             template <typename T>
    1114           0 :             inline T shr_impl(const T v0, const T v1, real_type_tag)
    1115             :             {
    1116           0 :                return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
    1117             :             }
    1118             : 
    1119             :             template <typename T>
    1120             :             inline T shr_impl(const T v0, const T v1, int_type_tag)
    1121             :             {
    1122             :                return v0 >> v1;
    1123             :             }
    1124             : 
    1125             :             template <typename T>
    1126           0 :             inline T shl_impl(const T v0, const T v1, real_type_tag)
    1127             :             {
    1128           0 :                return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
    1129             :             }
    1130             : 
    1131             :             template <typename T>
    1132             :             inline T shl_impl(const T v0, const T v1, int_type_tag)
    1133             :             {
    1134             :                return v0 << v1;
    1135             :             }
    1136             : 
    1137             :             template <typename T>
    1138         153 :             inline T sgn_impl(const T v, real_type_tag)
    1139             :             {
    1140         153 :                if      (v > T(0)) return T(+1);
    1141          30 :                else if (v < T(0)) return T(-1);
    1142          15 :                else               return T( 0);
    1143             :             }
    1144             : 
    1145             :             template <typename T>
    1146             :             inline T sgn_impl(const T v, int_type_tag)
    1147             :             {
    1148             :                if      (v > T(0)) return T(+1);
    1149             :                else if (v < T(0)) return T(-1);
    1150             :                else               return T( 0);
    1151             :             }
    1152             : 
    1153             :             template <typename T>
    1154         485 :             inline T and_impl(const T v0, const T v1, real_type_tag)
    1155             :             {
    1156         485 :                return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
    1157             :             }
    1158             : 
    1159             :             template <typename T>
    1160             :             inline T and_impl(const T v0, const T v1, int_type_tag)
    1161             :             {
    1162             :                return v0 && v1;
    1163             :             }
    1164             : 
    1165             :             template <typename T>
    1166         600 :             inline T nand_impl(const T v0, const T v1, real_type_tag)
    1167             :             {
    1168         600 :                return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
    1169             :             }
    1170             : 
    1171             :             template <typename T>
    1172             :             inline T nand_impl(const T v0, const T v1, int_type_tag)
    1173             :             {
    1174             :                return !(v0 && v1);
    1175             :             }
    1176             : 
    1177             :             template <typename T>
    1178         440 :             inline T or_impl(const T v0, const T v1, real_type_tag)
    1179             :             {
    1180         440 :                return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
    1181             :             }
    1182             : 
    1183             :             template <typename T>
    1184             :             inline T or_impl(const T v0, const T v1, int_type_tag)
    1185             :             {
    1186             :                return (v0 || v1);
    1187             :             }
    1188             : 
    1189             :             template <typename T>
    1190         600 :             inline T nor_impl(const T v0, const T v1, real_type_tag)
    1191             :             {
    1192         600 :                return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
    1193             :             }
    1194             : 
    1195             :             template <typename T>
    1196             :             inline T nor_impl(const T v0, const T v1, int_type_tag)
    1197             :             {
    1198             :                return !(v0 || v1);
    1199             :             }
    1200             : 
    1201             :             template <typename T>
    1202         265 :             inline T xor_impl(const T v0, const T v1, real_type_tag)
    1203             :             {
    1204         265 :                return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
    1205             :             }
    1206             : 
    1207             :             template <typename T>
    1208             :             inline T xor_impl(const T v0, const T v1, int_type_tag)
    1209             :             {
    1210             :                return v0 ^ v1;
    1211             :             }
    1212             : 
    1213             :             template <typename T>
    1214          80 :             inline T xnor_impl(const T v0, const T v1, real_type_tag)
    1215             :             {
    1216          80 :                const bool v0_true = is_true_impl(v0);
    1217          80 :                const bool v1_true = is_true_impl(v1);
    1218             : 
    1219          80 :                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
    1220          40 :                   return T(1);
    1221             :                else
    1222          40 :                   return T(0);
    1223             :             }
    1224             : 
    1225             :             template <typename T>
    1226             :             inline T xnor_impl(const T v0, const T v1, int_type_tag)
    1227             :             {
    1228             :                const bool v0_true = is_true_impl(v0);
    1229             :                const bool v1_true = is_true_impl(v1);
    1230             : 
    1231             :                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
    1232             :                   return T(1);
    1233             :                else
    1234             :                   return T(0);
    1235             :             }
    1236             : 
    1237             :             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
    1238             :             #define exprtk_define_erf(TT, impl)                \
    1239             :             inline TT erf_impl(const TT v) { return impl(v); } \
    1240             : 
    1241             :             exprtk_define_erf(float      , ::erff)
    1242    30000002 :             exprtk_define_erf(double     , ::erf )
    1243             :             exprtk_define_erf(long double, ::erfl)
    1244             :             #undef exprtk_define_erf
    1245             :             #endif
    1246             : 
    1247             :             template <typename T>
    1248    30000002 :             inline T erf_impl(const T v, real_type_tag)
    1249             :             {
    1250             :                #if defined(_MSC_VER) && (_MSC_VER < 1900)
    1251             :                // Credits: Abramowitz & Stegun Equations 7.1.25-28
    1252             :                static const T c[] =
    1253             :                {
    1254             :                   T( 1.26551223), T(1.00002368),
    1255             :                   T( 0.37409196), T(0.09678418),
    1256             :                   T(-0.18628806), T(0.27886807),
    1257             :                   T(-1.13520398), T(1.48851587),
    1258             :                   T(-0.82215223), T(0.17087277)
    1259             :                };
    1260             : 
    1261             :                const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
    1262             : 
    1263             :                const T result = T(1) - t * std::exp((-v * v) -
    1264             :                                             c[0] + t * (c[1] + t *
    1265             :                                            (c[2] + t * (c[3] + t *
    1266             :                                            (c[4] + t * (c[5] + t *
    1267             :                                            (c[6] + t * (c[7] + t *
    1268             :                                            (c[8] + t * (c[9]))))))))));
    1269             : 
    1270             :                return (v >= T(0)) ? result : -result;
    1271             :                #else
    1272    30000002 :                return erf_impl(v);
    1273             :                #endif
    1274             :             }
    1275             : 
    1276             :             template <typename T>
    1277             :             inline T erf_impl(const T v, int_type_tag)
    1278             :             {
    1279             :                return erf_impl(static_cast<double>(v),real_type_tag());
    1280             :             }
    1281             : 
    1282             :             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
    1283             :             #define exprtk_define_erfc(TT, impl)                \
    1284             :             inline TT erfc_impl(const TT v) { return impl(v); } \
    1285             : 
    1286             :             exprtk_define_erfc(float      ,::erfcf)
    1287    30000472 :             exprtk_define_erfc(double     ,::erfc )
    1288             :             exprtk_define_erfc(long double,::erfcl)
    1289             :             #undef exprtk_define_erfc
    1290             :             #endif
    1291             : 
    1292             :             template <typename T>
    1293    30000472 :             inline T erfc_impl(const T v, real_type_tag)
    1294             :             {
    1295             :                #if defined(_MSC_VER) && (_MSC_VER < 1900)
    1296             :                return T(1) - erf_impl(v,real_type_tag());
    1297             :                #else
    1298    30000472 :                return erfc_impl(v);
    1299             :                #endif
    1300             :             }
    1301             : 
    1302             :             template <typename T>
    1303             :             inline T erfc_impl(const T v, int_type_tag)
    1304             :             {
    1305             :                return erfc_impl(static_cast<double>(v),real_type_tag());
    1306             :             }
    1307             : 
    1308             :             template <typename T>
    1309         470 :             inline T ncdf_impl(const T v, real_type_tag)
    1310             :             {
    1311         470 :                return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag());
    1312             :             }
    1313             : 
    1314             :             template <typename T>
    1315             :             inline T ncdf_impl(const T v, int_type_tag)
    1316             :             {
    1317             :                return ncdf_impl(static_cast<double>(v),real_type_tag());
    1318             :             }
    1319             : 
    1320             :             template <typename T>
    1321          10 :             inline T sinc_impl(const T v, real_type_tag)
    1322             :             {
    1323          10 :                if (std::abs(v) >= std::numeric_limits<T>::epsilon())
    1324          10 :                    return(std::sin(v) / v);
    1325             :                else
    1326           0 :                   return T(1);
    1327             :             }
    1328             : 
    1329             :             template <typename T>
    1330             :             inline T sinc_impl(const T v, int_type_tag)
    1331             :             {
    1332             :                return sinc_impl(static_cast<double>(v),real_type_tag());
    1333             :             }
    1334             : 
    1335             :             #if __cplusplus >= 201103L
    1336             :             template <typename T>
    1337          80 :             inline T acosh_impl(const T v, real_type_tag)
    1338             :             {
    1339          80 :                return std::acosh(v);
    1340             :             }
    1341             : 
    1342             :             template <typename T>
    1343         210 :             inline T asinh_impl(const T v, real_type_tag)
    1344             :             {
    1345         210 :                return std::asinh(v);
    1346             :             }
    1347             : 
    1348             :             template <typename T>
    1349          80 :             inline T atanh_impl(const T v, real_type_tag)
    1350             :             {
    1351          80 :                return std::atanh(v);
    1352             :             }
    1353             :             #else
    1354             :             template <typename T>
    1355             :             inline T acosh_impl(const T v, real_type_tag)
    1356             :             {
    1357             :                return std::log(v + std::sqrt((v * v) - T(1)));
    1358             :             }
    1359             : 
    1360             :             template <typename T>
    1361             :             inline T asinh_impl(const T v, real_type_tag)
    1362             :             {
    1363             :                return std::log(v + std::sqrt((v * v) + T(1)));
    1364             :             }
    1365             : 
    1366             :             template <typename T>
    1367             :             inline T atanh_impl(const T v, real_type_tag)
    1368             :             {
    1369             :                return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2);
    1370             :             }
    1371             :             #endif
    1372             : 
    1373          10 :             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
    1374          10 :             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
    1375          10 :             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
    1376          60 :             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
    1377    40000697 :             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
    1378          15 :             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
    1379          32 :             template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
    1380         110 :             template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
    1381         175 :             template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
    1382         175 :             template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
    1383          10 :             template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
    1384       98767 :             template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
    1385           0 :             template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
    1386   144040751 :             template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
    1387          15 :             template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
    1388     6002428 :             template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
    1389         242 :             template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
    1390          15 :             template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
    1391          10 :             template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
    1392          10 :             template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
    1393          10 :             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
    1394           5 :             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
    1395          95 :             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
    1396           5 :             template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); }
    1397           5 :             template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); }
    1398         728 :             template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
    1399         695 :             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
    1400       25099 :             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
    1401             : 
    1402           1 :             template <typename T> inline T   const_pi_impl(real_type_tag) { return T(numeric::constant::pi);            }
    1403             :             template <typename T> inline T    const_e_impl(real_type_tag) { return T(numeric::constant::e);             }
    1404             :             template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1405             : 
    1406             :             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
    1407             :             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
    1408             :             template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
    1409             :             template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
    1410             :             template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
    1411             :             template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
    1412             :             template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
    1413             :             template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
    1414             :             template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
    1415             :             template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
    1416             :             template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
    1417             :             template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
    1418             :             template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
    1419             :             template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
    1420             :             template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1421             :             template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1422             :             template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1423             :             template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1424             :             template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1425             :             template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1426             :             template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1427             :             template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1428             :             template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1429             :             template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1430             :             template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1431             :             template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1432             :             template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1433             :             template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1434             :             template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1435             : 
    1436             :             template <typename T>
    1437       88171 :             inline bool is_integer_impl(const T& v, real_type_tag)
    1438             :             {
    1439       88171 :                return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
    1440             :             }
    1441             : 
    1442             :             template <typename T>
    1443             :             inline bool is_integer_impl(const T&, int_type_tag)
    1444             :             {
    1445             :                return true;
    1446             :             }
    1447             :          }
    1448             : 
    1449             :          template <typename Type>
    1450             :          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
    1451             : 
    1452             :          template <> struct numeric_info<int        > { enum { length = 10, size = 16, bound_length = 9 }; };
    1453             :          template <> struct numeric_info<float      > { enum { min_exp =  -38, max_exp =  +38 }; };
    1454             :          template <> struct numeric_info<double     > { enum { min_exp = -308, max_exp = +308 }; };
    1455             :          template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; };
    1456             : 
    1457             :          template <typename T>
    1458      112698 :          inline int to_int32(const T v)
    1459             :          {
    1460      112698 :             const typename details::number_type<T>::type num_type;
    1461      112698 :             return to_int32_impl(v, num_type);
    1462             :          }
    1463             : 
    1464             :          template <typename T>
    1465       57228 :          inline _int64_t to_int64(const T v)
    1466             :          {
    1467       57228 :             const typename details::number_type<T>::type num_type;
    1468       57228 :             return to_int64_impl(v, num_type);
    1469             :          }
    1470             : 
    1471             :          template <typename T>
    1472    32864168 :          inline _uint64_t to_uint64(const T v)
    1473             :          {
    1474    32864168 :             const typename details::number_type<T>::type num_type;
    1475    32864168 :             return to_uint64_impl(v, num_type);
    1476             :          }
    1477             : 
    1478             :          template <typename T>
    1479         195 :          inline bool is_nan(const T v)
    1480             :          {
    1481         195 :             const typename details::number_type<T>::type num_type;
    1482         195 :             return is_nan_impl(v, num_type);
    1483             :          }
    1484             : 
    1485             :          template <typename T>
    1486             :          inline T min(const T v0, const T v1)
    1487             :          {
    1488             :             const typename details::number_type<T>::type num_type;
    1489             :             return min_impl(v0, v1, num_type);
    1490             :          }
    1491             : 
    1492             :          template <typename T>
    1493             :          inline T max(const T v0, const T v1)
    1494             :          {
    1495             :             const typename details::number_type<T>::type num_type;
    1496             :             return max_impl(v0, v1, num_type);
    1497             :          }
    1498             : 
    1499             :          template <typename T>
    1500      267123 :          inline T equal(const T v0, const T v1)
    1501             :          {
    1502      267123 :             const typename details::number_type<T>::type num_type;
    1503      267123 :             return equal_impl(v0, v1, num_type);
    1504             :          }
    1505             : 
    1506             :          template <typename T>
    1507          20 :          inline T nequal(const T v0, const T v1)
    1508             :          {
    1509          20 :             const typename details::number_type<T>::type num_type;
    1510          20 :             return nequal_impl(v0, v1, num_type);
    1511             :          }
    1512             : 
    1513             :          template <typename T>
    1514      118489 :          inline T modulus(const T v0, const T v1)
    1515             :          {
    1516      118489 :             const typename details::number_type<T>::type num_type;
    1517      118489 :             return modulus_impl(v0, v1, num_type);
    1518             :          }
    1519             : 
    1520             :          template <typename T>
    1521        7664 :          inline T pow(const T v0, const T v1)
    1522             :          {
    1523        7664 :             const typename details::number_type<T>::type num_type;
    1524        7664 :             return pow_impl(v0, v1, num_type);
    1525             :          }
    1526             : 
    1527             :          template <typename T>
    1528           0 :          inline T logn(const T v0, const T v1)
    1529             :          {
    1530           0 :             const typename details::number_type<T>::type num_type;
    1531           0 :             return logn_impl(v0, v1, num_type);
    1532             :          }
    1533             : 
    1534             :          template <typename T>
    1535         160 :          inline T root(const T v0, const T v1)
    1536             :          {
    1537         160 :             const typename details::number_type<T>::type num_type;
    1538         160 :             return root_impl(v0, v1, num_type);
    1539             :          }
    1540             : 
    1541             :          template <typename T>
    1542         120 :          inline T roundn(const T v0, const T v1)
    1543             :          {
    1544         120 :             const typename details::number_type<T>::type num_type;
    1545         240 :             return roundn_impl(v0, v1, num_type);
    1546             :          }
    1547             : 
    1548             :          template <typename T>
    1549          30 :          inline T hypot(const T v0, const T v1)
    1550             :          {
    1551          30 :             const typename details::number_type<T>::type num_type;
    1552          30 :             return hypot_impl(v0, v1, num_type);
    1553             :          }
    1554             : 
    1555             :          template <typename T>
    1556           0 :          inline T atan2(const T v0, const T v1)
    1557             :          {
    1558           0 :             const typename details::number_type<T>::type num_type;
    1559           0 :             return atan2_impl(v0, v1, num_type);
    1560             :          }
    1561             : 
    1562             :          template <typename T>
    1563           0 :          inline T shr(const T v0, const T v1)
    1564             :          {
    1565           0 :             const typename details::number_type<T>::type num_type;
    1566           0 :             return shr_impl(v0, v1, num_type);
    1567             :          }
    1568             : 
    1569             :          template <typename T>
    1570           0 :          inline T shl(const T v0, const T v1)
    1571             :          {
    1572           0 :             const typename details::number_type<T>::type num_type;
    1573           0 :             return shl_impl(v0, v1, num_type);
    1574             :          }
    1575             : 
    1576             :          template <typename T>
    1577         485 :          inline T and_opr(const T v0, const T v1)
    1578             :          {
    1579         485 :             const typename details::number_type<T>::type num_type;
    1580         485 :             return and_impl(v0, v1, num_type);
    1581             :          }
    1582             : 
    1583             :          template <typename T>
    1584         600 :          inline T nand_opr(const T v0, const T v1)
    1585             :          {
    1586         600 :             const typename details::number_type<T>::type num_type;
    1587         600 :             return nand_impl(v0, v1, num_type);
    1588             :          }
    1589             : 
    1590             :          template <typename T>
    1591         440 :          inline T or_opr(const T v0, const T v1)
    1592             :          {
    1593         440 :             const typename details::number_type<T>::type num_type;
    1594         440 :             return or_impl(v0, v1, num_type);
    1595             :          }
    1596             : 
    1597             :          template <typename T>
    1598         600 :          inline T nor_opr(const T v0, const T v1)
    1599             :          {
    1600         600 :             const typename details::number_type<T>::type num_type;
    1601         600 :             return nor_impl(v0, v1, num_type);
    1602             :          }
    1603             : 
    1604             :          template <typename T>
    1605         265 :          inline T xor_opr(const T v0, const T v1)
    1606             :          {
    1607         265 :             const typename details::number_type<T>::type num_type;
    1608         530 :             return xor_impl(v0, v1, num_type);
    1609             :          }
    1610             : 
    1611             :          template <typename T>
    1612          80 :          inline T xnor_opr(const T v0, const T v1)
    1613             :          {
    1614          80 :             const typename details::number_type<T>::type num_type;
    1615         160 :             return xnor_impl(v0, v1, num_type);
    1616             :          }
    1617             : 
    1618             :          template <typename T>
    1619       88171 :          inline bool is_integer(const T v)
    1620             :          {
    1621       88171 :             const typename details::number_type<T>::type num_type;
    1622       88171 :             return is_integer_impl(v, num_type);
    1623             :          }
    1624             : 
    1625             :          template <typename T, unsigned int N>
    1626             :          struct fast_exp
    1627             :          {
    1628        6615 :             static inline T result(T v)
    1629             :             {
    1630        6615 :                unsigned int k = N;
    1631        6615 :                T l = T(1);
    1632             : 
    1633       35475 :                while (k)
    1634             :                {
    1635       28860 :                   if (1 == (k % 2))
    1636             :                   {
    1637       17640 :                      l *= v;
    1638       17640 :                      --k;
    1639             :                   }
    1640             : 
    1641       28860 :                   v *= v;
    1642       28860 :                   k /= 2;
    1643             :                }
    1644             : 
    1645        6615 :                return l;
    1646             :             }
    1647             :          };
    1648             : 
    1649        3255 :          template <typename T> struct fast_exp<T,10> { static inline T result(const T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
    1650        4455 :          template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } };
    1651       10295 :          template <typename T> struct fast_exp<T, 8> { static inline T result(const T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
    1652        6465 :          template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } };
    1653       13935 :          template <typename T> struct fast_exp<T, 6> { static inline T result(const T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
    1654       11730 :          template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } };
    1655       31507 :          template <typename T> struct fast_exp<T, 4> { static inline T result(const T v) { T v_2 = v * v; return v_2 * v_2; } };
    1656       24590 :          template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } };
    1657         241 :          template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v;     } };
    1658         120 :          template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v;         } };
    1659             :          template <typename T> struct fast_exp<T, 0> { static inline T result(const T  ) { return T(1);      } };
    1660             : 
    1661             :          #define exprtk_define_unary_function(FunctionName)        \
    1662             :          template <typename T>                                     \
    1663             :          inline T FunctionName (const T v)                         \
    1664             :          {                                                         \
    1665             :             const typename details::number_type<T>::type num_type; \
    1666             :             return  FunctionName##_impl(v,num_type);               \
    1667             :          }                                                         \
    1668             : 
    1669    22177777 :          exprtk_define_unary_function(abs  )
    1670          10 :          exprtk_define_unary_function(acos )
    1671          80 :          exprtk_define_unary_function(acosh)
    1672          10 :          exprtk_define_unary_function(asin )
    1673         210 :          exprtk_define_unary_function(asinh)
    1674          10 :          exprtk_define_unary_function(atan )
    1675          80 :          exprtk_define_unary_function(atanh)
    1676          60 :          exprtk_define_unary_function(ceil )
    1677    40000697 :          exprtk_define_unary_function(cos  )
    1678          15 :          exprtk_define_unary_function(cosh )
    1679          32 :          exprtk_define_unary_function(exp  )
    1680           0 :          exprtk_define_unary_function(expm1)
    1681         110 :          exprtk_define_unary_function(floor)
    1682         175 :          exprtk_define_unary_function(log  )
    1683         175 :          exprtk_define_unary_function(log10)
    1684          10 :          exprtk_define_unary_function(log2 )
    1685           0 :          exprtk_define_unary_function(log1p)
    1686       98767 :          exprtk_define_unary_function(neg  )
    1687           0 :          exprtk_define_unary_function(pos  )
    1688          60 :          exprtk_define_unary_function(round)
    1689   144040751 :          exprtk_define_unary_function(sin  )
    1690          10 :          exprtk_define_unary_function(sinc )
    1691          15 :          exprtk_define_unary_function(sinh )
    1692     6002428 :          exprtk_define_unary_function(sqrt )
    1693         242 :          exprtk_define_unary_function(tan  )
    1694          15 :          exprtk_define_unary_function(tanh )
    1695          10 :          exprtk_define_unary_function(cot  )
    1696          10 :          exprtk_define_unary_function(sec  )
    1697          10 :          exprtk_define_unary_function(csc  )
    1698           5 :          exprtk_define_unary_function(r2d  )
    1699          95 :          exprtk_define_unary_function(d2r  )
    1700           5 :          exprtk_define_unary_function(d2g  )
    1701           5 :          exprtk_define_unary_function(g2d  )
    1702         728 :          exprtk_define_unary_function(notl )
    1703         153 :          exprtk_define_unary_function(sgn  )
    1704    30000002 :          exprtk_define_unary_function(erf  )
    1705    30000002 :          exprtk_define_unary_function(erfc )
    1706         470 :          exprtk_define_unary_function(ncdf )
    1707         695 :          exprtk_define_unary_function(frac )
    1708       25099 :          exprtk_define_unary_function(trunc)
    1709             :          #undef exprtk_define_unary_function
    1710             :       }
    1711             : 
    1712             :       template <typename T>
    1713     2755603 :       inline T compute_pow10(T d, const int exponent)
    1714             :       {
    1715             :          static const double fract10[] =
    1716             :          {
    1717             :             0.0,
    1718             :             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,
    1719             :             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,
    1720             :             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,
    1721             :             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,
    1722             :             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,
    1723             :             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,
    1724             :             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,
    1725             :             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,
    1726             :             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,
    1727             :             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,
    1728             :             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,
    1729             :             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,
    1730             :             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,
    1731             :             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,
    1732             :             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,
    1733             :             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,
    1734             :             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,
    1735             :             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,
    1736             :             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,
    1737             :             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,
    1738             :             1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
    1739             :             1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
    1740             :             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,
    1741             :             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,
    1742             :             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,
    1743             :             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,
    1744             :             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,
    1745             :             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,
    1746             :             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,
    1747             :             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,
    1748             :             1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
    1749             :          };
    1750             : 
    1751             :          static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
    1752             : 
    1753     2755603 :          const int e = std::abs(exponent);
    1754             : 
    1755     2755603 :          if (exponent >= std::numeric_limits<T>::min_exponent10)
    1756             :          {
    1757     2755597 :             if (e < fract10_size)
    1758             :             {
    1759     2755597 :                if (exponent > 0)
    1760        1764 :                   return T(d * fract10[e]);
    1761             :                else
    1762     2753833 :                   return T(d / fract10[e]);
    1763             :             }
    1764             :             else
    1765           0 :                return T(d * std::pow(10.0, 10.0 * exponent));
    1766             :          }
    1767             :          else
    1768             :          {
    1769           6 :                      d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
    1770           6 :             return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
    1771             :          }
    1772             :       }
    1773             : 
    1774             :       template <typename Iterator, typename T>
    1775        2028 :       inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
    1776             :       {
    1777        2028 :          if (itr == end)
    1778           0 :             return false;
    1779             : 
    1780        2028 :          const bool negative = ('-' == (*itr));
    1781             : 
    1782        2028 :          if (negative || ('+' == (*itr)))
    1783             :          {
    1784        1706 :             if (end == ++itr)
    1785          14 :                return false;
    1786             :          }
    1787             : 
    1788             :          static const uchar_t zero = static_cast<uchar_t>('0');
    1789             : 
    1790        2340 :          while ((end != itr) && (zero == (*itr))) ++itr;
    1791             : 
    1792        2014 :          bool return_result = true;
    1793        2014 :          unsigned int digit = 0;
    1794        2014 :          const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
    1795             : 
    1796        2014 :          if (length <= 4)
    1797             :          {
    1798        2014 :             switch (length)
    1799             :             {
    1800             :                #ifdef exprtk_use_lut
    1801             : 
    1802             :                #define exprtk_process_digit                          \
    1803             :                if ((digit = details::digit_table[(int)*itr++]) < 10) \
    1804             :                   result = result * 10 + (digit);                    \
    1805             :                else                                                  \
    1806             :                {                                                     \
    1807             :                   return_result = false;                             \
    1808             :                   break;                                             \
    1809             :                }                                                     \
    1810             :                exprtk_fallthrough                                    \
    1811             : 
    1812             :                #else
    1813             : 
    1814             :                #define exprtk_process_digit        \
    1815             :                if ((digit = (*itr++ - zero)) < 10) \
    1816             :                   result = result * T(10) + digit; \
    1817             :                else                                \
    1818             :                {                                   \
    1819             :                   return_result = false;           \
    1820             :                   break;                           \
    1821             :                }                                   \
    1822             :                exprtk_fallthrough                  \
    1823             : 
    1824             :                #endif
    1825             : 
    1826           0 :                case 4 : exprtk_process_digit
    1827          12 :                case 3 : exprtk_process_digit
    1828          38 :                case 2 : exprtk_process_digit
    1829        1850 :                case 1 : if ((digit = (*itr - zero))>= 10)
    1830             :                         {
    1831           0 :                            digit = 0;
    1832           0 :                            return_result = false;
    1833             :                         }
    1834             : 
    1835             :                #undef exprtk_process_digit
    1836             :             }
    1837             :          }
    1838             :          else
    1839           0 :             return_result = false;
    1840             : 
    1841        2014 :          if (length && return_result)
    1842             :          {
    1843        1850 :             result = result * 10 + static_cast<T>(digit);
    1844        1850 :             ++itr;
    1845             :          }
    1846             : 
    1847        2014 :          result = negative ? -result : result;
    1848        2014 :          return return_result;
    1849             :       }
    1850             : 
    1851             :       template <typename Iterator, typename T>
    1852           0 :       static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
    1853             :       {
    1854             :          typedef typename std::iterator_traits<Iterator>::value_type type;
    1855             : 
    1856             :          static const std::size_t nan_length = 3;
    1857             : 
    1858           0 :          if (std::distance(itr,end) != static_cast<int>(nan_length))
    1859           0 :             return false;
    1860             : 
    1861           0 :          if (static_cast<type>('n') == (*itr))
    1862             :          {
    1863           0 :             if (
    1864           0 :                  (static_cast<type>('a') != *(itr + 1)) ||
    1865           0 :                  (static_cast<type>('n') != *(itr + 2))
    1866             :                )
    1867             :             {
    1868           0 :                return false;
    1869             :             }
    1870             :          }
    1871           0 :          else if (
    1872           0 :                    (static_cast<type>('A') != *(itr + 1)) ||
    1873           0 :                    (static_cast<type>('N') != *(itr + 2))
    1874             :                  )
    1875             :          {
    1876           0 :             return false;
    1877             :          }
    1878             : 
    1879           0 :          t = std::numeric_limits<T>::quiet_NaN();
    1880             : 
    1881           0 :          return true;
    1882             :       }
    1883             : 
    1884             :       template <typename Iterator, typename T>
    1885           0 :       static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative)
    1886             :       {
    1887             :          static const char_t inf_uc[] = "INFINITY";
    1888             :          static const char_t inf_lc[] = "infinity";
    1889             :          static const std::size_t inf_length = 8;
    1890             : 
    1891           0 :          const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
    1892             : 
    1893           0 :          if ((3 != length) && (inf_length != length))
    1894           0 :             return false;
    1895             : 
    1896           0 :          char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
    1897             : 
    1898           0 :          while (end != itr)
    1899             :          {
    1900           0 :             if (*inf_itr == static_cast<char_t>(*itr))
    1901             :             {
    1902           0 :                ++itr;
    1903           0 :                ++inf_itr;
    1904           0 :                continue;
    1905             :             }
    1906             :             else
    1907           0 :                return false;
    1908             :          }
    1909             : 
    1910           0 :          if (negative)
    1911           0 :             t = -std::numeric_limits<T>::infinity();
    1912             :          else
    1913           0 :             t =  std::numeric_limits<T>::infinity();
    1914             : 
    1915           0 :          return true;
    1916             :       }
    1917             : 
    1918             :       template <typename T>
    1919     6604807 :       inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
    1920             :       {
    1921             :          using namespace details::numeric;
    1922     6604807 :          return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp);
    1923             :       }
    1924             : 
    1925             :       template <typename Iterator, typename T>
    1926     3851068 :       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
    1927             :       {
    1928     3851068 :          if (end == itr_external) return false;
    1929             : 
    1930     3851068 :          Iterator itr = itr_external;
    1931             : 
    1932     3851068 :          T d = T(0);
    1933             : 
    1934     3851068 :          const bool negative = ('-' == (*itr));
    1935             : 
    1936     3851068 :          if (negative || '+' == (*itr))
    1937             :          {
    1938           0 :             if (end == ++itr)
    1939           0 :                return false;
    1940             :          }
    1941             : 
    1942     3851068 :          bool instate = false;
    1943             : 
    1944             :          static const char_t zero = static_cast<uchar_t>('0');
    1945             : 
    1946             :          #define parse_digit_1(d)          \
    1947             :          if ((digit = (*itr - zero)) < 10) \
    1948             :             { d = d * T(10) + digit; }     \
    1949             :          else                              \
    1950             :             { break; }                     \
    1951             :          if (end == ++itr) break;          \
    1952             : 
    1953             :          #define parse_digit_2(d)          \
    1954             :          if ((digit = (*itr - zero)) < 10) \
    1955             :             { d = d * T(10) + digit; }     \
    1956             :          else                              \
    1957             :             { break; }                     \
    1958             :             ++itr;                         \
    1959             : 
    1960     3851068 :          if ('.' != (*itr))
    1961             :          {
    1962     3850805 :             const Iterator curr = itr;
    1963             : 
    1964    10690401 :             while ((end != itr) && (zero == (*itr))) ++itr;
    1965             : 
    1966     4041815 :             while (end != itr)
    1967             :             {
    1968             :                unsigned int digit;
    1969     3971737 :                parse_digit_1(d)
    1970     2708107 :                parse_digit_1(d)
    1971      358151 :                parse_digit_2(d)
    1972             :             }
    1973             : 
    1974     3850805 :             if (curr != itr) instate = true;
    1975             :          }
    1976             : 
    1977     3851068 :          int exponent = 0;
    1978             : 
    1979     3851068 :          if (end != itr)
    1980             :          {
    1981     2755161 :             if ('.' == (*itr))
    1982             :             {
    1983     2754947 :                const Iterator curr = ++itr;
    1984     2754947 :                T tmp_d = T(0);
    1985             : 
    1986     8918259 :                while (end != itr)
    1987             :                {
    1988             :                   unsigned int digit;
    1989     6846005 :                   parse_digit_1(tmp_d)
    1990     6406994 :                   parse_digit_1(tmp_d)
    1991     6163406 :                   parse_digit_2(tmp_d)
    1992             :                }
    1993             : 
    1994     2754947 :                if (curr != itr)
    1995             :                {
    1996     2753753 :                   instate = true;
    1997             : 
    1998     2753753 :                   const int frac_exponent = static_cast<int>(-std::distance(curr, itr));
    1999             : 
    2000     2753753 :                   if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag()))
    2001           0 :                      return false;
    2002             : 
    2003     2753753 :                   d += compute_pow10(tmp_d, frac_exponent);
    2004             :                }
    2005             : 
    2006             :                #undef parse_digit_1
    2007             :                #undef parse_digit_2
    2008             :             }
    2009             : 
    2010     2755161 :             if (end != itr)
    2011             :             {
    2012        2028 :                typename std::iterator_traits<Iterator>::value_type c = (*itr);
    2013             : 
    2014        2028 :                if (('e' == c) || ('E' == c))
    2015             :                {
    2016        2028 :                   int exp = 0;
    2017             : 
    2018        2028 :                   if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
    2019             :                   {
    2020          14 :                      if (end == itr)
    2021          14 :                         return false;
    2022             :                      else
    2023           0 :                         c = (*itr);
    2024             :                   }
    2025             : 
    2026        2014 :                   exponent += exp;
    2027             :                }
    2028             : 
    2029        2014 :                if (end != itr)
    2030             :                {
    2031           0 :                   if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
    2032           0 :                      ++itr;
    2033           0 :                   else if ('#' == c)
    2034             :                   {
    2035           0 :                      if (end == ++itr)
    2036           0 :                         return false;
    2037           0 :                      else if (('I' <= (*itr)) && ((*itr) <= 'n'))
    2038             :                      {
    2039           0 :                         if (('i' == (*itr)) || ('I' == (*itr)))
    2040             :                         {
    2041           0 :                            return parse_inf(itr, end, t, negative);
    2042             :                         }
    2043           0 :                         else if (('n' == (*itr)) || ('N' == (*itr)))
    2044             :                         {
    2045           0 :                            return parse_nan(itr, end, t);
    2046             :                         }
    2047             :                         else
    2048           0 :                            return false;
    2049             :                      }
    2050             :                      else
    2051           0 :                         return false;
    2052             :                   }
    2053           0 :                   else if (('I' <= (*itr)) && ((*itr) <= 'n'))
    2054             :                   {
    2055           0 :                      if (('i' == (*itr)) || ('I' == (*itr)))
    2056             :                      {
    2057           0 :                         return parse_inf(itr, end, t, negative);
    2058             :                      }
    2059           0 :                      else if (('n' == (*itr)) || ('N' == (*itr)))
    2060             :                      {
    2061           0 :                         return parse_nan(itr, end, t);
    2062             :                      }
    2063             :                      else
    2064           0 :                         return false;
    2065             :                   }
    2066             :                   else
    2067           0 :                      return false;
    2068             :                }
    2069             :             }
    2070             :          }
    2071             : 
    2072     3851054 :          if ((end != itr) || (!instate))
    2073           0 :             return false;
    2074     3851054 :          else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
    2075           0 :             return false;
    2076     3851054 :          else if (exponent)
    2077        1850 :             d = compute_pow10(d,exponent);
    2078             : 
    2079     3851054 :          t = static_cast<T>((negative) ? -d : d);
    2080     3851054 :          return true;
    2081             :       }
    2082             : 
    2083             :       template <typename T>
    2084     3851068 :       inline bool string_to_real(const std::string& s, T& t)
    2085             :       {
    2086     3851068 :          const typename numeric::details::number_type<T>::type num_type;
    2087             : 
    2088     3851068 :          char_cptr begin = s.data();
    2089     3851068 :          char_cptr end   = s.data() + s.size();
    2090             : 
    2091     7702136 :          return string_to_real(begin, end, t, num_type);
    2092             :       }
    2093             : 
    2094             :       template <typename T>
    2095             :       struct functor_t
    2096             :       {
    2097             :          /*
    2098             :             Note: The following definitions for Type, may require tweaking
    2099             :                   based on the compiler and target architecture. The benchmark
    2100             :                   should provide enough information to make the right choice.
    2101             :          */
    2102             :          //typedef T Type;
    2103             :          //typedef const T Type;
    2104             :          typedef const T& Type;
    2105             :          typedef       T& RefType;
    2106             :          typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
    2107             :          typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
    2108             :          typedef T (*bfunc_t)(Type t0, Type t1);
    2109             :          typedef T (*ufunc_t)(Type t0);
    2110             :       };
    2111             : 
    2112             :    } // namespace details
    2113             : 
    2114             :    struct loop_runtime_check
    2115             :    {
    2116             :       enum loop_types
    2117             :       {
    2118             :          e_invalid           = 0,
    2119             :          e_for_loop          = 1,
    2120             :          e_while_loop        = 2,
    2121             :          e_repeat_until_loop = 4,
    2122             :          e_all_loops         = 7
    2123             :       };
    2124             : 
    2125             :       enum violation_type
    2126             :       {
    2127             :           e_unknown         = 0,
    2128             :           e_iteration_count = 1,
    2129             :           e_timeout         = 2
    2130             :       };
    2131             : 
    2132             :       loop_types loop_set;
    2133             : 
    2134             :       loop_runtime_check()
    2135             :       : loop_set(e_invalid)
    2136             :       , max_loop_iterations(0)
    2137             :       {}
    2138             : 
    2139             :       details::_uint64_t max_loop_iterations;
    2140             : 
    2141             :       struct violation_context
    2142             :       {
    2143             :          loop_types loop;
    2144             :          violation_type violation;
    2145             :          details::_uint64_t iteration_count;
    2146             :       };
    2147             : 
    2148             :       virtual bool check()
    2149             :       {
    2150             :          return true;
    2151             :       }
    2152             : 
    2153             :       virtual void handle_runtime_violation(const violation_context&)
    2154             :       {
    2155             :          throw std::runtime_error("ExprTk Loop runtime violation.");
    2156             :       }
    2157             : 
    2158             :       virtual ~loop_runtime_check()
    2159             :       {}
    2160             :    };
    2161             : 
    2162             :    typedef loop_runtime_check* loop_runtime_check_ptr;
    2163             : 
    2164             :    struct vector_access_runtime_check
    2165             :    {
    2166             :       struct violation_context
    2167             :       {
    2168             :          void* base_ptr;
    2169             :          void* end_ptr;
    2170             :          void* access_ptr;
    2171             :          std::size_t type_size;
    2172             :       };
    2173             : 
    2174          70 :       virtual ~vector_access_runtime_check()
    2175          70 :       {}
    2176             : 
    2177           0 :       virtual bool handle_runtime_violation(violation_context& /*context*/)
    2178             :       {
    2179           0 :          throw std::runtime_error("ExprTk runtime vector access violation.");
    2180             :          #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    2181             :          return false;
    2182             :          #endif
    2183             :       }
    2184             :    };
    2185             : 
    2186             :    typedef vector_access_runtime_check* vector_access_runtime_check_ptr;
    2187             : 
    2188             :    struct assert_check
    2189             :    {
    2190             :       struct assert_context
    2191             :       {
    2192             :          std::string condition;
    2193             :          std::string message;
    2194             :          std::string id;
    2195             :          std::size_t offet;
    2196             :       };
    2197             : 
    2198          54 :       virtual ~assert_check()
    2199          54 :       {}
    2200             : 
    2201           0 :       virtual void handle_assert(const assert_context& /*context*/)
    2202             :       {
    2203           0 :       }
    2204             :    };
    2205             : 
    2206             :    typedef assert_check* assert_check_ptr;
    2207             : 
    2208             :    struct compilation_check
    2209             :    {
    2210             :       struct compilation_context
    2211             :       {
    2212             :          std::string error_message;
    2213             :       };
    2214             : 
    2215             :       virtual bool continue_compilation(compilation_context& /*context*/) = 0;
    2216             : 
    2217             :       virtual ~compilation_check()
    2218             :       {}
    2219             :    };
    2220             : 
    2221             :    typedef compilation_check* compilation_check_ptr;
    2222             : 
    2223             :    namespace lexer
    2224             :    {
    2225             :       struct token
    2226             :       {
    2227             :          enum token_type
    2228             :          {
    2229             :             e_none        =   0, e_error       =   1, e_err_symbol  =   2,
    2230             :             e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
    2231             :             e_eof         =   6, e_number      =   7, e_symbol      =   8,
    2232             :             e_string      =   9, e_assign      =  10, e_addass      =  11,
    2233             :             e_subass      =  12, e_mulass      =  13, e_divass      =  14,
    2234             :             e_modass      =  15, e_shr         =  16, e_shl         =  17,
    2235             :             e_lte         =  18, e_ne          =  19, e_gte         =  20,
    2236             :             e_swap        =  21, e_lt          = '<', e_gt          = '>',
    2237             :             e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
    2238             :             e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
    2239             :             e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
    2240             :             e_sub         = '-', e_div         = '/', e_mul         = '*',
    2241             :             e_mod         = '%', e_pow         = '^', e_colon       = ':',
    2242             :             e_ternary     = '?'
    2243             :          };
    2244             : 
    2245   129155035 :          token()
    2246   129155035 :          : type(e_none)
    2247   258310070 :          , value("")
    2248   129155035 :          , position(std::numeric_limits<std::size_t>::max())
    2249   129155035 :          {}
    2250             : 
    2251      379883 :          void clear()
    2252             :          {
    2253      379883 :             type     = e_none;
    2254      379883 :             value    = "";
    2255      379883 :             position = std::numeric_limits<std::size_t>::max();
    2256      379883 :          }
    2257             : 
    2258             :          template <typename Iterator>
    2259    10933167 :          inline token& set_operator(const token_type tt,
    2260             :                                     const Iterator begin, const Iterator end,
    2261             :                                     const Iterator base_begin = Iterator(0))
    2262             :          {
    2263    10933167 :             type = tt;
    2264    10933167 :             value.assign(begin,end);
    2265    10933167 :             if (base_begin)
    2266    10933167 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2267    10933167 :             return (*this);
    2268             :          }
    2269             : 
    2270             :          template <typename Iterator>
    2271     3335950 :          inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
    2272             :          {
    2273     3335950 :             type = e_symbol;
    2274     3335950 :             value.assign(begin,end);
    2275     3335950 :             if (base_begin)
    2276     3335950 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2277     3335950 :             return (*this);
    2278             :          }
    2279             : 
    2280             :          template <typename Iterator>
    2281     2040016 :          inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
    2282             :          {
    2283     2040016 :             type = e_number;
    2284     2040016 :             value.assign(begin,end);
    2285     2040016 :             if (base_begin)
    2286     2040016 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2287     2040016 :             return (*this);
    2288             :          }
    2289             : 
    2290             :          template <typename Iterator>
    2291       51555 :          inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
    2292             :          {
    2293       51555 :             type = e_string;
    2294       51555 :             value.assign(begin,end);
    2295       51555 :             if (base_begin)
    2296       51555 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2297       51555 :             return (*this);
    2298             :          }
    2299             : 
    2300        1350 :          inline token& set_string(const std::string& s, const std::size_t p)
    2301             :          {
    2302        1350 :             type     = e_string;
    2303        1350 :             value    = s;
    2304        1350 :             position = p;
    2305        1350 :             return (*this);
    2306             :          }
    2307             : 
    2308             :          template <typename Iterator>
    2309         788 :          inline token& set_error(const token_type et,
    2310             :                                  const Iterator begin, const Iterator end,
    2311             :                                  const Iterator base_begin = Iterator(0))
    2312             :          {
    2313         788 :             if (
    2314         297 :                  (e_error      == et) ||
    2315         297 :                  (e_err_symbol == et) ||
    2316         237 :                  (e_err_number == et) ||
    2317           0 :                  (e_err_string == et) ||
    2318             :                  (e_err_sfunc  == et)
    2319             :                )
    2320             :             {
    2321         788 :                type = et;
    2322             :             }
    2323             :             else
    2324           0 :                type = e_error;
    2325             : 
    2326         788 :             value.assign(begin,end);
    2327             : 
    2328         788 :             if (base_begin)
    2329         788 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2330             : 
    2331         788 :             return (*this);
    2332             :          }
    2333             : 
    2334           0 :          static inline std::string to_str(token_type t)
    2335             :          {
    2336           0 :             switch (t)
    2337             :             {
    2338           0 :                case e_none        : return "NONE";
    2339           0 :                case e_error       : return "ERROR";
    2340           0 :                case e_err_symbol  : return "ERROR_SYMBOL";
    2341           0 :                case e_err_number  : return "ERROR_NUMBER";
    2342           0 :                case e_err_string  : return "ERROR_STRING";
    2343           0 :                case e_eof         : return "EOF";
    2344           0 :                case e_number      : return "NUMBER";
    2345           0 :                case e_symbol      : return "SYMBOL";
    2346           0 :                case e_string      : return "STRING";
    2347           0 :                case e_assign      : return ":=";
    2348           0 :                case e_addass      : return "+=";
    2349           0 :                case e_subass      : return "-=";
    2350           0 :                case e_mulass      : return "*=";
    2351           0 :                case e_divass      : return "/=";
    2352           0 :                case e_modass      : return "%=";
    2353           0 :                case e_shr         : return ">>";
    2354           0 :                case e_shl         : return "<<";
    2355           0 :                case e_lte         : return "<=";
    2356           0 :                case e_ne          : return "!=";
    2357           0 :                case e_gte         : return ">=";
    2358           0 :                case e_lt          : return "<";
    2359           0 :                case e_gt          : return ">";
    2360           0 :                case e_eq          : return "=";
    2361           0 :                case e_rbracket    : return ")";
    2362           0 :                case e_lbracket    : return "(";
    2363           0 :                case e_rsqrbracket : return "]";
    2364           0 :                case e_lsqrbracket : return "[";
    2365           0 :                case e_rcrlbracket : return "}";
    2366           0 :                case e_lcrlbracket : return "{";
    2367           0 :                case e_comma       : return ",";
    2368           0 :                case e_add         : return "+";
    2369           0 :                case e_sub         : return "-";
    2370           0 :                case e_div         : return "/";
    2371           0 :                case e_mul         : return "*";
    2372           0 :                case e_mod         : return "%";
    2373           0 :                case e_pow         : return "^";
    2374           0 :                case e_colon       : return ":";
    2375           0 :                case e_ternary     : return "?";
    2376           0 :                case e_swap        : return "<=>";
    2377           0 :                default            : return "UNKNOWN";
    2378             :             }
    2379             :          }
    2380             : 
    2381    17142531 :          inline bool is_error() const
    2382             :          {
    2383             :             return (
    2384    34284080 :                      (e_error      == type) ||
    2385    17141549 :                      (e_err_symbol == type) ||
    2386    17141549 :                      (e_err_number == type) ||
    2387    51425035 :                      (e_err_string == type) ||
    2388    17140955 :                      (e_err_sfunc  == type)
    2389    17142531 :                    );
    2390             :          }
    2391             : 
    2392             :          token_type type;
    2393             :          std::string value;
    2394             :          std::size_t position;
    2395             :       };
    2396             : 
    2397             :       class generator
    2398             :       {
    2399             :       public:
    2400             : 
    2401             :          typedef token token_t;
    2402             :          typedef std::vector<token_t> token_list_t;
    2403             :          typedef token_list_t::iterator token_list_itr_t;
    2404             :          typedef details::char_t char_t;
    2405             : 
    2406      108660 :          generator()
    2407      217320 :          : base_itr_(0)
    2408      108660 :          , s_itr_   (0)
    2409      108660 :          , s_end_   (0)
    2410             :          {
    2411      108660 :             clear();
    2412      108660 :          }
    2413             : 
    2414      108660 :          inline void clear()
    2415             :          {
    2416      108660 :             base_itr_ = 0;
    2417      108660 :             s_itr_    = 0;
    2418      108660 :             s_end_    = 0;
    2419      108660 :             token_list_.clear();
    2420      108660 :             token_itr_ = token_list_.end();
    2421      108660 :             store_token_itr_ = token_list_.end();
    2422      108660 :          }
    2423             : 
    2424      380686 :          inline bool process(const std::string& str)
    2425             :          {
    2426      380686 :             base_itr_ = str.data();
    2427      380686 :             s_itr_    = str.data();
    2428      380686 :             s_end_    = str.data() + str.size();
    2429             : 
    2430      380686 :             eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_);
    2431      380686 :             token_list_.clear();
    2432             : 
    2433    17447223 :             while (!is_end(s_itr_))
    2434             :             {
    2435    17067325 :                scan_token();
    2436             : 
    2437    17067325 :                if (!token_list_.empty() && token_list_.back().is_error())
    2438         788 :                   return false;
    2439             :             }
    2440             : 
    2441      379898 :             return true;
    2442             :          }
    2443             : 
    2444      379898 :          inline bool empty() const
    2445             :          {
    2446      379898 :             return token_list_.empty();
    2447             :          }
    2448             : 
    2449       78215 :          inline std::size_t size() const
    2450             :          {
    2451       78215 :             return token_list_.size();
    2452             :          }
    2453             : 
    2454      750056 :          inline void begin()
    2455             :          {
    2456      750056 :             token_itr_ = token_list_.begin();
    2457      750056 :             store_token_itr_ = token_list_.begin();
    2458      750056 :          }
    2459             : 
    2460             :          inline void store()
    2461             :          {
    2462             :             store_token_itr_ = token_itr_;
    2463             :          }
    2464             : 
    2465             :          inline void restore()
    2466             :          {
    2467             :             token_itr_ = store_token_itr_;
    2468             :          }
    2469             : 
    2470    13552170 :          inline token_t& next_token()
    2471             :          {
    2472    13552170 :             if (token_list_.end() != token_itr_)
    2473             :             {
    2474    13201971 :                return *token_itr_++;
    2475             :             }
    2476             :             else
    2477      350199 :                return eof_token_;
    2478             :          }
    2479             : 
    2480     5806079 :          inline token_t& peek_next_token()
    2481             :          {
    2482     5806079 :             if (token_list_.end() != token_itr_)
    2483             :             {
    2484     5772425 :                return *token_itr_;
    2485             :             }
    2486             :             else
    2487       33654 :                return eof_token_;
    2488             :          }
    2489             : 
    2490   108233665 :          inline token_t& operator[](const std::size_t& index)
    2491             :          {
    2492   108233665 :             if (index < token_list_.size())
    2493             :             {
    2494   108233665 :                return token_list_[index];
    2495             :             }
    2496             :             else
    2497           0 :                return eof_token_;
    2498             :          }
    2499             : 
    2500             :          inline token_t operator[](const std::size_t& index) const
    2501             :          {
    2502             :             if (index < token_list_.size())
    2503             :             {
    2504             :                return token_list_[index];
    2505             :             }
    2506             :             else
    2507             :                return eof_token_;
    2508             :          }
    2509             : 
    2510      421620 :          inline bool finished() const
    2511             :          {
    2512      421620 :             return (token_list_.end() == token_itr_);
    2513             :          }
    2514             : 
    2515        4626 :          inline void insert_front(token_t::token_type tk_type)
    2516             :          {
    2517        4626 :             if (
    2518        9252 :                  !token_list_.empty() &&
    2519        9252 :                  (token_list_.end() != token_itr_)
    2520             :                )
    2521             :             {
    2522        4626 :                token_t t = *token_itr_;
    2523             : 
    2524        4626 :                t.type     = tk_type;
    2525        4626 :                token_itr_ = token_list_.insert(token_itr_,t);
    2526        4626 :             }
    2527        4626 :          }
    2528             : 
    2529      434919 :          inline std::string substr(const std::size_t& begin, const std::size_t& end) const
    2530             :          {
    2531      434919 :             const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
    2532      434919 :             const details::char_cptr end_itr   = ((base_itr_ + end  ) < s_end_) ? (base_itr_ + end  ) : s_end_;
    2533             : 
    2534      869838 :             return std::string(begin_itr,end_itr);
    2535             :          }
    2536             : 
    2537             :          inline std::string remaining() const
    2538             :          {
    2539             :             if (finished())
    2540             :                return "";
    2541             :             else if (token_list_.begin() != token_itr_)
    2542             :                return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
    2543             :             else
    2544             :                return std::string(base_itr_ + token_itr_->position, s_end_);
    2545             :          }
    2546             : 
    2547             :       private:
    2548             : 
    2549    85253906 :          inline bool is_end(details::char_cptr itr) const
    2550             :          {
    2551    85253906 :             return (s_end_ == itr);
    2552             :          }
    2553             : 
    2554             :          #ifndef exprtk_disable_comments
    2555    15982420 :          inline bool is_comment_start(details::char_cptr itr) const
    2556             :          {
    2557    15982420 :             const char_t c0 = *(itr + 0);
    2558    15982420 :             const char_t c1 = *(itr + 1);
    2559             : 
    2560    15982420 :             if ('#' == c0)
    2561         243 :                return true;
    2562    15982177 :             else if (!is_end(itr + 1))
    2563             :             {
    2564    15634544 :                if (('/' == c0) && ('/' == c1)) return true;
    2565    15634524 :                if (('/' == c0) && ('*' == c1)) return true;
    2566             :             }
    2567    15982123 :             return false;
    2568             :          }
    2569             :          #else
    2570             :          inline bool is_comment_start(details::char_cptr) const
    2571             :          {
    2572             :             return false;
    2573             :          }
    2574             :          #endif
    2575             : 
    2576     1084905 :          inline void skip_whitespace()
    2577             :          {
    2578     2420251 :             while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
    2579             :             {
    2580     1335346 :                ++s_itr_;
    2581             :             }
    2582     1084905 :          }
    2583             : 
    2584         297 :          inline void skip_comments()
    2585             :          {
    2586             :             #ifndef exprtk_disable_comments
    2587             :             // The following comment styles are supported:
    2588             :             // 1. // .... \n
    2589             :             // 2. #  .... \n
    2590             :             // 3. /* .... */
    2591             :             struct test
    2592             :             {
    2593         297 :                static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
    2594             :                {
    2595         297 :                   mode = 0;
    2596         297 :                   if      ('#' == c0)    { mode = 1; incr = 1; }
    2597          54 :                   else if ('/' == c0)
    2598             :                   {
    2599          54 :                      if      ('/' == c1) { mode = 1; incr = 2; }
    2600          34 :                      else if ('*' == c1) { mode = 2; incr = 2; }
    2601             :                   }
    2602         297 :                   return (0 != mode);
    2603             :                }
    2604             : 
    2605       31112 :                static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
    2606             :                {
    2607       31112 :                   if (
    2608       31112 :                        ((1 == mode) && ('\n' == c0)) ||
    2609       31106 :                        ((2 == mode) && ( '*' == c0) && ('/' == c1))
    2610             :                      )
    2611             :                   {
    2612          23 :                      mode = 0;
    2613          23 :                      return true;
    2614             :                   }
    2615             :                   else
    2616       31089 :                      return false;
    2617             :                }
    2618             :             };
    2619             : 
    2620         297 :             int mode      = 0;
    2621         297 :             int increment = 0;
    2622             : 
    2623         297 :             if (is_end(s_itr_))
    2624          23 :                return;
    2625         297 :             else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
    2626           0 :                return;
    2627             : 
    2628         297 :             details::char_cptr cmt_start = s_itr_;
    2629             : 
    2630         297 :             s_itr_ += increment;
    2631             : 
    2632       31403 :             while (!is_end(s_itr_))
    2633             :             {
    2634       31129 :                if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
    2635             :                {
    2636           6 :                   ++s_itr_;
    2637           6 :                   return;
    2638             :                }
    2639             : 
    2640       31123 :                if ((2 == mode))
    2641             :                {
    2642        1664 :                   if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
    2643             :                   {
    2644          17 :                      s_itr_ += 2;
    2645          17 :                      return;
    2646             :                   }
    2647             :                }
    2648             : 
    2649       31106 :                ++s_itr_;
    2650             :             }
    2651             : 
    2652         274 :             if (2 == mode)
    2653             :             {
    2654          17 :                token_t t;
    2655          17 :                t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
    2656          17 :                token_list_.push_back(t);
    2657          17 :             }
    2658             :             #endif
    2659             :          }
    2660             : 
    2661         236 :          inline bool next_is_digit(const details::char_cptr itr) const
    2662             :          {
    2663         472 :             return ((itr + 1) != s_end_) &&
    2664         472 :                    details::is_digit(*(itr + 1));
    2665             :          }
    2666             : 
    2667    17067325 :          inline void scan_token()
    2668             :          {
    2669    17067325 :             const char_t c = *s_itr_;
    2670             : 
    2671    17067325 :             if (details::is_whitespace(c))
    2672             :             {
    2673     1084905 :                skip_whitespace();
    2674     1084905 :                return;
    2675             :             }
    2676    15982420 :             else if (is_comment_start(s_itr_))
    2677             :             {
    2678         297 :                skip_comments();
    2679         297 :                return;
    2680             :             }
    2681    15982123 :             else if (details::is_operator_char(c))
    2682             :             {
    2683    10553558 :                scan_operator();
    2684    10553558 :                return;
    2685             :             }
    2686     5428565 :             else if (details::is_letter(c))
    2687             :             {
    2688     3316561 :                scan_symbol();
    2689     3316561 :                return;
    2690             :             }
    2691     2112004 :             else if (('.' == c) && !next_is_digit(s_itr_))
    2692             :             {
    2693           0 :                scan_operator();
    2694           0 :                return;
    2695             :             }
    2696     2112004 :             else if (details::is_digit(c) || ('.' == c))
    2697             :             {
    2698     2040076 :                scan_number();
    2699     2040076 :                return;
    2700             :             }
    2701       71928 :             else if ('$' == c)
    2702             :             {
    2703        4245 :                scan_special_function();
    2704        4245 :                return;
    2705             :             }
    2706             :             #ifndef exprtk_disable_string_capabilities
    2707       67683 :             else if ('\'' == c)
    2708             :             {
    2709       53142 :                scan_string();
    2710       53142 :                return;
    2711             :             }
    2712             :             #endif
    2713       14541 :             else if ('~' == c)
    2714             :             {
    2715       14067 :                token_t t;
    2716       14067 :                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
    2717       14067 :                token_list_.push_back(t);
    2718       14067 :                ++s_itr_;
    2719       14067 :                return;
    2720       14067 :             }
    2721             :             else
    2722             :             {
    2723         474 :                token_t t;
    2724         474 :                t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
    2725         474 :                token_list_.push_back(t);
    2726         474 :                ++s_itr_;
    2727         474 :             }
    2728             :          }
    2729             : 
    2730    10553558 :          inline void scan_operator()
    2731             :          {
    2732    10553558 :             token_t t;
    2733             : 
    2734    10553558 :             const char_t c0 = s_itr_[0];
    2735             : 
    2736    10553558 :             if (!is_end(s_itr_ + 1))
    2737             :             {
    2738    10229345 :                const char_t c1 = s_itr_[1];
    2739             : 
    2740    10229345 :                if (!is_end(s_itr_ + 2))
    2741             :                {
    2742     9965063 :                   const char_t c2 = s_itr_[2];
    2743             : 
    2744     9965063 :                   if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
    2745             :                   {
    2746        2728 :                      t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
    2747        2728 :                      token_list_.push_back(t);
    2748        2728 :                      s_itr_ += 3;
    2749        2728 :                      return;
    2750             :                   }
    2751             :                }
    2752             : 
    2753    10226617 :                token_t::token_type ttype = token_t::e_none;
    2754             : 
    2755    10226617 :                if      ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
    2756    10224401 :                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
    2757    10223721 :                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
    2758    10223631 :                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
    2759    10220676 :                else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
    2760    10158003 :                else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
    2761    10066697 :                else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
    2762    10066697 :                else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
    2763    10066697 :                else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
    2764    10056602 :                else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
    2765    10055550 :                else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
    2766    10055210 :                else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
    2767    10054873 :                else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
    2768             : 
    2769    10226617 :                if (token_t::e_none != ttype)
    2770             :                {
    2771      171819 :                   t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
    2772      171819 :                   token_list_.push_back(t);
    2773      171819 :                   s_itr_ += 2;
    2774      171819 :                   return;
    2775             :                }
    2776             :             }
    2777             : 
    2778    10379011 :             if ('<' == c0)
    2779        7467 :                t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
    2780    10371544 :             else if ('>' == c0)
    2781        6963 :                t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
    2782    10364581 :             else if (';' == c0)
    2783      124270 :                t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
    2784    10240311 :             else if ('&' == c0)
    2785         657 :                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
    2786    10239654 :             else if ('|' == c0)
    2787         420 :                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
    2788             :             else
    2789    10239234 :                t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
    2790             : 
    2791    10379011 :             token_list_.push_back(t);
    2792    10379011 :             ++s_itr_;
    2793    10553558 :          }
    2794             : 
    2795     3316561 :          inline void scan_symbol()
    2796             :          {
    2797     3316561 :             details::char_cptr initial_itr = s_itr_;
    2798             : 
    2799     9077959 :             while (!is_end(s_itr_))
    2800             :             {
    2801     9065759 :                if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
    2802             :                {
    2803     3305881 :                   if ('.' != (*s_itr_))
    2804     3304361 :                      break;
    2805             :                   /*
    2806             :                      Permit symbols that contain a 'dot'
    2807             :                      Allowed   : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
    2808             :                      Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
    2809             :                   */
    2810        1520 :                   if (
    2811        3040 :                        (s_itr_ != initial_itr)                     &&
    2812        1520 :                        !is_end(s_itr_ + 1)                         &&
    2813        3040 :                        !details::is_letter_or_digit(*(s_itr_ + 1)) &&
    2814           0 :                        ('_' != (*(s_itr_ + 1)))
    2815             :                      )
    2816           0 :                      break;
    2817             :                }
    2818             : 
    2819     5761398 :                ++s_itr_;
    2820             :             }
    2821             : 
    2822     3316561 :             token_t t;
    2823     3316561 :             t.set_symbol(initial_itr, s_itr_, base_itr_);
    2824     3316561 :             token_list_.push_back(t);
    2825     3316561 :          }
    2826             : 
    2827     2040076 :          inline void scan_number()
    2828             :          {
    2829             :             /*
    2830             :                Attempt to match a valid numeric value in one of the following formats:
    2831             :                (01) 123456
    2832             :                (02) 123456.
    2833             :                (03) 123.456
    2834             :                (04) 123.456e3
    2835             :                (05) 123.456E3
    2836             :                (06) 123.456e+3
    2837             :                (07) 123.456E+3
    2838             :                (08) 123.456e-3
    2839             :                (09) 123.456E-3
    2840             :                (00) .1234
    2841             :                (11) .1234e3
    2842             :                (12) .1234E+3
    2843             :                (13) .1234e+3
    2844             :                (14) .1234E-3
    2845             :                (15) .1234e-3
    2846             :             */
    2847             : 
    2848     2040076 :             details::char_cptr initial_itr = s_itr_;
    2849     2040076 :             bool dot_found                 = false;
    2850     2040076 :             bool e_found                   = false;
    2851     2040076 :             bool post_e_sign_found         = false;
    2852     2040076 :             bool post_e_digit_found        = false;
    2853     2040076 :             token_t t;
    2854             : 
    2855    19064804 :             while (!is_end(s_itr_))
    2856             :             {
    2857    19049145 :                if ('.' == (*s_itr_))
    2858             :                {
    2859     1464717 :                   if (dot_found)
    2860             :                   {
    2861           0 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2862           0 :                      token_list_.push_back(t);
    2863             : 
    2864           0 :                      return;
    2865             :                   }
    2866             : 
    2867     1464717 :                   dot_found = true;
    2868     1464717 :                   ++s_itr_;
    2869             : 
    2870     1464717 :                   continue;
    2871             :                }
    2872    17584428 :                else if ('e' == std::tolower(*s_itr_))
    2873             :                {
    2874        1095 :                   const char_t& c = *(s_itr_ + 1);
    2875             : 
    2876        1095 :                   if (is_end(s_itr_ + 1))
    2877             :                   {
    2878           0 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2879           0 :                      token_list_.push_back(t);
    2880             : 
    2881           0 :                      return;
    2882             :                   }
    2883        1095 :                   else if (
    2884        1383 :                             ('+' != c) &&
    2885        1330 :                             ('-' != c) &&
    2886         235 :                             !details::is_digit(c)
    2887             :                           )
    2888             :                   {
    2889          60 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2890          60 :                      token_list_.push_back(t);
    2891             : 
    2892          60 :                      return;
    2893             :                   }
    2894             : 
    2895        1035 :                   e_found = true;
    2896        1035 :                   ++s_itr_;
    2897             : 
    2898        1035 :                   continue;
    2899        1035 :                }
    2900    17583333 :                else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
    2901             :                {
    2902         860 :                   if (post_e_sign_found)
    2903             :                   {
    2904           0 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2905           0 :                      token_list_.push_back(t);
    2906             : 
    2907           0 :                      return;
    2908             :                   }
    2909             : 
    2910         860 :                   post_e_sign_found = true;
    2911         860 :                   ++s_itr_;
    2912             : 
    2913         860 :                   continue;
    2914             :                }
    2915    17582473 :                else if (e_found && details::is_digit(*s_itr_))
    2916             :                {
    2917        1133 :                   post_e_digit_found = true;
    2918        1133 :                   ++s_itr_;
    2919             : 
    2920        1133 :                   continue;
    2921             :                }
    2922    17581340 :                else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
    2923     2024357 :                   break;
    2924             :                else
    2925    15556983 :                   ++s_itr_;
    2926             :             }
    2927             : 
    2928     2040016 :             t.set_numeric(initial_itr, s_itr_, base_itr_);
    2929     2040016 :             token_list_.push_back(t);
    2930             : 
    2931     2040016 :             return;
    2932     2040076 :          }
    2933             : 
    2934        4245 :          inline void scan_special_function()
    2935             :          {
    2936        4245 :             details::char_cptr initial_itr = s_itr_;
    2937        4245 :             token_t t;
    2938             : 
    2939             :             // $fdd(x,x,x) = at least 11 chars
    2940        8490 :             if (std::distance(s_itr_,s_end_) < 11)
    2941             :             {
    2942           0 :                t.set_error(
    2943             :                   token::e_err_sfunc,
    2944           0 :                   initial_itr, std::min(initial_itr + 11, s_end_),
    2945             :                   base_itr_);
    2946           0 :                token_list_.push_back(t);
    2947             : 
    2948           0 :                return;
    2949             :             }
    2950             : 
    2951        4245 :             if (
    2952        8490 :                  !(('$' == *s_itr_)                       &&
    2953        4245 :                    (details::imatch  ('f',*(s_itr_ + 1))) &&
    2954        4245 :                    (details::is_digit(*(s_itr_ + 2)))     &&
    2955        4245 :                    (details::is_digit(*(s_itr_ + 3))))
    2956             :                )
    2957             :             {
    2958           0 :                t.set_error(
    2959             :                   token::e_err_sfunc,
    2960           0 :                   initial_itr, std::min(initial_itr + 4, s_end_),
    2961             :                   base_itr_);
    2962           0 :                token_list_.push_back(t);
    2963             : 
    2964           0 :                return;
    2965             :             }
    2966             : 
    2967        4245 :             s_itr_ += 4; // $fdd = 4chars
    2968             : 
    2969        4245 :             t.set_symbol(initial_itr, s_itr_, base_itr_);
    2970        4245 :             token_list_.push_back(t);
    2971             : 
    2972        4245 :             return;
    2973        4245 :          }
    2974             : 
    2975             :          #ifndef exprtk_disable_string_capabilities
    2976       53142 :          inline void scan_string()
    2977             :          {
    2978       53142 :             details::char_cptr initial_itr = s_itr_ + 1;
    2979       53142 :             token_t t;
    2980             : 
    2981      106284 :             if (std::distance(s_itr_,s_end_) < 2)
    2982             :             {
    2983           1 :                t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
    2984           1 :                token_list_.push_back(t);
    2985             : 
    2986           1 :                return;
    2987             :             }
    2988             : 
    2989       53141 :             ++s_itr_;
    2990             : 
    2991       53141 :             bool escaped_found = false;
    2992       53141 :             bool escaped = false;
    2993             : 
    2994      386419 :             while (!is_end(s_itr_))
    2995             :             {
    2996      386183 :                if (!details::is_valid_string_char(*s_itr_))
    2997             :                {
    2998           0 :                   t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    2999           0 :                   token_list_.push_back(t);
    3000             : 
    3001           0 :                   return;
    3002             :                }
    3003      386183 :                else if (!escaped && ('\\' == *s_itr_))
    3004             :                {
    3005        3050 :                   escaped_found = true;
    3006        3050 :                   escaped = true;
    3007        3050 :                   ++s_itr_;
    3008             : 
    3009        3050 :                   continue;
    3010             :                }
    3011      383133 :                else if (!escaped)
    3012             :                {
    3013      380083 :                   if ('\'' == *s_itr_)
    3014       52905 :                      break;
    3015             :                }
    3016        3050 :                else if (escaped)
    3017             :                {
    3018        3050 :                   if (
    3019        5150 :                        !is_end(s_itr_) && ('0' == *(s_itr_)) &&
    3020        2100 :                        ((s_itr_ + 4) <= s_end_)
    3021             :                      )
    3022             :                   {
    3023        2100 :                      const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1)));
    3024             : 
    3025        4200 :                      const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
    3026        2100 :                                               details::is_hex_digit(*(s_itr_ + 3)) ;
    3027             : 
    3028        2100 :                      if (!(x_separator && both_digits))
    3029             :                      {
    3030           0 :                         t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    3031           0 :                         token_list_.push_back(t);
    3032             : 
    3033           0 :                         return;
    3034             :                      }
    3035             :                      else
    3036        2100 :                         s_itr_ += 3;
    3037             :                   }
    3038             : 
    3039        3050 :                   escaped = false;
    3040             :                }
    3041             : 
    3042      330228 :                ++s_itr_;
    3043             :             }
    3044             : 
    3045       53141 :             if (is_end(s_itr_))
    3046             :             {
    3047         236 :                t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    3048         236 :                token_list_.push_back(t);
    3049             : 
    3050         236 :                return;
    3051             :             }
    3052             : 
    3053       52905 :             if (!escaped_found)
    3054       51555 :                t.set_string(initial_itr, s_itr_, base_itr_);
    3055             :             else
    3056             :             {
    3057        1350 :                std::string parsed_string(initial_itr,s_itr_);
    3058             : 
    3059        1350 :                if (!details::cleanup_escapes(parsed_string))
    3060             :                {
    3061           0 :                   t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    3062           0 :                   token_list_.push_back(t);
    3063             : 
    3064           0 :                   return;
    3065             :                }
    3066             : 
    3067        1350 :                t.set_string(
    3068             :                   parsed_string,
    3069        2700 :                   static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
    3070        1350 :             }
    3071             : 
    3072       52905 :             token_list_.push_back(t);
    3073       52905 :             ++s_itr_;
    3074             : 
    3075       52905 :             return;
    3076       53142 :          }
    3077             :          #endif
    3078             : 
    3079             :       private:
    3080             : 
    3081             :          token_list_t       token_list_;
    3082             :          token_list_itr_t   token_itr_;
    3083             :          token_list_itr_t   store_token_itr_;
    3084             :          token_t            eof_token_;
    3085             :          details::char_cptr base_itr_;
    3086             :          details::char_cptr s_itr_;
    3087             :          details::char_cptr s_end_;
    3088             : 
    3089             :          friend class token_scanner;
    3090             :          friend class token_modifier;
    3091             :          friend class token_inserter;
    3092             :          friend class token_joiner;
    3093             :       }; // class generator
    3094             : 
    3095             :       class helper_interface
    3096             :       {
    3097             :       public:
    3098             : 
    3099           0 :          virtual void init()                     {              }
    3100     2260727 :          virtual void reset()                    {              }
    3101     1519578 :          virtual bool result()                   { return true; }
    3102           0 :          virtual std::size_t process(generator&) { return 0;    }
    3103      869280 :          virtual ~helper_interface()             {              }
    3104             :       };
    3105             : 
    3106             :       class token_scanner : public helper_interface
    3107             :       {
    3108             :       public:
    3109             : 
    3110      434640 :          virtual ~token_scanner()
    3111      434640 :          {}
    3112             : 
    3113      434640 :          explicit token_scanner(const std::size_t& stride)
    3114      434640 :          : stride_(stride)
    3115             :          {
    3116      434640 :             if (stride > 4)
    3117             :             {
    3118           0 :                throw std::invalid_argument("token_scanner() - Invalid stride value");
    3119             :             }
    3120      434640 :          }
    3121             : 
    3122     1500929 :          inline std::size_t process(generator& g) exprtk_override
    3123             :          {
    3124     1500929 :             if (g.token_list_.size() >= stride_)
    3125             :             {
    3126    60774246 :                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
    3127             :                {
    3128    59280391 :                   token t;
    3129             : 
    3130    59280391 :                   switch (stride_)
    3131             :                   {
    3132    31841817 :                      case 1 :
    3133             :                               {
    3134    31841817 :                                  const token& t0 = g.token_list_[i];
    3135             : 
    3136    31841817 :                                  if (!operator()(t0))
    3137             :                                  {
    3138        4797 :                                     return i;
    3139             :                                  }
    3140             :                               }
    3141    31837020 :                               break;
    3142             : 
    3143    13981404 :                      case 2 :
    3144             :                               {
    3145    13981404 :                                  const token& t0 = g.token_list_[i    ];
    3146    13981404 :                                  const token& t1 = g.token_list_[i + 1];
    3147             : 
    3148    13981404 :                                  if (!operator()(t0, t1))
    3149             :                                  {
    3150           0 :                                     return i;
    3151             :                                  }
    3152             :                               }
    3153    13981404 :                               break;
    3154             : 
    3155    13457170 :                      case 3 :
    3156             :                               {
    3157    13457170 :                                  const token& t0 = g.token_list_[i    ];
    3158    13457170 :                                  const token& t1 = g.token_list_[i + 1];
    3159    13457170 :                                  const token& t2 = g.token_list_[i + 2];
    3160             : 
    3161    13457170 :                                  if (!operator()(t0, t1, t2))
    3162             :                                  {
    3163           0 :                                     return i;
    3164             :                                  }
    3165             :                               }
    3166    13457170 :                               break;
    3167             : 
    3168           0 :                      case 4 :
    3169             :                               {
    3170           0 :                                  const token& t0 = g.token_list_[i    ];
    3171           0 :                                  const token& t1 = g.token_list_[i + 1];
    3172           0 :                                  const token& t2 = g.token_list_[i + 2];
    3173           0 :                                  const token& t3 = g.token_list_[i + 3];
    3174             : 
    3175           0 :                                  if (!operator()(t0, t1, t2, t3))
    3176             :                                  {
    3177           0 :                                     return i;
    3178             :                                  }
    3179             :                               }
    3180           0 :                               break;
    3181             :                   }
    3182    59280391 :                }
    3183             :             }
    3184             : 
    3185     1496132 :             return (g.token_list_.size() - stride_ + 1);
    3186             :          }
    3187             : 
    3188           0 :          virtual bool operator() (const token&)
    3189             :          {
    3190           0 :             return false;
    3191             :          }
    3192             : 
    3193           0 :          virtual bool operator() (const token&, const token&)
    3194             :          {
    3195           0 :             return false;
    3196             :          }
    3197             : 
    3198           0 :          virtual bool operator() (const token&, const token&, const token&)
    3199             :          {
    3200           0 :             return false;
    3201             :          }
    3202             : 
    3203           0 :          virtual bool operator() (const token&, const token&, const token&, const token&)
    3204             :          {
    3205           0 :             return false;
    3206             :          }
    3207             : 
    3208             :       private:
    3209             : 
    3210             :          const std::size_t stride_;
    3211             :       }; // class token_scanner
    3212             : 
    3213             :       class token_modifier : public helper_interface
    3214             :       {
    3215             :       public:
    3216             : 
    3217      379897 :          inline std::size_t process(generator& g) exprtk_override
    3218             :          {
    3219      379897 :             std::size_t changes = 0;
    3220             : 
    3221    16427929 :             for (std::size_t i = 0; i < g.token_list_.size(); ++i)
    3222             :             {
    3223    16048032 :                if (modify(g.token_list_[i])) changes++;
    3224             :             }
    3225             : 
    3226      379897 :             return changes;
    3227             :          }
    3228             : 
    3229             :          virtual bool modify(token& t) = 0;
    3230             :       };
    3231             : 
    3232             :       class token_inserter : public helper_interface
    3233             :       {
    3234             :       public:
    3235             : 
    3236      108660 :          explicit token_inserter(const std::size_t& stride)
    3237      108660 :          : stride_(stride)
    3238             :          {
    3239      108660 :             if (stride > 5)
    3240             :             {
    3241           0 :                throw std::invalid_argument("token_inserter() - Invalid stride value");
    3242             :             }
    3243      108660 :          }
    3244             : 
    3245      379887 :          inline std::size_t process(generator& g) exprtk_override
    3246             :          {
    3247      379887 :             if (g.token_list_.empty())
    3248           0 :                return 0;
    3249      379887 :             else if (g.token_list_.size() < stride_)
    3250         708 :                return 0;
    3251             : 
    3252      379179 :             std::size_t changes = 0;
    3253             : 
    3254             :             typedef std::pair<std::size_t, token> insert_t;
    3255      379179 :             std::vector<insert_t> insert_list;
    3256      379179 :             insert_list.reserve(10000);
    3257             : 
    3258    15903698 :             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
    3259             :             {
    3260    15524519 :                int insert_index = -1;
    3261    15524519 :                token t;
    3262             : 
    3263    15524519 :                switch (stride_)
    3264             :                {
    3265           0 :                   case 1 : insert_index = insert(g.token_list_[i],t);
    3266           0 :                            break;
    3267             : 
    3268    15524519 :                   case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
    3269    15524519 :                            break;
    3270             : 
    3271           0 :                   case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
    3272           0 :                            break;
    3273             : 
    3274           0 :                   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);
    3275           0 :                            break;
    3276             : 
    3277           0 :                   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);
    3278           0 :                            break;
    3279             :                }
    3280             : 
    3281    15524519 :                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
    3282             :                {
    3283      151028 :                   insert_list.push_back(insert_t(i, t));
    3284      151028 :                   changes++;
    3285             :                }
    3286    15524519 :             }
    3287             : 
    3288      379179 :             if (!insert_list.empty())
    3289             :             {
    3290       37034 :                generator::token_list_t token_list;
    3291             : 
    3292       37034 :                std::size_t insert_index = 0;
    3293             : 
    3294     4782050 :                for (std::size_t i = 0; i < g.token_list_.size(); ++i)
    3295             :                {
    3296     4745016 :                   token_list.push_back(g.token_list_[i]);
    3297             : 
    3298     4745016 :                   if (
    3299     6350895 :                        (insert_index < insert_list.size()) &&
    3300     1605879 :                        (insert_list[insert_index].first == i)
    3301             :                      )
    3302             :                   {
    3303      151028 :                      token_list.push_back(insert_list[insert_index].second);
    3304      151028 :                      insert_index++;
    3305             :                   }
    3306             :                }
    3307             : 
    3308       37034 :                std::swap(g.token_list_,token_list);
    3309       37034 :             }
    3310             : 
    3311      379179 :             return changes;
    3312      379179 :          }
    3313             : 
    3314             :          #define token_inserter_empty_body \
    3315             :          {                                 \
    3316             :             return -1;                     \
    3317             :          }                                 \
    3318             : 
    3319           0 :          inline virtual int insert(const token&, token&)
    3320           0 :          token_inserter_empty_body
    3321             : 
    3322           0 :          inline virtual int insert(const token&, const token&, token&)
    3323           0 :          token_inserter_empty_body
    3324             : 
    3325           0 :          inline virtual int insert(const token&, const token&, const token&, token&)
    3326           0 :          token_inserter_empty_body
    3327             : 
    3328           0 :          inline virtual int insert(const token&, const token&, const token&, const token&, token&)
    3329           0 :          token_inserter_empty_body
    3330             : 
    3331           0 :          inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
    3332           0 :          token_inserter_empty_body
    3333             : 
    3334             :          #undef token_inserter_empty_body
    3335             : 
    3336             :       private:
    3337             : 
    3338             :          const std::size_t stride_;
    3339             :       };
    3340             : 
    3341             :       class token_joiner : public helper_interface
    3342             :       {
    3343             :       public:
    3344             : 
    3345      217320 :          explicit token_joiner(const std::size_t& stride)
    3346      217320 :          : stride_(stride)
    3347      217320 :          {}
    3348             : 
    3349      759794 :          inline std::size_t process(generator& g) exprtk_override
    3350             :          {
    3351      759794 :             if (g.token_list_.empty())
    3352           0 :                return 0;
    3353             : 
    3354      759794 :             switch (stride_)
    3355             :             {
    3356      379897 :                case 2  : return process_stride_2(g);
    3357      379897 :                case 3  : return process_stride_3(g);
    3358           0 :                default : return 0;
    3359             :             }
    3360             :          }
    3361             : 
    3362           0 :          virtual bool join(const token&, const token&, token&)               { return false; }
    3363           0 :          virtual bool join(const token&, const token&, const token&, token&) { return false; }
    3364             : 
    3365             :       private:
    3366             : 
    3367      379897 :          inline std::size_t process_stride_2(generator& g)
    3368             :          {
    3369      379897 :             if (g.token_list_.size() < 2)
    3370         708 :                return 0;
    3371             : 
    3372      379189 :             std::size_t changes = 0;
    3373             : 
    3374      379189 :             generator::token_list_t token_list;
    3375      379189 :             token_list.reserve(10000);
    3376             : 
    3377    16041449 :             for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
    3378             :             {
    3379    15662260 :                token t;
    3380             : 
    3381             :                for ( ; ; )
    3382             :                {
    3383    15668531 :                   if (!join(g[i], g[i + 1], t))
    3384             :                   {
    3385    15661214 :                      token_list.push_back(g[i]);
    3386    15661214 :                      break;
    3387             :                   }
    3388             : 
    3389        7317 :                   token_list.push_back(t);
    3390             : 
    3391        7317 :                   ++changes;
    3392             : 
    3393        7317 :                   i += 2;
    3394             : 
    3395        7317 :                   if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1))
    3396        1046 :                      break;
    3397             :                }
    3398    15662260 :             }
    3399             : 
    3400      379189 :             token_list.push_back(g.token_list_.back());
    3401             : 
    3402      379189 :             assert(token_list.size() <= g.token_list_.size());
    3403             : 
    3404      379189 :             std::swap(token_list, g.token_list_);
    3405             : 
    3406      379189 :             return changes;
    3407      379189 :          }
    3408             : 
    3409      379897 :          inline std::size_t process_stride_3(generator& g)
    3410             :          {
    3411      379897 :             if (g.token_list_.size() < 3)
    3412        1577 :                return 0;
    3413             : 
    3414      378320 :             std::size_t changes = 0;
    3415             : 
    3416      378320 :             generator::token_list_t token_list;
    3417      378320 :             token_list.reserve(10000);
    3418             : 
    3419    15667068 :             for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
    3420             :             {
    3421    15288748 :                token t;
    3422             : 
    3423             :                for ( ; ; )
    3424             :                {
    3425    15288946 :                   if (!join(g[i], g[i + 1], g[i + 2], t))
    3426             :                   {
    3427    15288746 :                      token_list.push_back(g[i]);
    3428    15288746 :                      break;
    3429             :                   }
    3430             : 
    3431         200 :                   token_list.push_back(t);
    3432             : 
    3433         200 :                   ++changes;
    3434             : 
    3435         200 :                   i += 3;
    3436             : 
    3437         200 :                   if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2))
    3438           2 :                      break;
    3439             :                }
    3440    15288748 :             }
    3441             : 
    3442      378320 :             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
    3443      378320 :             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
    3444             : 
    3445      378320 :             assert(token_list.size() <= g.token_list_.size());
    3446             : 
    3447      378320 :             std::swap(token_list, g.token_list_);
    3448             : 
    3449      378320 :             return changes;
    3450      378320 :          }
    3451             : 
    3452             :          const std::size_t stride_;
    3453             :       };
    3454             : 
    3455             :       namespace helper
    3456             :       {
    3457             : 
    3458             :          inline void dump(const lexer::generator& generator)
    3459             :          {
    3460             :             for (std::size_t i = 0; i < generator.size(); ++i)
    3461             :             {
    3462             :                const lexer::token& t = generator[i];
    3463             :                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
    3464             :                       static_cast<int>(i),
    3465             :                       static_cast<int>(t.position),
    3466             :                       t.to_str(t.type).c_str(),
    3467             :                       t.value.c_str());
    3468             :             }
    3469             :          }
    3470             : 
    3471             :          class commutative_inserter : public lexer::token_inserter
    3472             :          {
    3473             :          public:
    3474             : 
    3475             :             using lexer::token_inserter::insert;
    3476             : 
    3477      108660 :             commutative_inserter()
    3478      108660 :             : lexer::token_inserter(2)
    3479      108660 :             {}
    3480             : 
    3481     3585747 :             inline void ignore_symbol(const std::string& symbol)
    3482             :             {
    3483     3585747 :                ignore_set_.insert(symbol);
    3484     3585747 :             }
    3485             : 
    3486    15524519 :             inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override
    3487             :             {
    3488    15524519 :                bool match         = false;
    3489    15524519 :                new_token.type     = lexer::token::e_mul;
    3490    15524519 :                new_token.value    = "*";
    3491    15524519 :                new_token.position = t1.position;
    3492             : 
    3493    15524519 :                if (t0.type == lexer::token::e_symbol)
    3494             :                {
    3495     3304699 :                   if (ignore_set_.end() != ignore_set_.find(t0.value))
    3496             :                   {
    3497      136807 :                      return -1;
    3498             :                   }
    3499     3167892 :                   else if (!t0.value.empty() && ('$' == t0.value[0]))
    3500             :                   {
    3501        4245 :                      return -1;
    3502             :                   }
    3503             :                }
    3504             : 
    3505    15383467 :                if (t1.type == lexer::token::e_symbol)
    3506             :                {
    3507     2909588 :                   if (ignore_set_.end() != ignore_set_.find(t1.value))
    3508             :                   {
    3509      101872 :                      return -1;
    3510             :                   }
    3511             :                }
    3512    15281595 :                if      ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
    3513    15178385 :                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
    3514    15136577 :                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
    3515    15136530 :                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
    3516    15136483 :                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
    3517    15136439 :                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
    3518    15135153 :                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
    3519    15135107 :                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
    3520    15135061 :                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
    3521    15130783 :                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
    3522    15130726 :                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
    3523    15130671 :                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_symbol     )) match = true;
    3524             : 
    3525    15281595 :                return (match) ? 1 : -1;
    3526             :             }
    3527             : 
    3528             :          private:
    3529             : 
    3530             :             std::set<std::string,details::ilesscompare> ignore_set_;
    3531             :          };
    3532             : 
    3533             :          class operator_joiner exprtk_final : public token_joiner
    3534             :          {
    3535             :          public:
    3536             : 
    3537      217320 :             explicit operator_joiner(const std::size_t& stride)
    3538      217320 :             : token_joiner(stride)
    3539      217320 :             {}
    3540             : 
    3541    15668531 :             inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override
    3542             :             {
    3543             :                // ': =' --> ':='
    3544    15668531 :                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
    3545             :                {
    3546           0 :                   t.type     = lexer::token::e_assign;
    3547           0 :                   t.value    = ":=";
    3548           0 :                   t.position = t0.position;
    3549             : 
    3550           0 :                   return true;
    3551             :                }
    3552             :                // '+ =' --> '+='
    3553    15668531 :                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
    3554             :                {
    3555           0 :                   t.type     = lexer::token::e_addass;
    3556           0 :                   t.value    = "+=";
    3557           0 :                   t.position = t0.position;
    3558             : 
    3559           0 :                   return true;
    3560             :                }
    3561             :                // '- =' --> '-='
    3562    15668531 :                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
    3563             :                {
    3564           0 :                   t.type     = lexer::token::e_subass;
    3565           0 :                   t.value    = "-=";
    3566           0 :                   t.position = t0.position;
    3567             : 
    3568           0 :                   return true;
    3569             :                }
    3570             :                // '* =' --> '*='
    3571    15668531 :                else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
    3572             :                {
    3573           0 :                   t.type     = lexer::token::e_mulass;
    3574           0 :                   t.value    = "*=";
    3575           0 :                   t.position = t0.position;
    3576             : 
    3577           0 :                   return true;
    3578             :                }
    3579             :                // '/ =' --> '/='
    3580    15668531 :                else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
    3581             :                {
    3582           0 :                   t.type     = lexer::token::e_divass;
    3583           0 :                   t.value    = "/=";
    3584           0 :                   t.position = t0.position;
    3585             : 
    3586           0 :                   return true;
    3587             :                }
    3588             :                // '% =' --> '%='
    3589    15668531 :                else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
    3590             :                {
    3591           0 :                   t.type     = lexer::token::e_modass;
    3592           0 :                   t.value    = "%=";
    3593           0 :                   t.position = t0.position;
    3594             : 
    3595           0 :                   return true;
    3596             :                }
    3597             :                // '> =' --> '>='
    3598    15668531 :                else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
    3599             :                {
    3600           0 :                   t.type     = lexer::token::e_gte;
    3601           0 :                   t.value    = ">=";
    3602           0 :                   t.position = t0.position;
    3603             : 
    3604           0 :                   return true;
    3605             :                }
    3606             :                // '< =' --> '<='
    3607    15668531 :                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
    3608             :                {
    3609           0 :                   t.type     = lexer::token::e_lte;
    3610           0 :                   t.value    = "<=";
    3611           0 :                   t.position = t0.position;
    3612             : 
    3613           0 :                   return true;
    3614             :                }
    3615             :                // '= =' --> '=='
    3616    15668531 :                else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
    3617             :                {
    3618           4 :                   t.type     = lexer::token::e_eq;
    3619           4 :                   t.value    = "==";
    3620           4 :                   t.position = t0.position;
    3621             : 
    3622           4 :                   return true;
    3623             :                }
    3624             :                // '! =' --> '!='
    3625    15668527 :                else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
    3626             :                {
    3627           0 :                   t.type     = lexer::token::e_ne;
    3628           0 :                   t.value    = "!=";
    3629           0 :                   t.position = t0.position;
    3630             : 
    3631           0 :                   return true;
    3632             :                }
    3633             :                // '< >' --> '<>'
    3634    15668527 :                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
    3635             :                {
    3636           0 :                   t.type     = lexer::token::e_ne;
    3637           0 :                   t.value    = "<>";
    3638           0 :                   t.position = t0.position;
    3639             : 
    3640           0 :                   return true;
    3641             :                }
    3642             :                // '<= >' --> '<=>'
    3643    15668527 :                else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
    3644             :                {
    3645           0 :                   t.type     = lexer::token::e_swap;
    3646           0 :                   t.value    = "<=>";
    3647           0 :                   t.position = t0.position;
    3648             : 
    3649           0 :                   return true;
    3650             :                }
    3651             :                // '+ -' --> '-'
    3652    15668527 :                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
    3653             :                {
    3654        3618 :                   t.type     = lexer::token::e_sub;
    3655        3618 :                   t.value    = "-";
    3656        3618 :                   t.position = t0.position;
    3657             : 
    3658        3618 :                   return true;
    3659             :                }
    3660             :                // '- +' --> '-'
    3661    15664909 :                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
    3662             :                {
    3663          39 :                   t.type     = lexer::token::e_sub;
    3664          39 :                   t.value    = "-";
    3665          39 :                   t.position = t0.position;
    3666             : 
    3667          39 :                   return true;
    3668             :                }
    3669             :                // '- -' --> '+'
    3670    15664870 :                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
    3671             :                {
    3672             :                   /*
    3673             :                      Note: May need to reconsider this when wanting to implement
    3674             :                      pre/postfix decrement operator
    3675             :                   */
    3676        3656 :                   t.type     = lexer::token::e_add;
    3677        3656 :                   t.value    = "+";
    3678        3656 :                   t.position = t0.position;
    3679             : 
    3680        3656 :                   return true;
    3681             :                }
    3682             :                else
    3683    15661214 :                   return false;
    3684             :             }
    3685             : 
    3686    15288946 :             inline bool join(const lexer::token& t0,
    3687             :                              const lexer::token& t1,
    3688             :                              const lexer::token& t2,
    3689             :                              lexer::token& t) exprtk_override
    3690             :             {
    3691             :                // '[ * ]' --> '[*]'
    3692    15288946 :                if (
    3693    15288946 :                     (t0.type == lexer::token::e_lsqrbracket) &&
    3694       98801 :                     (t1.type == lexer::token::e_mul        ) &&
    3695         210 :                     (t2.type == lexer::token::e_rsqrbracket)
    3696             :                   )
    3697             :                {
    3698         200 :                   t.type     = lexer::token::e_symbol;
    3699         200 :                   t.value    = "[*]";
    3700         200 :                   t.position = t0.position;
    3701             : 
    3702         200 :                   return true;
    3703             :                }
    3704             :                else
    3705    15288746 :                   return false;
    3706             :             }
    3707             :          };
    3708             : 
    3709             :          class bracket_checker exprtk_final : public lexer::token_scanner
    3710             :          {
    3711             :          public:
    3712             : 
    3713             :             using lexer::token_scanner::operator();
    3714             : 
    3715      108660 :             bracket_checker()
    3716           0 :             : token_scanner(1)
    3717      108660 :             , state_(true)
    3718      108660 :             {}
    3719             : 
    3720      379883 :             bool result() exprtk_override
    3721             :             {
    3722      379883 :                if (!stack_.empty())
    3723             :                {
    3724        5025 :                   lexer::token t;
    3725        5025 :                   t.value      = stack_.top().first;
    3726        5025 :                   t.position   = stack_.top().second;
    3727        5025 :                   error_token_ = t;
    3728        5025 :                   state_       = false;
    3729             : 
    3730        5025 :                   return false;
    3731        5025 :                }
    3732             :                else
    3733      374858 :                   return state_;
    3734             :             }
    3735             : 
    3736       17788 :             lexer::token error_token()
    3737             :             {
    3738       17788 :                return error_token_;
    3739             :             }
    3740             : 
    3741      379883 :             void reset() exprtk_override
    3742             :             {
    3743             :                // Why? because msvc doesn't support swap properly.
    3744      379883 :                stack_ = std::stack<std::pair<char,std::size_t> >();
    3745      379883 :                state_ = true;
    3746      379883 :                error_token_.clear();
    3747      379883 :             }
    3748             : 
    3749    15793785 :             bool operator() (const lexer::token& t) exprtk_override
    3750             :             {
    3751    15793785 :                if (
    3752    15793785 :                     !t.value.empty()                       &&
    3753    15784335 :                     (lexer::token::e_string != t.type)     &&
    3754    44062692 :                     (lexer::token::e_symbol != t.type)     &&
    3755    12484572 :                     exprtk::details::is_bracket(t.value[0])
    3756             :                   )
    3757             :                {
    3758     6142767 :                   details::char_t c = t.value[0];
    3759             : 
    3760     6142767 :                   if      (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));
    3761     3206663 :                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
    3762     3163373 :                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
    3763     3064488 :                   else if (exprtk::details::is_right_bracket(c))
    3764             :                   {
    3765     3064488 :                      if (stack_.empty())
    3766             :                      {
    3767        3869 :                         state_       = false;
    3768        3869 :                         error_token_ = t;
    3769             : 
    3770        3869 :                         return false;
    3771             :                      }
    3772     3060619 :                      else if (c != stack_.top().first)
    3773             :                      {
    3774         928 :                         state_       = false;
    3775         928 :                         error_token_ = t;
    3776             : 
    3777         928 :                         return false;
    3778             :                      }
    3779             :                      else
    3780     3059691 :                         stack_.pop();
    3781             :                   }
    3782             :                }
    3783             : 
    3784    15788988 :                return true;
    3785             :             }
    3786             : 
    3787             :          private:
    3788             : 
    3789             :             bool state_;
    3790             :             std::stack<std::pair<char,std::size_t> > stack_;
    3791             :             lexer::token error_token_;
    3792             :          };
    3793             : 
    3794             :          template <typename T>
    3795             :          class numeric_checker exprtk_final : public lexer::token_scanner
    3796             :          {
    3797             :          public:
    3798             : 
    3799             :             using lexer::token_scanner::operator();
    3800             : 
    3801      108660 :             numeric_checker()
    3802      217320 :             : token_scanner (1)
    3803      108660 :             , current_index_(0)
    3804      108660 :             {}
    3805             : 
    3806      379897 :             bool result() exprtk_override
    3807             :             {
    3808      379897 :                return error_list_.empty();
    3809             :             }
    3810             : 
    3811      379897 :             void reset() exprtk_override
    3812             :             {
    3813      379897 :                error_list_.clear();
    3814      379897 :                current_index_ = 0;
    3815      379897 :             }
    3816             : 
    3817    16048032 :             bool operator() (const lexer::token& t) exprtk_override
    3818             :             {
    3819    16048032 :                if (token::e_number == t.type)
    3820             :                {
    3821             :                   T v;
    3822             : 
    3823     2045200 :                   if (!exprtk::details::string_to_real(t.value,v))
    3824             :                   {
    3825          14 :                      error_list_.push_back(current_index_);
    3826             :                   }
    3827             :                }
    3828             : 
    3829    16048032 :                ++current_index_;
    3830             : 
    3831    16048032 :                return true;
    3832             :             }
    3833             : 
    3834          42 :             std::size_t error_count() const
    3835             :             {
    3836          42 :                return error_list_.size();
    3837             :             }
    3838             : 
    3839          14 :             std::size_t error_index(const std::size_t& i)
    3840             :             {
    3841          14 :                if (i < error_list_.size())
    3842          14 :                   return error_list_[i];
    3843             :                else
    3844           0 :                   return std::numeric_limits<std::size_t>::max();
    3845             :             }
    3846             : 
    3847          14 :             void clear_errors()
    3848             :             {
    3849          14 :                error_list_.clear();
    3850          14 :             }
    3851             : 
    3852             :          private:
    3853             : 
    3854             :             std::size_t current_index_;
    3855             :             std::vector<std::size_t> error_list_;
    3856             :          };
    3857             : 
    3858             :          class symbol_replacer exprtk_final : public lexer::token_modifier
    3859             :          {
    3860             :          private:
    3861             : 
    3862             :             typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
    3863             : 
    3864             :          public:
    3865             : 
    3866             :             bool remove(const std::string& target_symbol)
    3867             :             {
    3868             :                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
    3869             : 
    3870             :                if (replace_map_.end() == itr)
    3871             :                   return false;
    3872             : 
    3873             :                replace_map_.erase(itr);
    3874             : 
    3875             :                return true;
    3876             :             }
    3877             : 
    3878      220520 :             bool add_replace(const std::string& target_symbol,
    3879             :                              const std::string& replace_symbol,
    3880             :                              const lexer::token::token_type token_type = lexer::token::e_symbol)
    3881             :             {
    3882      220520 :                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
    3883             : 
    3884      220520 :                if (replace_map_.end() != itr)
    3885             :                {
    3886           0 :                   return false;
    3887             :                }
    3888             : 
    3889      220520 :                replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
    3890             : 
    3891      220520 :                return true;
    3892             :             }
    3893             : 
    3894      108660 :             void clear()
    3895             :             {
    3896      108660 :                replace_map_.clear();
    3897      108660 :             }
    3898             : 
    3899             :          private:
    3900             : 
    3901    16048032 :             bool modify(lexer::token& t) exprtk_override
    3902             :             {
    3903    16048032 :                if (lexer::token::e_symbol == t.type)
    3904             :                {
    3905     3321359 :                   if (replace_map_.empty())
    3906       15993 :                      return false;
    3907             : 
    3908     3321359 :                   const replace_map_t::iterator itr = replace_map_.find(t.value);
    3909             : 
    3910     3321359 :                   if (replace_map_.end() != itr)
    3911             :                   {
    3912       15993 :                      t.value = itr->second.first;
    3913       15993 :                      t.type  = itr->second.second;
    3914             : 
    3915       15993 :                      return true;
    3916             :                   }
    3917             :                }
    3918             : 
    3919    16032039 :                return false;
    3920             :             }
    3921             : 
    3922             :             replace_map_t replace_map_;
    3923             :          };
    3924             : 
    3925             :          class sequence_validator exprtk_final : public lexer::token_scanner
    3926             :          {
    3927             :          private:
    3928             : 
    3929             :             typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
    3930             :             typedef std::set<token_pair_t> set_t;
    3931             : 
    3932             :          public:
    3933             : 
    3934             :             using lexer::token_scanner::operator();
    3935             : 
    3936      108660 :             sequence_validator()
    3937      108660 :             : lexer::token_scanner(2)
    3938             :             {
    3939      108660 :                add_invalid(lexer::token::e_number, lexer::token::e_number);
    3940      108660 :                add_invalid(lexer::token::e_string, lexer::token::e_string);
    3941      108660 :                add_invalid(lexer::token::e_number, lexer::token::e_string);
    3942      108660 :                add_invalid(lexer::token::e_string, lexer::token::e_number);
    3943             : 
    3944      108660 :                add_invalid_set1(lexer::token::e_assign );
    3945      108660 :                add_invalid_set1(lexer::token::e_shr    );
    3946      108660 :                add_invalid_set1(lexer::token::e_shl    );
    3947      108660 :                add_invalid_set1(lexer::token::e_lte    );
    3948      108660 :                add_invalid_set1(lexer::token::e_ne     );
    3949      108660 :                add_invalid_set1(lexer::token::e_gte    );
    3950      108660 :                add_invalid_set1(lexer::token::e_lt     );
    3951      108660 :                add_invalid_set1(lexer::token::e_gt     );
    3952      108660 :                add_invalid_set1(lexer::token::e_eq     );
    3953      108660 :                add_invalid_set1(lexer::token::e_comma  );
    3954      108660 :                add_invalid_set1(lexer::token::e_add    );
    3955      108660 :                add_invalid_set1(lexer::token::e_sub    );
    3956      108660 :                add_invalid_set1(lexer::token::e_div    );
    3957      108660 :                add_invalid_set1(lexer::token::e_mul    );
    3958      108660 :                add_invalid_set1(lexer::token::e_mod    );
    3959      108660 :                add_invalid_set1(lexer::token::e_pow    );
    3960      108660 :                add_invalid_set1(lexer::token::e_colon  );
    3961      108660 :                add_invalid_set1(lexer::token::e_ternary);
    3962      108660 :             }
    3963             : 
    3964      370989 :             bool result() exprtk_override
    3965             :             {
    3966      370989 :                return error_list_.empty();
    3967             :             }
    3968             : 
    3969    13981404 :             bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override
    3970             :             {
    3971    13981404 :                const set_t::value_type p = std::make_pair(t0.type,t1.type);
    3972             : 
    3973    13981404 :                if (invalid_bracket_check(t0.type,t1.type))
    3974             :                {
    3975         559 :                   error_list_.push_back(std::make_pair(t0,t1));
    3976             :                }
    3977    13980845 :                else if (invalid_comb_.find(p) != invalid_comb_.end())
    3978             :                {
    3979         443 :                   error_list_.push_back(std::make_pair(t0,t1));
    3980             :                }
    3981             : 
    3982    13981404 :                return true;
    3983             :             }
    3984             : 
    3985        2660 :             std::size_t error_count() const
    3986             :             {
    3987        2660 :                return error_list_.size();
    3988             :             }
    3989             : 
    3990        1002 :             std::pair<lexer::token,lexer::token> error(const std::size_t index)
    3991             :             {
    3992        1002 :                if (index < error_list_.size())
    3993             :                {
    3994        1002 :                   return error_list_[index];
    3995             :                }
    3996             :                else
    3997             :                {
    3998           0 :                   static const lexer::token error_token;
    3999           0 :                   return std::make_pair(error_token,error_token);
    4000             :                }
    4001             :             }
    4002             : 
    4003         829 :             void clear_errors()
    4004             :             {
    4005         829 :                error_list_.clear();
    4006         829 :             }
    4007             : 
    4008             :          private:
    4009             : 
    4010    29772840 :             void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t)
    4011             :             {
    4012    29772840 :                invalid_comb_.insert(std::make_pair(base,t));
    4013    29772840 :             }
    4014             : 
    4015     1955880 :             void add_invalid_set1(const lexer::token::token_type t)
    4016             :             {
    4017     1955880 :                add_invalid(t, lexer::token::e_assign);
    4018     1955880 :                add_invalid(t, lexer::token::e_shr   );
    4019     1955880 :                add_invalid(t, lexer::token::e_shl   );
    4020     1955880 :                add_invalid(t, lexer::token::e_lte   );
    4021     1955880 :                add_invalid(t, lexer::token::e_ne    );
    4022     1955880 :                add_invalid(t, lexer::token::e_gte   );
    4023     1955880 :                add_invalid(t, lexer::token::e_lt    );
    4024     1955880 :                add_invalid(t, lexer::token::e_gt    );
    4025     1955880 :                add_invalid(t, lexer::token::e_eq    );
    4026     1955880 :                add_invalid(t, lexer::token::e_comma );
    4027     1955880 :                add_invalid(t, lexer::token::e_div   );
    4028     1955880 :                add_invalid(t, lexer::token::e_mul   );
    4029     1955880 :                add_invalid(t, lexer::token::e_mod   );
    4030     1955880 :                add_invalid(t, lexer::token::e_pow   );
    4031     1955880 :                add_invalid(t, lexer::token::e_colon );
    4032     1955880 :             }
    4033             : 
    4034    13981404 :             bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t)
    4035             :             {
    4036    13981404 :                if (details::is_right_bracket(static_cast<details::char_t>(base)))
    4037             :                {
    4038     2418152 :                   switch (t)
    4039             :                   {
    4040       29259 :                      case lexer::token::e_assign : return (']' != base);
    4041          35 :                      case lexer::token::e_string : return (')' != base);
    4042     2388858 :                      default                     : return false;
    4043             :                   }
    4044             :                }
    4045    11563252 :                else if (details::is_left_bracket(static_cast<details::char_t>(base)))
    4046             :                {
    4047     2734279 :                   if (details::is_right_bracket(static_cast<details::char_t>(t)))
    4048       11677 :                      return false;
    4049     2722602 :                   else if (details::is_left_bracket(static_cast<details::char_t>(t)))
    4050     1217665 :                      return false;
    4051             :                   else
    4052             :                   {
    4053     1504937 :                      switch (t)
    4054             :                      {
    4055      581566 :                         case lexer::token::e_number  : return false;
    4056      818586 :                         case lexer::token::e_symbol  : return false;
    4057        3362 :                         case lexer::token::e_string  : return false;
    4058        2323 :                         case lexer::token::e_add     : return false;
    4059       88699 :                         case lexer::token::e_sub     : return false;
    4060       10199 :                         case lexer::token::e_colon   : return false;
    4061          19 :                         case lexer::token::e_ternary : return false;
    4062         183 :                         default                      : return true ;
    4063             :                      }
    4064             :                   }
    4065             :                }
    4066     8828973 :                else if (details::is_right_bracket(static_cast<details::char_t>(t)))
    4067             :                {
    4068     1586989 :                   switch (base)
    4069             :                   {
    4070      811878 :                      case lexer::token::e_number  : return false;
    4071      747157 :                      case lexer::token::e_symbol  : return false;
    4072        9372 :                      case lexer::token::e_string  : return false;
    4073        6731 :                      case lexer::token::e_eof     : return false;
    4074       11445 :                      case lexer::token::e_colon   : return false;
    4075          30 :                      case lexer::token::e_ternary : return false;
    4076         376 :                      default                      : return true ;
    4077             :                   }
    4078             :                }
    4079     7241984 :                else if (details::is_left_bracket(static_cast<details::char_t>(t)))
    4080             :                {
    4081     1475880 :                   switch (base)
    4082             :                   {
    4083           0 :                      case lexer::token::e_rbracket    : return true;
    4084           0 :                      case lexer::token::e_rsqrbracket : return true;
    4085           0 :                      case lexer::token::e_rcrlbracket : return true;
    4086     1475880 :                      default                          : return false;
    4087             :                   }
    4088             :                }
    4089             : 
    4090     5766104 :                return false;
    4091             :             }
    4092             : 
    4093             :             set_t invalid_comb_;
    4094             :             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
    4095             :          };
    4096             : 
    4097             :          class sequence_validator_3tokens exprtk_final : public lexer::token_scanner
    4098             :          {
    4099             :          private:
    4100             : 
    4101             :             typedef lexer::token::token_type token_t;
    4102             :             typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
    4103             :             typedef std::set<token_triplet_t> set_t;
    4104             : 
    4105             :          public:
    4106             : 
    4107             :             using lexer::token_scanner::operator();
    4108             : 
    4109      108660 :             sequence_validator_3tokens()
    4110      108660 :             : lexer::token_scanner(3)
    4111             :             {
    4112      108660 :                add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number);
    4113      108660 :                add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string);
    4114      108660 :                add_invalid(lexer::token::e_comma  , lexer::token::e_comma  , lexer::token::e_comma );
    4115             : 
    4116      108660 :                add_invalid(lexer::token::e_add    , lexer::token::e_add    , lexer::token::e_add   );
    4117      108660 :                add_invalid(lexer::token::e_sub    , lexer::token::e_sub    , lexer::token::e_sub   );
    4118      108660 :                add_invalid(lexer::token::e_div    , lexer::token::e_div    , lexer::token::e_div   );
    4119      108660 :                add_invalid(lexer::token::e_mul    , lexer::token::e_mul    , lexer::token::e_mul   );
    4120      108660 :                add_invalid(lexer::token::e_mod    , lexer::token::e_mod    , lexer::token::e_mod   );
    4121      108660 :                add_invalid(lexer::token::e_pow    , lexer::token::e_pow    , lexer::token::e_pow   );
    4122             : 
    4123      108660 :                add_invalid(lexer::token::e_add    , lexer::token::e_sub    , lexer::token::e_add   );
    4124      108660 :                add_invalid(lexer::token::e_sub    , lexer::token::e_add    , lexer::token::e_sub   );
    4125      108660 :                add_invalid(lexer::token::e_div    , lexer::token::e_mul    , lexer::token::e_div   );
    4126      108660 :                add_invalid(lexer::token::e_mul    , lexer::token::e_div    , lexer::token::e_mul   );
    4127      108660 :                add_invalid(lexer::token::e_mod    , lexer::token::e_pow    , lexer::token::e_mod   );
    4128      108660 :                add_invalid(lexer::token::e_pow    , lexer::token::e_mod    , lexer::token::e_pow   );
    4129      108660 :             }
    4130             : 
    4131      370160 :             bool result() exprtk_override
    4132             :             {
    4133      370160 :                return error_list_.empty();
    4134             :             }
    4135             : 
    4136    13457170 :             bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override
    4137             :             {
    4138    13457170 :                const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
    4139             : 
    4140    13457170 :                if (invalid_comb_.find(p) != invalid_comb_.end())
    4141             :                {
    4142           4 :                   error_list_.push_back(std::make_pair(t0,t1));
    4143             :                }
    4144             : 
    4145    13457170 :                return true;
    4146             :             }
    4147             : 
    4148           8 :             std::size_t error_count() const
    4149             :             {
    4150           8 :                return error_list_.size();
    4151             :             }
    4152             : 
    4153           4 :             std::pair<lexer::token,lexer::token> error(const std::size_t index)
    4154             :             {
    4155           4 :                if (index < error_list_.size())
    4156             :                {
    4157           4 :                   return error_list_[index];
    4158             :                }
    4159             :                else
    4160             :                {
    4161           0 :                   static const lexer::token error_token;
    4162           0 :                   return std::make_pair(error_token,error_token);
    4163             :                }
    4164             :             }
    4165             : 
    4166           2 :             void clear_errors()
    4167             :             {
    4168           2 :                error_list_.clear();
    4169           2 :             }
    4170             : 
    4171             :          private:
    4172             : 
    4173     1629900 :             void add_invalid(const token_t t0, const token_t t1, const token_t t2)
    4174             :             {
    4175     1629900 :                invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
    4176     1629900 :             }
    4177             : 
    4178             :             set_t invalid_comb_;
    4179             :             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
    4180             :          };
    4181             : 
    4182             :          struct helper_assembly
    4183             :          {
    4184      434640 :             inline bool register_scanner(lexer::token_scanner* scanner)
    4185             :             {
    4186      434640 :                if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
    4187             :                                                          token_scanner_list.end  (),
    4188             :                                                          scanner))
    4189             :                {
    4190           0 :                   return false;
    4191             :                }
    4192             : 
    4193      434640 :                token_scanner_list.push_back(scanner);
    4194             : 
    4195      434640 :                return true;
    4196             :             }
    4197             : 
    4198      108660 :             inline bool register_modifier(lexer::token_modifier* modifier)
    4199             :             {
    4200      108660 :                if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
    4201             :                                                           token_modifier_list.end  (),
    4202             :                                                           modifier))
    4203             :                {
    4204           0 :                   return false;
    4205             :                }
    4206             : 
    4207      108660 :                token_modifier_list.push_back(modifier);
    4208             : 
    4209      108660 :                return true;
    4210             :             }
    4211             : 
    4212      217320 :             inline bool register_joiner(lexer::token_joiner* joiner)
    4213             :             {
    4214      217320 :                if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
    4215             :                                                         token_joiner_list.end  (),
    4216             :                                                         joiner))
    4217             :                {
    4218           0 :                   return false;
    4219             :                }
    4220             : 
    4221      217320 :                token_joiner_list.push_back(joiner);
    4222             : 
    4223      217320 :                return true;
    4224             :             }
    4225             : 
    4226      108659 :             inline bool register_inserter(lexer::token_inserter* inserter)
    4227             :             {
    4228      108659 :                if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
    4229             :                                                           token_inserter_list.end  (),
    4230             :                                                           inserter))
    4231             :                {
    4232           0 :                   return false;
    4233             :                }
    4234             : 
    4235      108659 :                token_inserter_list.push_back(inserter);
    4236             : 
    4237      108659 :                return true;
    4238             :             }
    4239             : 
    4240      379897 :             inline bool run_modifiers(lexer::generator& g)
    4241             :             {
    4242      379897 :                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
    4243             : 
    4244      759794 :                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
    4245             :                {
    4246      379897 :                   lexer::token_modifier& modifier = (*token_modifier_list[i]);
    4247             : 
    4248      379897 :                   modifier.reset();
    4249      379897 :                   modifier.process(g);
    4250             : 
    4251      379897 :                   if (!modifier.result())
    4252             :                   {
    4253           0 :                      error_token_modifier = token_modifier_list[i];
    4254             : 
    4255           0 :                      return false;
    4256             :                   }
    4257             :                }
    4258             : 
    4259      379897 :                return true;
    4260             :             }
    4261             : 
    4262      379897 :             inline bool run_joiners(lexer::generator& g)
    4263             :             {
    4264      379897 :                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
    4265             : 
    4266     1139691 :                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
    4267             :                {
    4268      759794 :                   lexer::token_joiner& joiner = (*token_joiner_list[i]);
    4269             : 
    4270      759794 :                   joiner.reset();
    4271      759794 :                   joiner.process(g);
    4272             : 
    4273      759794 :                   if (!joiner.result())
    4274             :                   {
    4275           0 :                      error_token_joiner = token_joiner_list[i];
    4276             : 
    4277           0 :                      return false;
    4278             :                   }
    4279             :                }
    4280             : 
    4281      379897 :                return true;
    4282             :             }
    4283             : 
    4284      379887 :             inline bool run_inserters(lexer::generator& g)
    4285             :             {
    4286      379887 :                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
    4287             : 
    4288      759774 :                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
    4289             :                {
    4290      379887 :                   lexer::token_inserter& inserter = (*token_inserter_list[i]);
    4291             : 
    4292      379887 :                   inserter.reset();
    4293      379887 :                   inserter.process(g);
    4294             : 
    4295      379887 :                   if (!inserter.result())
    4296             :                   {
    4297           0 :                      error_token_inserter = token_inserter_list[i];
    4298             : 
    4299           0 :                      return false;
    4300             :                   }
    4301             :                }
    4302             : 
    4303      379887 :                return true;
    4304             :             }
    4305             : 
    4306      379897 :             inline bool run_scanners(lexer::generator& g)
    4307             :             {
    4308      379897 :                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
    4309             : 
    4310     1871087 :                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
    4311             :                {
    4312     1500929 :                   lexer::token_scanner& scanner = (*token_scanner_list[i]);
    4313             : 
    4314     1500929 :                   scanner.reset();
    4315     1500929 :                   scanner.process(g);
    4316             : 
    4317     1500929 :                   if (!scanner.result())
    4318             :                   {
    4319        9739 :                      error_token_scanner = token_scanner_list[i];
    4320             : 
    4321        9739 :                      return false;
    4322             :                   }
    4323             :                }
    4324             : 
    4325      370158 :                return true;
    4326             :             }
    4327             : 
    4328             :             std::vector<lexer::token_scanner*>  token_scanner_list;
    4329             :             std::vector<lexer::token_modifier*> token_modifier_list;
    4330             :             std::vector<lexer::token_joiner*>   token_joiner_list;
    4331             :             std::vector<lexer::token_inserter*> token_inserter_list;
    4332             : 
    4333             :             lexer::token_scanner*  error_token_scanner;
    4334             :             lexer::token_modifier* error_token_modifier;
    4335             :             lexer::token_joiner*   error_token_joiner;
    4336             :             lexer::token_inserter* error_token_inserter;
    4337             :          };
    4338             :       }
    4339             : 
    4340             :       class parser_helper
    4341             :       {
    4342             :       public:
    4343             : 
    4344             :          typedef token     token_t;
    4345             :          typedef generator generator_t;
    4346             : 
    4347      380686 :          inline bool init(const std::string& str)
    4348             :          {
    4349      380686 :             if (!lexer_.process(str))
    4350             :             {
    4351         788 :                return false;
    4352             :             }
    4353             : 
    4354      379898 :             lexer_.begin();
    4355             : 
    4356      379898 :             next_token();
    4357             : 
    4358      379898 :             return true;
    4359             :          }
    4360             : 
    4361     3288819 :          inline generator_t& lexer()
    4362             :          {
    4363     3288819 :             return lexer_;
    4364             :          }
    4365             : 
    4366             :          inline const generator_t& lexer() const
    4367             :          {
    4368             :             return lexer_;
    4369             :          }
    4370             : 
    4371             :          inline void store_token()
    4372             :          {
    4373             :             lexer_.store();
    4374             :             store_current_token_ = current_token_;
    4375             :          }
    4376             : 
    4377             :          inline void restore_token()
    4378             :          {
    4379             :             lexer_.restore();
    4380             :             current_token_ = store_current_token_;
    4381             :          }
    4382             : 
    4383    13552170 :          inline void next_token()
    4384             :          {
    4385    13552170 :             current_token_ = lexer_.next_token();
    4386    13552170 :          }
    4387             : 
    4388    63521882 :          inline const token_t& current_token() const
    4389             :          {
    4390    63521882 :             return current_token_;
    4391             :          }
    4392             : 
    4393             :          inline const token_t& peek_next_token()
    4394             :          {
    4395             :             return lexer_.peek_next_token();
    4396             :          }
    4397             : 
    4398             :          enum token_advance_mode
    4399             :          {
    4400             :             e_hold    = 0,
    4401             :             e_advance = 1
    4402             :          };
    4403             : 
    4404     4117643 :          inline void advance_token(const token_advance_mode mode)
    4405             :          {
    4406     4117643 :             if (e_advance == mode)
    4407             :             {
    4408     3589974 :                next_token();
    4409             :             }
    4410     4117643 :          }
    4411             : 
    4412    18664985 :          inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
    4413             :          {
    4414    18664985 :             if (current_token().type != ttype)
    4415             :             {
    4416    14552715 :                return false;
    4417             :             }
    4418             : 
    4419     4112270 :             advance_token(mode);
    4420             : 
    4421     4112270 :             return true;
    4422             :          }
    4423             : 
    4424          80 :          inline bool token_is(const token_t::token_type& ttype,
    4425             :                               const std::string& value,
    4426             :                               const token_advance_mode mode = e_advance)
    4427             :          {
    4428          80 :             if (
    4429         160 :                  (current_token().type != ttype) ||
    4430          80 :                  !exprtk::details::imatch(value,current_token().value)
    4431             :                )
    4432             :             {
    4433           0 :                return false;
    4434             :             }
    4435             : 
    4436          80 :             advance_token(mode);
    4437             : 
    4438          80 :             return true;
    4439             :          }
    4440             : 
    4441        5333 :          inline bool token_is(const std::string& value,
    4442             :                               const token_advance_mode mode = e_advance)
    4443             :          {
    4444        5333 :             if (!exprtk::details::imatch(value,current_token().value))
    4445             :             {
    4446          40 :                return false;
    4447             :             }
    4448             : 
    4449        5293 :             advance_token(mode);
    4450             : 
    4451        5293 :             return true;
    4452             :          }
    4453             : 
    4454          10 :          inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance)
    4455             :          {
    4456          10 :             switch (current_token().type)
    4457             :             {
    4458           0 :                case token_t::e_add :
    4459             :                case token_t::e_sub :
    4460             :                case token_t::e_div :
    4461             :                case token_t::e_mul :
    4462             :                case token_t::e_mod :
    4463           0 :                case token_t::e_pow : break;
    4464          10 :                default             : return false;
    4465             :             }
    4466             : 
    4467           0 :             advance_token(mode);
    4468             : 
    4469           0 :             return true;
    4470             :          }
    4471             : 
    4472          10 :          inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance)
    4473             :          {
    4474          10 :             switch (current_token().type)
    4475             :             {
    4476           0 :                case token_t::e_eq  :
    4477             :                case token_t::e_lte :
    4478             :                case token_t::e_ne  :
    4479             :                case token_t::e_gte :
    4480             :                case token_t::e_lt  :
    4481           0 :                case token_t::e_gt  : break;
    4482          10 :                default             : return false;
    4483             :             }
    4484             : 
    4485           0 :             advance_token(mode);
    4486             : 
    4487           0 :             return true;
    4488             :          }
    4489             : 
    4490             :          inline bool token_is_left_bracket(const token_advance_mode mode = e_advance)
    4491             :          {
    4492             :             switch (current_token().type)
    4493             :             {
    4494             :                case token_t::e_lbracket    :
    4495             :                case token_t::e_lcrlbracket :
    4496             :                case token_t::e_lsqrbracket : break;
    4497             :                default                     : return false;
    4498             :             }
    4499             : 
    4500             :             advance_token(mode);
    4501             : 
    4502             :             return true;
    4503             :          }
    4504             : 
    4505          10 :          inline bool token_is_right_bracket(const token_advance_mode mode = e_advance)
    4506             :          {
    4507          10 :             switch (current_token().type)
    4508             :             {
    4509           0 :                case token_t::e_rbracket    :
    4510             :                case token_t::e_rcrlbracket :
    4511           0 :                case token_t::e_rsqrbracket : break;
    4512          10 :                default                     : return false;
    4513             :             }
    4514             : 
    4515           0 :             advance_token(mode);
    4516             : 
    4517           0 :             return true;
    4518             :          }
    4519             : 
    4520          10 :          inline bool token_is_loop(const token_advance_mode mode = e_advance)
    4521             :          {
    4522          30 :             return token_is("for"   , mode) ||
    4523          60 :                    token_is("while" , mode) ||
    4524          40 :                    token_is("repeat", mode) ;
    4525             :          }
    4526             : 
    4527     5806024 :          inline bool peek_token_is(const token_t::token_type& ttype)
    4528             :          {
    4529     5806024 :             return (lexer_.peek_next_token().type == ttype);
    4530             :          }
    4531             : 
    4532          55 :          inline bool peek_token_is(const std::string& s)
    4533             :          {
    4534          55 :             return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
    4535             :          }
    4536             : 
    4537             :       private:
    4538             : 
    4539             :          generator_t lexer_;
    4540             :          token_t     current_token_;
    4541             :          token_t     store_current_token_;
    4542             :       };
    4543             :    }
    4544             : 
    4545             :    template <typename T>
    4546             :    class vector_view
    4547             :    {
    4548             :    public:
    4549             : 
    4550             :       typedef T* data_ptr_t;
    4551             : 
    4552        4195 :       vector_view(data_ptr_t data, const std::size_t& size)
    4553        4195 :       : base_size_(size)
    4554        4195 :       , size_(size)
    4555        4195 :       , data_(data)
    4556        8390 :       , data_ref_(0)
    4557             :       {
    4558        4195 :          assert(size_ > 0);
    4559        4195 :       }
    4560             : 
    4561             :       vector_view(const vector_view<T>& vv)
    4562             :       : base_size_(vv.base_size_)
    4563             :       , size_(vv.size_)
    4564             :       , data_(vv.data_)
    4565             :       , data_ref_(0)
    4566             :       {
    4567             :          assert(size_ > 0);
    4568             :       }
    4569             : 
    4570        6800 :       inline void rebase(data_ptr_t data)
    4571             :       {
    4572        6800 :          data_ = data;
    4573             : 
    4574        6800 :          if (!data_ref_.empty())
    4575             :          {
    4576       11027 :             for (std::size_t i = 0; i < data_ref_.size(); ++i)
    4577             :             {
    4578        8547 :                (*data_ref_[i]) = data;
    4579             :             }
    4580             :          }
    4581        6800 :       }
    4582             : 
    4583           6 :       inline data_ptr_t data() const
    4584             :       {
    4585           6 :          return data_;
    4586             :       }
    4587             : 
    4588        4172 :       inline std::size_t base_size() const
    4589             :       {
    4590        4172 :          return base_size_;
    4591             :       }
    4592             : 
    4593       32851 :       inline std::size_t size() const
    4594             :       {
    4595       32851 :          return size_;
    4596             :       }
    4597             : 
    4598             :       inline const T& operator[](const std::size_t index) const
    4599             :       {
    4600             :          assert(index < size_);
    4601             :          return data_[index];
    4602             :       }
    4603             : 
    4604        7555 :       inline T& operator[](const std::size_t index)
    4605             :       {
    4606        7555 :          assert(index < size_);
    4607        7555 :          return data_[index];
    4608             :       }
    4609             : 
    4610        3670 :       void set_ref(data_ptr_t* data_ref)
    4611             :       {
    4612        3670 :          data_ref_.push_back(data_ref);
    4613             :          exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n",
    4614             :                        reinterpret_cast<void*>(data_ref),
    4615             :                        static_cast<int>(data_ref_.size())));
    4616        3670 :       }
    4617             : 
    4618        3670 :       void remove_ref(data_ptr_t* data_ref)
    4619             :       {
    4620        7340 :          data_ref_.erase(
    4621        3670 :             std::remove(data_ref_.begin(), data_ref_.end(), data_ref),
    4622        3670 :             data_ref_.end());
    4623             :          exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n",
    4624             :                        reinterpret_cast<void*>(data_ref),
    4625             :                        static_cast<int>(data_ref_.size())));
    4626        3670 :       }
    4627             : 
    4628         240 :       bool set_size(const std::size_t new_size)
    4629             :       {
    4630         240 :          if ((new_size > 0) && (new_size <= base_size_))
    4631             :          {
    4632         240 :             size_ = new_size;
    4633             :             exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n",
    4634             :                           reinterpret_cast<void*>(data_),
    4635             :                           size_));
    4636         240 :             return true;
    4637             :          }
    4638             : 
    4639             :          exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu  base_size: %lu\n",
    4640             :                        new_size,
    4641             :                        base_size_));
    4642           0 :          return false;
    4643             :       }
    4644             : 
    4645             :    private:
    4646             : 
    4647             :       const std::size_t base_size_;
    4648             :       std::size_t size_;
    4649             :       data_ptr_t  data_;
    4650             :       std::vector<data_ptr_t*> data_ref_;
    4651             :    };
    4652             : 
    4653             :    template <typename T>
    4654        4137 :    inline vector_view<T> make_vector_view(T* data,
    4655             :                                           const std::size_t size, const std::size_t offset = 0)
    4656             :    {
    4657        4137 :       return vector_view<T>(data + offset, size);
    4658             :    }
    4659             : 
    4660             :    template <typename T>
    4661          58 :    inline vector_view<T> make_vector_view(std::vector<T>& v,
    4662             :                                           const std::size_t size, const std::size_t offset = 0)
    4663             :    {
    4664          58 :       return vector_view<T>(v.data() + offset, size);
    4665             :    }
    4666             : 
    4667             :    template <typename T> class results_context;
    4668             : 
    4669             :    template <typename T>
    4670             :    struct type_store
    4671             :    {
    4672             :       enum store_type
    4673             :       {
    4674             :          e_unknown,
    4675             :          e_scalar ,
    4676             :          e_vector ,
    4677             :          e_string
    4678             :       };
    4679             : 
    4680        3724 :       type_store()
    4681        3724 :       : data(0)
    4682        3724 :       , size(0)
    4683        3724 :       , type(e_unknown)
    4684        3724 :       {}
    4685             : 
    4686             :       union
    4687             :       {
    4688             :          void* data;
    4689             :          T*    vec_data;
    4690             :       };
    4691             : 
    4692             :       std::size_t size;
    4693             :       store_type  type;
    4694             : 
    4695             :       class parameter_list
    4696             :       {
    4697             :       public:
    4698             : 
    4699        5088 :          explicit parameter_list(std::vector<type_store>& pl)
    4700        5088 :          : parameter_list_(pl)
    4701        5088 :          {}
    4702             : 
    4703             :          inline bool empty() const
    4704             :          {
    4705             :             return parameter_list_.empty();
    4706             :          }
    4707             : 
    4708        2042 :          inline std::size_t size() const
    4709             :          {
    4710        2042 :             return parameter_list_.size();
    4711             :          }
    4712             : 
    4713       11043 :          inline type_store& operator[](const std::size_t& index)
    4714             :          {
    4715       11043 :             return parameter_list_[index];
    4716             :          }
    4717             : 
    4718             :          inline const type_store& operator[](const std::size_t& index) const
    4719             :          {
    4720             :             return parameter_list_[index];
    4721             :          }
    4722             : 
    4723             :          inline type_store& front()
    4724             :          {
    4725             :             return parameter_list_[0];
    4726             :          }
    4727             : 
    4728             :          inline const type_store& front() const
    4729             :          {
    4730             :             return parameter_list_[0];
    4731             :          }
    4732             : 
    4733         536 :          inline type_store& back()
    4734             :          {
    4735         536 :             return parameter_list_.back();
    4736             :          }
    4737             : 
    4738             :          inline const type_store& back() const
    4739             :          {
    4740             :             return parameter_list_.back();
    4741             :          }
    4742             : 
    4743             :       private:
    4744             : 
    4745             :          std::vector<type_store>& parameter_list_;
    4746             : 
    4747             :          friend class results_context<T>;
    4748             :       };
    4749             : 
    4750             :       template <typename ViewType>
    4751             :       struct type_view
    4752             :       {
    4753             :          typedef type_store<T> type_store_t;
    4754             :          typedef ViewType      value_t;
    4755             : 
    4756        7947 :          explicit type_view(type_store_t& ts)
    4757        7947 :          : ts_(ts)
    4758        7947 :          , data_(reinterpret_cast<value_t*>(ts_.data))
    4759        7947 :          {}
    4760             : 
    4761           2 :          explicit type_view(const type_store_t& ts)
    4762           2 :          : ts_(const_cast<type_store_t&>(ts))
    4763           2 :          , data_(reinterpret_cast<value_t*>(ts_.data))
    4764           2 :          {}
    4765             : 
    4766       13454 :          inline std::size_t size() const
    4767             :          {
    4768       13454 :             return ts_.size;
    4769             :          }
    4770             : 
    4771        5325 :          inline value_t& operator[](const std::size_t& i)
    4772             :          {
    4773        5325 :             return data_[i];
    4774             :          }
    4775             : 
    4776       31371 :          inline const value_t& operator[](const std::size_t& i) const
    4777             :          {
    4778       31371 :             return data_[i];
    4779             :          }
    4780             : 
    4781          57 :          inline const value_t* begin() const { return data_; }
    4782         300 :          inline       value_t* begin()       { return data_; }
    4783             : 
    4784             :          inline const value_t* end() const
    4785             :          {
    4786             :             return static_cast<value_t*>(data_ + ts_.size);
    4787             :          }
    4788             : 
    4789           2 :          inline value_t* end()
    4790             :          {
    4791           2 :             return static_cast<value_t*>(data_ + ts_.size);
    4792             :          }
    4793             : 
    4794             :          type_store_t& ts_;
    4795             :          value_t* data_;
    4796             :       };
    4797             : 
    4798             :       typedef type_view<T>    vector_view;
    4799             :       typedef type_view<char> string_view;
    4800             : 
    4801             :       struct scalar_view
    4802             :       {
    4803             :          typedef type_store<T> type_store_t;
    4804             :          typedef T value_t;
    4805             : 
    4806        3356 :          explicit scalar_view(type_store_t& ts)
    4807        3356 :          : v_(*reinterpret_cast<value_t*>(ts.data))
    4808        3356 :          {}
    4809             : 
    4810          16 :          explicit scalar_view(const type_store_t& ts)
    4811          16 :          : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
    4812          16 :          {}
    4813             : 
    4814        1026 :          inline value_t& operator() ()
    4815             :          {
    4816        1026 :             return v_;
    4817             :          }
    4818             : 
    4819           2 :          inline const value_t& operator() () const
    4820             :          {
    4821           2 :             return v_;
    4822             :          }
    4823             : 
    4824             :          inline operator value_t() const
    4825             :          {
    4826             :             return v_;
    4827             :          }
    4828             : 
    4829         714 :          inline operator value_t()
    4830             :          {
    4831         714 :             return v_;
    4832             :          }
    4833             : 
    4834             :          template <typename IntType>
    4835             :          inline bool to_int(IntType& i) const
    4836             :          {
    4837             :             if (!exprtk::details::numeric::is_integer(v_))
    4838             :                return false;
    4839             : 
    4840             :             i = static_cast<IntType>(v_);
    4841             : 
    4842             :             return true;
    4843             :          }
    4844             : 
    4845             :          template <typename UIntType>
    4846        1630 :          inline bool to_uint(UIntType& u) const
    4847             :          {
    4848        1630 :             if (v_ < T(0))
    4849           0 :                return false;
    4850        1630 :             else if (!exprtk::details::numeric::is_integer(v_))
    4851           0 :                return false;
    4852             : 
    4853        1630 :             u = static_cast<UIntType>(v_);
    4854             : 
    4855        1630 :             return true;
    4856             :          }
    4857             : 
    4858             :          T& v_;
    4859             :       };
    4860             :    };
    4861             : 
    4862             :    template <typename StringView>
    4863          48 :    inline std::string to_str(const StringView& view)
    4864             :    {
    4865          96 :       return std::string(view.begin(),view.size());
    4866             :    }
    4867             : 
    4868             :    #ifndef exprtk_disable_return_statement
    4869             :    namespace details
    4870             :    {
    4871             :       template <typename T> class return_node;
    4872             :       template <typename T> class return_envelope_node;
    4873             :    }
    4874             :    #endif
    4875             : 
    4876             :    template <typename T>
    4877             :    class results_context
    4878             :    {
    4879             :    public:
    4880             : 
    4881             :       typedef type_store<T> type_store_t;
    4882             :       typedef typename type_store_t::scalar_view scalar_t;
    4883             :       typedef typename type_store_t::vector_view vector_t;
    4884             :       typedef typename type_store_t::string_view string_t;
    4885             : 
    4886         111 :       results_context()
    4887         111 :       : results_available_(false)
    4888         111 :       {}
    4889             : 
    4890          97 :       inline std::size_t count() const
    4891             :       {
    4892          97 :          if (results_available_)
    4893          97 :             return parameter_list_.size();
    4894             :          else
    4895           0 :             return 0;
    4896             :       }
    4897             : 
    4898             :       inline type_store_t& operator[](const std::size_t& index)
    4899             :       {
    4900             :          return parameter_list_[index];
    4901             :       }
    4902             : 
    4903          80 :       inline const type_store_t& operator[](const std::size_t& index) const
    4904             :       {
    4905          80 :          return parameter_list_[index];
    4906             :       }
    4907             : 
    4908           2 :       inline bool get_scalar(const std::size_t& index, T& out) const
    4909             :       {
    4910           2 :          if (
    4911           4 :               (index < parameter_list_.size()) &&
    4912           2 :               (parameter_list_[index].type == type_store_t::e_scalar)
    4913             :             )
    4914             :          {
    4915           2 :             const scalar_t scalar(parameter_list_[index]);
    4916           2 :             out = scalar();
    4917           2 :             return true;
    4918             :          }
    4919             : 
    4920           0 :          return false;
    4921             :       }
    4922             : 
    4923             :       template <typename OutputIterator>
    4924           1 :       inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const
    4925             :       {
    4926           1 :          if (
    4927           2 :               (index < parameter_list_.size()) &&
    4928           1 :               (parameter_list_[index].type == type_store_t::e_vector)
    4929             :             )
    4930             :          {
    4931           1 :             const vector_t vector(parameter_list_[index]);
    4932           5 :             for (std::size_t i = 0; i < vector.size(); ++i)
    4933             :             {
    4934           4 :                *(out_itr++) = vector[i];
    4935             :             }
    4936             : 
    4937           1 :             return true;
    4938             :          }
    4939             : 
    4940           0 :          return false;
    4941             :       }
    4942             : 
    4943           1 :       inline bool get_vector(const std::size_t& index, std::vector<T>& out) const
    4944             :       {
    4945           1 :          return get_vector(index,std::back_inserter(out));
    4946             :       }
    4947             : 
    4948           1 :       inline bool get_string(const std::size_t& index, std::string& out) const
    4949             :       {
    4950           1 :          if (
    4951           2 :               (index < parameter_list_.size()) &&
    4952           1 :               (parameter_list_[index].type == type_store_t::e_string)
    4953             :             )
    4954             :          {
    4955           1 :             const string_t str(parameter_list_[index]);
    4956           1 :             out.assign(str.begin(),str.size());
    4957           1 :             return true;
    4958             :          }
    4959             : 
    4960           0 :          return false;
    4961             :       }
    4962             : 
    4963             :    private:
    4964             : 
    4965         111 :       inline void clear()
    4966             :       {
    4967         111 :          results_available_ = false;
    4968         111 :       }
    4969             : 
    4970             :       typedef std::vector<type_store_t> ts_list_t;
    4971             :       typedef typename type_store_t::parameter_list parameter_list_t;
    4972             : 
    4973          31 :       inline void assign(const parameter_list_t& pl)
    4974             :       {
    4975          31 :          parameter_list_    = pl.parameter_list_;
    4976          31 :          results_available_ = true;
    4977          31 :       }
    4978             : 
    4979             :       bool results_available_;
    4980             :       ts_list_t parameter_list_;
    4981             : 
    4982             :       #ifndef exprtk_disable_return_statement
    4983             :       friend class details::return_node<T>;
    4984             :       friend class details::return_envelope_node<T>;
    4985             :       #endif
    4986             :    };
    4987             : 
    4988             :    namespace details
    4989             :    {
    4990             :       enum operator_type
    4991             :       {
    4992             :          e_default , e_null    , e_add     , e_sub     ,
    4993             :          e_mul     , e_div     , e_mod     , e_pow     ,
    4994             :          e_atan2   , e_min     , e_max     , e_avg     ,
    4995             :          e_sum     , e_prod    , e_lt      , e_lte     ,
    4996             :          e_eq      , e_equal   , e_ne      , e_nequal  ,
    4997             :          e_gte     , e_gt      , e_and     , e_nand    ,
    4998             :          e_or      , e_nor     , e_xor     , e_xnor    ,
    4999             :          e_mand    , e_mor     , e_scand   , e_scor    ,
    5000             :          e_shr     , e_shl     , e_abs     , e_acos    ,
    5001             :          e_acosh   , e_asin    , e_asinh   , e_atan    ,
    5002             :          e_atanh   , e_ceil    , e_cos     , e_cosh    ,
    5003             :          e_exp     , e_expm1   , e_floor   , e_log     ,
    5004             :          e_log10   , e_log2    , e_log1p   , e_logn    ,
    5005             :          e_neg     , e_pos     , e_round   , e_roundn  ,
    5006             :          e_root    , e_sqrt    , e_sin     , e_sinc    ,
    5007             :          e_sinh    , e_sec     , e_csc     , e_tan     ,
    5008             :          e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
    5009             :          e_inrange , e_sgn     , e_r2d     , e_d2r     ,
    5010             :          e_d2g     , e_g2d     , e_hypot   , e_notl    ,
    5011             :          e_erf     , e_erfc    , e_ncdf    , e_frac    ,
    5012             :          e_trunc   , e_assign  , e_addass  , e_subass  ,
    5013             :          e_mulass  , e_divass  , e_modass  , e_in      ,
    5014             :          e_like    , e_ilike   , e_multi   , e_smulti  ,
    5015             :          e_swap    ,
    5016             : 
    5017             :          // Do not add new functions/operators after this point.
    5018             :          e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
    5019             :          e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
    5020             :          e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
    5021             :          e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
    5022             :          e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
    5023             :          e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
    5024             :          e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
    5025             :          e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
    5026             :          e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
    5027             :          e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
    5028             :          e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
    5029             :          e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
    5030             :          e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
    5031             :          e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
    5032             :          e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
    5033             :          e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
    5034             :          e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
    5035             :          e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
    5036             :          e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
    5037             :          e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
    5038             :          e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
    5039             :          e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
    5040             :          e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
    5041             :          e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
    5042             :          e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
    5043             :          e_sffinal  = 1100,
    5044             :          e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
    5045             :          e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
    5046             :          e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
    5047             :          e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
    5048             :          e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
    5049             :          e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
    5050             :          e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
    5051             :          e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
    5052             :          e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
    5053             :          e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
    5054             :          e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
    5055             :          e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
    5056             :          e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
    5057             :          e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
    5058             :          e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
    5059             :          e_sf4ext60 = 2060, e_sf4ext61 = 2061
    5060             :       };
    5061             : 
    5062           3 :       inline std::string to_str(const operator_type opr)
    5063             :       {
    5064           3 :          switch (opr)
    5065             :          {
    5066           0 :             case e_add    : return  "+"  ;
    5067           0 :             case e_sub    : return  "-"  ;
    5068           0 :             case e_mul    : return  "*"  ;
    5069           0 :             case e_div    : return  "/"  ;
    5070           0 :             case e_mod    : return  "%"  ;
    5071           0 :             case e_pow    : return  "^"  ;
    5072           0 :             case e_assign : return ":="  ;
    5073           0 :             case e_addass : return "+="  ;
    5074           9 :             case e_subass : return "-="  ;
    5075           0 :             case e_mulass : return "*="  ;
    5076           0 :             case e_divass : return "/="  ;
    5077           0 :             case e_modass : return "%="  ;
    5078           0 :             case e_lt     : return  "<"  ;
    5079           0 :             case e_lte    : return "<="  ;
    5080           0 :             case e_eq     : return "=="  ;
    5081           0 :             case e_equal  : return  "="  ;
    5082           0 :             case e_ne     : return "!="  ;
    5083           0 :             case e_nequal : return "<>"  ;
    5084           0 :             case e_gte    : return ">="  ;
    5085           0 :             case e_gt     : return  ">"  ;
    5086           0 :             case e_and    : return "and" ;
    5087           0 :             case e_or     : return "or"  ;
    5088           0 :             case e_xor    : return "xor" ;
    5089           0 :             case e_nand   : return "nand";
    5090           0 :             case e_nor    : return "nor" ;
    5091           0 :             case e_xnor   : return "xnor";
    5092           0 :             default       : return "N/A" ;
    5093             :          }
    5094             :       }
    5095             : 
    5096             :       struct base_operation_t
    5097             :       {
    5098     5650320 :          base_operation_t(const operator_type t, const unsigned int& np)
    5099     5650320 :          : type(t)
    5100     5650320 :          , num_params(np)
    5101     5650320 :          {}
    5102             : 
    5103             :          operator_type type;
    5104             :          unsigned int num_params;
    5105             :       };
    5106             : 
    5107             :       namespace loop_unroll
    5108             :       {
    5109             :          const unsigned int global_loop_batch_size =
    5110             :          #ifndef exprtk_disable_superscalar_unroll
    5111             :          16;
    5112             :          #else
    5113             :           4;
    5114             :          #endif
    5115             : 
    5116             :          struct details
    5117             :          {
    5118       31598 :             explicit details(const std::size_t& vsize,
    5119             :                              const unsigned int loop_batch_size = global_loop_batch_size)
    5120       31598 :             : batch_size(loop_batch_size   )
    5121       31598 :             , remainder (vsize % batch_size)
    5122       31598 :             , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
    5123       31598 :             {}
    5124             : 
    5125             :             unsigned int batch_size;
    5126             :             int remainder;
    5127             :             int upper_bound;
    5128             :          };
    5129             :       }
    5130             : 
    5131             :       #ifdef exprtk_enable_debugging
    5132             :       inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
    5133             :       {
    5134             :          if (size)
    5135             :             exprtk_debug(("%s - addr: %p size: %d\n",
    5136             :                           s.c_str(),
    5137             :                           ptr,
    5138             :                           static_cast<unsigned int>(size)));
    5139             :          else
    5140             :             exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr));
    5141             :       }
    5142             : 
    5143             :       template <typename T>
    5144             :       inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size)
    5145             :       {
    5146             :          printf("----- %s (%p) -----\n",
    5147             :                 vec_name.c_str(),
    5148             :                 static_cast<const void*>(data));
    5149             :          printf("[ ");
    5150             :          for (std::size_t i = 0; i <  size; ++i)
    5151             :          {
    5152             :             printf("%8.3f\t", data[i]);
    5153             :          }
    5154             :          printf(" ]\n");
    5155             :          printf("---------------------\n");
    5156             :       }
    5157             :       #else
    5158     1065860 :       inline void dump_ptr(const std::string&, const void*) {}
    5159       12247 :       inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
    5160             :       template <typename T>
    5161             :       inline void dump_vector(const std::string&, const T*, const std::size_t) {}
    5162             :       #endif
    5163             : 
    5164             :       template <typename T>
    5165             :       class vec_data_store
    5166             :       {
    5167             :       public:
    5168             : 
    5169             :          typedef vec_data_store<T> type;
    5170             :          typedef T* data_t;
    5171             : 
    5172             :       private:
    5173             : 
    5174             :          struct control_block
    5175             :          {
    5176       27934 :             control_block()
    5177       27934 :             : ref_count(1)
    5178       27934 :             , size     (0)
    5179       27934 :             , data     (0)
    5180       27934 :             , destruct (true)
    5181       27934 :             {}
    5182             : 
    5183       12247 :             explicit control_block(const std::size_t& dsize)
    5184       12247 :             : ref_count(1    )
    5185       12247 :             , size     (dsize)
    5186       12247 :             , data     (0    )
    5187       12247 :             , destruct (true )
    5188       12247 :             { create_data(); }
    5189             : 
    5190       49912 :             control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
    5191       49912 :             : ref_count(1     )
    5192       49912 :             , size     (dsize )
    5193       49912 :             , data     (dptr  )
    5194       49912 :             , destruct (dstrct)
    5195       49912 :             {}
    5196             : 
    5197       90093 :            ~control_block()
    5198             :             {
    5199       90093 :                if (data && destruct && (0 == ref_count))
    5200             :                {
    5201       24494 :                   dump_ptr("~vec_data_store::control_block() data",data);
    5202       12247 :                   delete[] data;
    5203       12247 :                   data = reinterpret_cast<data_t>(0);
    5204             :                }
    5205       90093 :             }
    5206             : 
    5207       90093 :             static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
    5208             :             {
    5209       90093 :                if (dsize)
    5210             :                {
    5211       62159 :                   if (0 == data_ptr)
    5212       12247 :                      return (new control_block(dsize));
    5213             :                   else
    5214       49912 :                      return (new control_block(dsize, data_ptr, dstrct));
    5215             :                }
    5216             :                else
    5217       27934 :                   return (new control_block);
    5218             :             }
    5219             : 
    5220      145120 :             static inline void destroy(control_block*& cntrl_blck)
    5221             :             {
    5222      145120 :                if (cntrl_blck)
    5223             :                {
    5224      145120 :                   if (
    5225      290240 :                        (0 !=   cntrl_blck->ref_count) &&
    5226      145120 :                        (0 == --cntrl_blck->ref_count)
    5227             :                      )
    5228             :                   {
    5229       90093 :                      delete cntrl_blck;
    5230             :                   }
    5231             : 
    5232      145120 :                   cntrl_blck = 0;
    5233             :                }
    5234      145120 :             }
    5235             : 
    5236             :             std::size_t ref_count;
    5237             :             std::size_t size;
    5238             :             data_t      data;
    5239             :             bool        destruct;
    5240             : 
    5241             :          private:
    5242             : 
    5243             :             control_block(const control_block&) exprtk_delete;
    5244             :             control_block& operator=(const control_block&) exprtk_delete;
    5245             : 
    5246       12247 :             inline void create_data()
    5247             :             {
    5248       12247 :                destruct = true;
    5249       12247 :                data     = new T[size];
    5250       12247 :                std::fill_n(data, size, T(0));
    5251       24494 :                dump_ptr("control_block::create_data() - data", data, size);
    5252       12247 :             }
    5253             :          };
    5254             : 
    5255             :       public:
    5256             : 
    5257       27934 :          vec_data_store()
    5258       27934 :          : control_block_(control_block::create(0))
    5259       27934 :          {}
    5260             : 
    5261       12247 :          explicit vec_data_store(const std::size_t& size)
    5262       12247 :          : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true))
    5263       12247 :          {}
    5264             : 
    5265       49912 :          vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
    5266       49912 :          : control_block_(control_block::create(size, data, dstrct))
    5267       49912 :          {}
    5268             : 
    5269       26187 :          vec_data_store(const type& vds)
    5270             :          {
    5271       26187 :             control_block_ = vds.control_block_;
    5272       26187 :             control_block_->ref_count++;
    5273       26187 :          }
    5274             : 
    5275      116280 :         ~vec_data_store()
    5276             :          {
    5277      116280 :             control_block::destroy(control_block_);
    5278      116280 :          }
    5279             : 
    5280       29522 :          type& operator=(const type& vds)
    5281             :          {
    5282       29522 :             if (this != &vds)
    5283             :             {
    5284       29522 :                const std::size_t final_size = min_size(control_block_, vds.control_block_);
    5285             : 
    5286       29522 :                vds.control_block_->size = final_size;
    5287       29522 :                    control_block_->size = final_size;
    5288             : 
    5289       29522 :                if (control_block_->destruct || (0 == control_block_->data))
    5290             :                {
    5291       28840 :                   control_block::destroy(control_block_);
    5292             : 
    5293       28840 :                   control_block_ = vds.control_block_;
    5294       28840 :                   control_block_->ref_count++;
    5295             :                }
    5296             :             }
    5297             : 
    5298       29522 :             return (*this);
    5299             :          }
    5300             : 
    5301       46015 :          inline data_t data()
    5302             :          {
    5303       46015 :             return control_block_->data;
    5304             :          }
    5305             : 
    5306    32972108 :          inline data_t data() const
    5307             :          {
    5308    32972108 :             return control_block_->data;
    5309             :          }
    5310             : 
    5311       50017 :          inline std::size_t size() const
    5312             :          {
    5313       50017 :             return control_block_->size;
    5314             :          }
    5315             : 
    5316      122163 :          inline data_t& ref()
    5317             :          {
    5318      122163 :             return control_block_->data;
    5319             :          }
    5320             : 
    5321             :          inline void dump() const
    5322             :          {
    5323             :             #ifdef exprtk_enable_debugging
    5324             :             exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
    5325             :                           size(),
    5326             :                           data(),
    5327             :                           (control_block_->destruct ? 'T' : 'F')));
    5328             : 
    5329             :             for (std::size_t i = 0; i < size(); ++i)
    5330             :             {
    5331             :                if (5 == i)
    5332             :                   exprtk_debug(("\n"));
    5333             : 
    5334             :                exprtk_debug(("%15.10f ", data()[i]));
    5335             :             }
    5336             :             exprtk_debug(("\n"));
    5337             :             #endif
    5338             :          }
    5339             : 
    5340         649 :          static inline void match_sizes(type& vds0, type& vds1)
    5341             :          {
    5342         649 :             const std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
    5343         649 :             vds0.control_block_->size = size;
    5344         649 :             vds1.control_block_->size = size;
    5345         649 :          }
    5346             : 
    5347             :       private:
    5348             : 
    5349       30171 :          static inline std::size_t min_size(const control_block* cb0, const control_block* cb1)
    5350             :          {
    5351       30171 :             const std::size_t size0 = cb0->size;
    5352       30171 :             const std::size_t size1 = cb1->size;
    5353             : 
    5354       30171 :             if (size0 && size1)
    5355        2237 :                return std::min(size0,size1);
    5356             :             else
    5357       27934 :                return (size0) ? size0 : size1;
    5358             :          }
    5359             : 
    5360             :          control_block* control_block_;
    5361             :       };
    5362             : 
    5363             :       namespace numeric
    5364             :       {
    5365             :          namespace details
    5366             :          {
    5367             :             template <typename T>
    5368      100770 :             inline T process_impl(const operator_type operation, const T arg)
    5369             :             {
    5370      100770 :                switch (operation)
    5371             :                {
    5372         160 :                   case e_abs   : return numeric::abs  (arg);
    5373          10 :                   case e_acos  : return numeric::acos (arg);
    5374          80 :                   case e_acosh : return numeric::acosh(arg);
    5375          10 :                   case e_asin  : return numeric::asin (arg);
    5376         210 :                   case e_asinh : return numeric::asinh(arg);
    5377           5 :                   case e_atan  : return numeric::atan (arg);
    5378          80 :                   case e_atanh : return numeric::atanh(arg);
    5379          60 :                   case e_ceil  : return numeric::ceil (arg);
    5380         371 :                   case e_cos   : return numeric::cos  (arg);
    5381          15 :                   case e_cosh  : return numeric::cosh (arg);
    5382          32 :                   case e_exp   : return numeric::exp  (arg);
    5383           0 :                   case e_expm1 : return numeric::expm1(arg);
    5384         110 :                   case e_floor : return numeric::floor(arg);
    5385          45 :                   case e_log   : return numeric::log  (arg);
    5386          45 :                   case e_log10 : return numeric::log10(arg);
    5387          10 :                   case e_log2  : return numeric::log2 (arg);
    5388           0 :                   case e_log1p : return numeric::log1p(arg);
    5389       95723 :                   case e_neg   : return numeric::neg  (arg);
    5390           0 :                   case e_pos   : return numeric::pos  (arg);
    5391          60 :                   case e_round : return numeric::round(arg);
    5392         370 :                   case e_sin   : return numeric::sin  (arg);
    5393           5 :                   case e_sinc  : return numeric::sinc (arg);
    5394          15 :                   case e_sinh  : return numeric::sinh (arg);
    5395        1708 :                   case e_sqrt  : return numeric::sqrt (arg);
    5396         232 :                   case e_tan   : return numeric::tan  (arg);
    5397          15 :                   case e_tanh  : return numeric::tanh (arg);
    5398           5 :                   case e_cot   : return numeric::cot  (arg);
    5399           5 :                   case e_sec   : return numeric::sec  (arg);
    5400           5 :                   case e_csc   : return numeric::csc  (arg);
    5401           5 :                   case e_r2d   : return numeric::r2d  (arg);
    5402          95 :                   case e_d2r   : return numeric::d2r  (arg);
    5403           5 :                   case e_d2g   : return numeric::d2g  (arg);
    5404           5 :                   case e_g2d   : return numeric::g2d  (arg);
    5405         720 :                   case e_notl  : return numeric::notl (arg);
    5406          45 :                   case e_sgn   : return numeric::sgn  (arg);
    5407           1 :                   case e_erf   : return numeric::erf  (arg);
    5408           1 :                   case e_erfc  : return numeric::erfc (arg);
    5409         470 :                   case e_ncdf  : return numeric::ncdf (arg);
    5410          15 :                   case e_frac  : return numeric::frac (arg);
    5411          22 :                   case e_trunc : return numeric::trunc(arg);
    5412             : 
    5413           0 :                   default      : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
    5414           0 :                                  return std::numeric_limits<T>::quiet_NaN();
    5415             :                }
    5416             :             }
    5417             : 
    5418             :             template <typename T>
    5419      449085 :             inline T process_impl(const operator_type operation, const T arg0, const T arg1)
    5420             :             {
    5421      449085 :                switch (operation)
    5422             :                {
    5423       39384 :                   case e_add    : return (arg0 + arg1);
    5424       32292 :                   case e_sub    : return (arg0 - arg1);
    5425       47651 :                   case e_mul    : return (arg0 * arg1);
    5426       48572 :                   case e_div    : return (arg0 / arg1);
    5427          86 :                   case e_mod    : return modulus<T>(arg0,arg1);
    5428        6284 :                   case e_pow    : return pow<T>(arg0,arg1);
    5429           0 :                   case e_atan2  : return atan2<T>(arg0,arg1);
    5430           0 :                   case e_min    : return std::min<T>(arg0,arg1);
    5431           0 :                   case e_max    : return std::max<T>(arg0,arg1);
    5432           0 :                   case e_logn   : return logn<T>(arg0,arg1);
    5433        1126 :                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
    5434         335 :                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
    5435        2477 :                   case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
    5436         285 :                   case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
    5437         130 :                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
    5438        1000 :                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
    5439         485 :                   case e_and    : return and_opr <T>(arg0,arg1);
    5440         600 :                   case e_nand   : return nand_opr<T>(arg0,arg1);
    5441         440 :                   case e_or     : return or_opr  <T>(arg0,arg1);
    5442         600 :                   case e_nor    : return nor_opr <T>(arg0,arg1);
    5443         240 :                   case e_xor    : return xor_opr <T>(arg0,arg1);
    5444          80 :                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
    5445         160 :                   case e_root   : return root    <T>(arg0,arg1);
    5446         120 :                   case e_roundn : return roundn  <T>(arg0,arg1);
    5447      266688 :                   case e_equal  : return equal   <T>(arg0,arg1);
    5448          20 :                   case e_nequal : return nequal  <T>(arg0,arg1);
    5449          30 :                   case e_hypot  : return hypot   <T>(arg0,arg1);
    5450           0 :                   case e_shr    : return shr     <T>(arg0,arg1);
    5451           0 :                   case e_shl    : return shl     <T>(arg0,arg1);
    5452             : 
    5453           0 :                   default       : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
    5454           0 :                                   return std::numeric_limits<T>::quiet_NaN();
    5455             :                }
    5456             :             }
    5457             : 
    5458             :             template <typename T>
    5459             :             inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
    5460             :             {
    5461             :                switch (operation)
    5462             :                {
    5463             :                   case e_add    : return (arg0 + arg1);
    5464             :                   case e_sub    : return (arg0 - arg1);
    5465             :                   case e_mul    : return (arg0 * arg1);
    5466             :                   case e_div    : return (arg0 / arg1);
    5467             :                   case e_mod    : return arg0 % arg1;
    5468             :                   case e_pow    : return pow<T>(arg0,arg1);
    5469             :                   case e_min    : return std::min<T>(arg0,arg1);
    5470             :                   case e_max    : return std::max<T>(arg0,arg1);
    5471             :                   case e_logn   : return logn<T>(arg0,arg1);
    5472             :                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
    5473             :                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
    5474             :                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
    5475             :                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
    5476             :                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
    5477             :                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
    5478             :                   case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
    5479             :                   case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
    5480             :                   case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
    5481             :                   case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
    5482             :                   case e_xor    : return arg0 ^ arg1;
    5483             :                   case e_xnor   : return !(arg0 ^ arg1);
    5484             :                   case e_root   : return root<T>(arg0,arg1);
    5485             :                   case e_equal  : return arg0 == arg1;
    5486             :                   case e_nequal : return arg0 != arg1;
    5487             :                   case e_hypot  : return hypot<T>(arg0,arg1);
    5488             :                   case e_shr    : return arg0 >> arg1;
    5489             :                   case e_shl    : return arg0 << arg1;
    5490             : 
    5491             :                   default       : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
    5492             :                                   return std::numeric_limits<T>::quiet_NaN();
    5493             :                }
    5494             :             }
    5495             :          }
    5496             : 
    5497             :          template <typename T>
    5498      100770 :          inline T process(const operator_type operation, const T arg)
    5499             :          {
    5500      100770 :             return exprtk::details::numeric::details::process_impl(operation,arg);
    5501             :          }
    5502             : 
    5503             :          template <typename T>
    5504      449085 :          inline T process(const operator_type operation, const T arg0, const T arg1)
    5505             :          {
    5506      449085 :             return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
    5507             :          }
    5508             :       }
    5509             : 
    5510             :       template <typename Node>
    5511             :       struct node_collector_interface
    5512             :       {
    5513             :          typedef Node* node_ptr_t;
    5514             :          typedef Node** node_pp_t;
    5515             :          typedef std::vector<node_pp_t> noderef_list_t;
    5516             : 
    5517     6606989 :          virtual ~node_collector_interface()
    5518     6606989 :          {}
    5519             : 
    5520     4042852 :          virtual void collect_nodes(noderef_list_t&)
    5521     4042852 :          {}
    5522             :       };
    5523             : 
    5524             :       template <typename Node>
    5525             :       struct node_depth_base;
    5526             : 
    5527             :       template <typename T>
    5528             :       class expression_node : public node_collector_interface<expression_node<T> >
    5529             :                             , public node_depth_base<expression_node<T> >
    5530             :       {
    5531             :       public:
    5532             : 
    5533             :          enum node_type
    5534             :          {
    5535             :             e_none          , e_null          , e_constant    , e_unary        ,
    5536             :             e_binary        , e_binary_ext    , e_trinary     , e_quaternary   ,
    5537             :             e_vararg        , e_conditional   , e_while       , e_repeat       ,
    5538             :             e_for           , e_switch        , e_mswitch     , e_return       ,
    5539             :             e_retenv        , e_variable      , e_stringvar   , e_stringconst  ,
    5540             :             e_stringvarrng  , e_cstringvarrng , e_strgenrange , e_strconcat    ,
    5541             :             e_stringvarsize , e_strswap       , e_stringsize  , e_stringvararg ,
    5542             :             e_function      , e_vafunction    , e_genfunction , e_strfunction  ,
    5543             :             e_strcondition  , e_strccondition , e_add         , e_sub          ,
    5544             :             e_mul           , e_div           , e_mod         , e_pow          ,
    5545             :             e_lt            , e_lte           , e_gt          , e_gte          ,
    5546             :             e_eq            , e_ne            , e_and         , e_nand         ,
    5547             :             e_or            , e_nor           , e_xor         , e_xnor         ,
    5548             :             e_in            , e_like          , e_ilike       , e_inranges     ,
    5549             :             e_ipow          , e_ipowinv       , e_abs         , e_acos         ,
    5550             :             e_acosh         , e_asin          , e_asinh       , e_atan         ,
    5551             :             e_atanh         , e_ceil          , e_cos         , e_cosh         ,
    5552             :             e_exp           , e_expm1         , e_floor       , e_log          ,
    5553             :             e_log10         , e_log2          , e_log1p       , e_neg          ,
    5554             :             e_pos           , e_round         , e_sin         , e_sinc         ,
    5555             :             e_sinh          , e_sqrt          , e_tan         , e_tanh         ,
    5556             :             e_cot           , e_sec           , e_csc         , e_r2d          ,
    5557             :             e_d2r           , e_d2g           , e_g2d         , e_notl         ,
    5558             :             e_sgn           , e_erf           , e_erfc        , e_ncdf         ,
    5559             :             e_frac          , e_trunc         , e_uvouv       , e_vov          ,
    5560             :             e_cov           , e_voc           , e_vob         , e_bov          ,
    5561             :             e_cob           , e_boc           , e_vovov       , e_vovoc        ,
    5562             :             e_vocov         , e_covov         , e_covoc       , e_vovovov      ,
    5563             :             e_vovovoc       , e_vovocov       , e_vocovov     , e_covovov      ,
    5564             :             e_covocov       , e_vocovoc       , e_covovoc     , e_vococov      ,
    5565             :             e_sf3ext        , e_sf4ext        , e_nulleq      , e_strass       ,
    5566             :             e_vector        , e_vecsize       , e_vecelem     , e_veccelem     ,
    5567             :             e_vecelemrtc    , e_veccelemrtc   , e_rbvecelem   , e_rbvecelemrtc ,
    5568             :             e_rbveccelem    , e_rbveccelemrtc , e_vecinit     , e_vecvalass    ,
    5569             :             e_vecvecass     , e_vecopvalass   , e_vecopvecass , e_vecfunc      ,
    5570             :             e_vecvecswap    , e_vecvecineq    , e_vecvalineq  , e_valvecineq   ,
    5571             :             e_vecvecarith   , e_vecvalarith   , e_valvecarith , e_vecunaryop   ,
    5572             :             e_vecondition   , e_break         , e_continue    , e_swap         ,
    5573             :             e_assert
    5574             :          };
    5575             : 
    5576             :          typedef T value_type;
    5577             :          typedef expression_node<T>* expression_ptr;
    5578             :          typedef node_collector_interface<expression_node<T> > nci_t;
    5579             :          typedef typename nci_t::noderef_list_t noderef_list_t;
    5580             :          typedef node_depth_base<expression_node<T> > ndb_t;
    5581             : 
    5582     6606989 :          virtual ~expression_node()
    5583     6606989 :          {}
    5584             : 
    5585           0 :          inline virtual T value() const
    5586             :          {
    5587           0 :             return std::numeric_limits<T>::quiet_NaN();
    5588             :          }
    5589             : 
    5590           0 :          inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
    5591             :          {
    5592           0 :             return reinterpret_cast<expression_ptr>(index * 0);
    5593             :          }
    5594             : 
    5595    23087024 :          inline virtual node_type type() const
    5596             :          {
    5597    23087024 :             return e_none;
    5598             :          }
    5599             : 
    5600     5470126 :          inline virtual bool valid() const
    5601             :          {
    5602     5470126 :             return true;
    5603             :          }
    5604             :       }; // class expression_node
    5605             : 
    5606             :       template <typename T>
    5607             :       inline bool is_generally_string_node(const expression_node<T>* node);
    5608             : 
    5609    20653600 :       inline bool is_true(const double v)
    5610             :       {
    5611    20653600 :          return std::not_equal_to<double>()(0.0,v);
    5612             :       }
    5613             : 
    5614             :       inline bool is_true(const long double v)
    5615             :       {
    5616             :          return std::not_equal_to<long double>()(0.0L,v);
    5617             :       }
    5618             : 
    5619             :       inline bool is_true(const float v)
    5620             :       {
    5621             :          return std::not_equal_to<float>()(0.0f,v);
    5622             :       }
    5623             : 
    5624             :       template <typename T>
    5625    20744571 :       inline bool is_true(const expression_node<T>* node)
    5626             :       {
    5627    20744571 :          return std::not_equal_to<T>()(T(0),node->value());
    5628             :       }
    5629             : 
    5630             :       template <typename T>
    5631   166324875 :       inline bool is_true(const std::pair<expression_node<T>*,bool>& node)
    5632             :       {
    5633   166324875 :          return std::not_equal_to<T>()(T(0),node.first->value());
    5634             :       }
    5635             : 
    5636             :       template <typename T>
    5637        1215 :       inline bool is_false(const expression_node<T>* node)
    5638             :       {
    5639        1215 :          return std::equal_to<T>()(T(0),node->value());
    5640             :       }
    5641             : 
    5642             :       template <typename T>
    5643             :       inline bool is_false(const std::pair<expression_node<T>*,bool>& node)
    5644             :       {
    5645             :          return std::equal_to<T>()(T(0),node.first->value());
    5646             :       }
    5647             : 
    5648             :       template <typename T>
    5649       22688 :       inline bool is_literal_node(const expression_node<T>* node)
    5650             :       {
    5651       22688 :          return node && (details::expression_node<T>::e_constant == node->type());
    5652             :       }
    5653             : 
    5654             :       template <typename T>
    5655           0 :       inline bool is_unary_node(const expression_node<T>* node)
    5656             :       {
    5657           0 :          return node && (details::expression_node<T>::e_unary == node->type());
    5658             :       }
    5659             : 
    5660             :       template <typename T>
    5661      915317 :       inline bool is_neg_unary_node(const expression_node<T>* node)
    5662             :       {
    5663      915317 :          return node && (details::expression_node<T>::e_neg == node->type());
    5664             :       }
    5665             : 
    5666             :       template <typename T>
    5667           0 :       inline bool is_binary_node(const expression_node<T>* node)
    5668             :       {
    5669           0 :          return node && (details::expression_node<T>::e_binary == node->type());
    5670             :       }
    5671             : 
    5672             :       template <typename T>
    5673    15010702 :       inline bool is_variable_node(const expression_node<T>* node)
    5674             :       {
    5675    15010702 :          return node && (details::expression_node<T>::e_variable == node->type());
    5676             :       }
    5677             : 
    5678             :       template <typename T>
    5679        5456 :       inline bool is_ivariable_node(const expression_node<T>* node)
    5680             :       {
    5681       10912 :          return node &&
    5682             :                 (
    5683        5456 :                   details::expression_node<T>::e_variable      == node->type() ||
    5684        4816 :                   details::expression_node<T>::e_vecelem       == node->type() ||
    5685        4336 :                   details::expression_node<T>::e_veccelem      == node->type() ||
    5686        4336 :                   details::expression_node<T>::e_vecelemrtc    == node->type() ||
    5687        4324 :                   details::expression_node<T>::e_veccelemrtc   == node->type() ||
    5688        4324 :                   details::expression_node<T>::e_rbvecelem     == node->type() ||
    5689        4324 :                   details::expression_node<T>::e_rbveccelem    == node->type() ||
    5690        4324 :                   details::expression_node<T>::e_rbvecelemrtc  == node->type() ||
    5691        4324 :                   details::expression_node<T>::e_rbveccelemrtc == node->type()
    5692        5456 :                 );
    5693             :       }
    5694             : 
    5695             :       template <typename T>
    5696       30549 :       inline bool is_vector_elem_node(const expression_node<T>* node)
    5697             :       {
    5698       30549 :          return node && (details::expression_node<T>::e_vecelem == node->type());
    5699             :       }
    5700             : 
    5701             :       template <typename T>
    5702       22412 :       inline bool is_vector_celem_node(const expression_node<T>* node)
    5703             :       {
    5704       22412 :          return node && (details::expression_node<T>::e_veccelem == node->type());
    5705             :       }
    5706             : 
    5707             :       template <typename T>
    5708       28914 :       inline bool is_vector_elem_rtc_node(const expression_node<T>* node)
    5709             :       {
    5710       28914 :          return node && (details::expression_node<T>::e_vecelemrtc == node->type());
    5711             :       }
    5712             : 
    5713             :       template <typename T>
    5714       28838 :       inline bool is_vector_celem_rtc_node(const expression_node<T>* node)
    5715             :       {
    5716       28838 :          return node && (details::expression_node<T>::e_veccelemrtc == node->type());
    5717             :       }
    5718             : 
    5719             :       template <typename T>
    5720       29138 :       inline bool is_rebasevector_elem_node(const expression_node<T>* node)
    5721             :       {
    5722       29138 :          return node && (details::expression_node<T>::e_rbvecelem == node->type());
    5723             :       }
    5724             : 
    5725             :       template <typename T>
    5726       27638 :       inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node)
    5727             :       {
    5728       27638 :          return node && (details::expression_node<T>::e_rbvecelemrtc == node->type());
    5729             :       }
    5730             : 
    5731             :       template <typename T>
    5732        9122 :       inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node)
    5733             :       {
    5734        9122 :          return node && (details::expression_node<T>::e_rbveccelemrtc == node->type());
    5735             :       }
    5736             : 
    5737             :       template <typename T>
    5738       28538 :       inline bool is_rebasevector_celem_node(const expression_node<T>* node)
    5739             :       {
    5740       28538 :          return node && (details::expression_node<T>::e_rbveccelem == node->type());
    5741             :       }
    5742             : 
    5743             :       template <typename T>
    5744      359673 :       inline bool is_vector_node(const expression_node<T>* node)
    5745             :       {
    5746      359673 :          return node && (details::expression_node<T>::e_vector == node->type());
    5747             :       }
    5748             : 
    5749             :       template <typename T>
    5750    13547496 :       inline bool is_ivector_node(const expression_node<T>* node)
    5751             :       {
    5752    13547496 :          if (node)
    5753             :          {
    5754    13546044 :             switch (node->type())
    5755             :             {
    5756      120148 :                case details::expression_node<T>::e_vector      :
    5757             :                case details::expression_node<T>::e_vecvalass   :
    5758             :                case details::expression_node<T>::e_vecvecass   :
    5759             :                case details::expression_node<T>::e_vecopvalass :
    5760             :                case details::expression_node<T>::e_vecopvecass :
    5761             :                case details::expression_node<T>::e_vecvecswap  :
    5762             :                case details::expression_node<T>::e_vecvecarith :
    5763             :                case details::expression_node<T>::e_vecvalarith :
    5764             :                case details::expression_node<T>::e_valvecarith :
    5765             :                case details::expression_node<T>::e_vecunaryop  :
    5766      120148 :                case details::expression_node<T>::e_vecondition : return true;
    5767    13425896 :                default                                         : return false;
    5768             :             }
    5769             :          }
    5770             :          else
    5771        1452 :             return false;
    5772             :       }
    5773             : 
    5774             :       template <typename T>
    5775    19259819 :       inline bool is_constant_node(const expression_node<T>* node)
    5776             :       {
    5777    38519638 :          return node &&
    5778             :          (
    5779    19259819 :            details::expression_node<T>::e_constant    == node->type() ||
    5780    13337531 :            details::expression_node<T>::e_stringconst == node->type()
    5781    19259819 :          );
    5782             :       }
    5783             : 
    5784             :       template <typename T>
    5785    11166625 :       inline bool is_null_node(const expression_node<T>* node)
    5786             :       {
    5787    11166625 :          return node && (details::expression_node<T>::e_null == node->type());
    5788             :       }
    5789             : 
    5790             :       template <typename T>
    5791     6275505 :       inline bool is_break_node(const expression_node<T>* node)
    5792             :       {
    5793     6275505 :          return node && (details::expression_node<T>::e_break == node->type());
    5794             :       }
    5795             : 
    5796             :       template <typename T>
    5797     6275185 :       inline bool is_continue_node(const expression_node<T>* node)
    5798             :       {
    5799     6275185 :          return node && (details::expression_node<T>::e_continue == node->type());
    5800             :       }
    5801             : 
    5802             :       template <typename T>
    5803             :       inline bool is_swap_node(const expression_node<T>* node)
    5804             :       {
    5805             :          return node && (details::expression_node<T>::e_swap == node->type());
    5806             :       }
    5807             : 
    5808             :       template <typename T>
    5809           0 :       inline bool is_function(const expression_node<T>* node)
    5810             :       {
    5811           0 :          return node && (details::expression_node<T>::e_function == node->type());
    5812             :       }
    5813             : 
    5814             :       template <typename T>
    5815          54 :       inline bool is_vararg_node(const expression_node<T>* node)
    5816             :       {
    5817          54 :          return node && (details::expression_node<T>::e_vararg == node->type());
    5818             :       }
    5819             : 
    5820             :       template <typename T>
    5821     5822804 :       inline bool is_return_node(const expression_node<T>* node)
    5822             :       {
    5823     5822804 :          return node && (details::expression_node<T>::e_return == node->type());
    5824             :       }
    5825             : 
    5826             :       template <typename T> class unary_node;
    5827             : 
    5828             :       template <typename T>
    5829             :       inline bool is_negate_node(const expression_node<T>* node)
    5830             :       {
    5831             :          if (node && is_unary_node(node))
    5832             :          {
    5833             :             return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
    5834             :          }
    5835             :          else
    5836             :             return false;
    5837             :       }
    5838             : 
    5839             :       template <typename T>
    5840          84 :       inline bool is_assert_node(const expression_node<T>* node)
    5841             :       {
    5842          84 :          return node && (details::expression_node<T>::e_assert == node->type());
    5843             :       }
    5844             : 
    5845             :       template <typename T>
    5846     4085341 :       inline bool branch_deletable(const expression_node<T>* node)
    5847             :       {
    5848     4085341 :          return (0 != node)             &&
    5849     8056685 :                 !is_variable_node(node) &&
    5850     8056685 :                 !is_string_node  (node) ;
    5851             :       }
    5852             : 
    5853             :       template <std::size_t N, typename T>
    5854      747115 :       inline bool all_nodes_valid(expression_node<T>* const (&b)[N])
    5855             :       {
    5856     2305059 :          for (std::size_t i = 0; i < N; ++i)
    5857             :          {
    5858     1557944 :             if (0 == b[i]) return false;
    5859             :          }
    5860             : 
    5861      747115 :          return true;
    5862             :       }
    5863             : 
    5864             :       template <typename T,
    5865             :                 typename Allocator,
    5866             :                 template <typename, typename> class Sequence>
    5867       54774 :       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
    5868             :       {
    5869      213723 :          for (std::size_t i = 0; i < b.size(); ++i)
    5870             :          {
    5871      158949 :             if (0 == b[i]) return false;
    5872             :          }
    5873             : 
    5874       54774 :          return true;
    5875             :       }
    5876             : 
    5877             :       template <std::size_t N, typename T>
    5878        2710 :       inline bool all_nodes_variables(expression_node<T>* const (&b)[N])
    5879             :       {
    5880       12350 :          for (std::size_t i = 0; i < N; ++i)
    5881             :          {
    5882        9640 :             if (0 == b[i])
    5883           0 :                return false;
    5884        9640 :             else if (!is_variable_node(b[i]))
    5885           0 :                return false;
    5886             :          }
    5887             : 
    5888        2710 :          return true;
    5889             :       }
    5890             : 
    5891             :       template <typename T,
    5892             :                 typename Allocator,
    5893             :                 template <typename, typename> class Sequence>
    5894       45814 :       inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b)
    5895             :       {
    5896       52864 :          for (std::size_t i = 0; i < b.size(); ++i)
    5897             :          {
    5898       50556 :             if (0 == b[i])
    5899           0 :                return false;
    5900       50556 :             else if (!is_variable_node(b[i]))
    5901       43506 :                return false;
    5902             :          }
    5903             : 
    5904        2308 :          return true;
    5905             :       }
    5906             : 
    5907             :       template <typename Node>
    5908             :       class node_collection_destructor
    5909             :       {
    5910             :       public:
    5911             : 
    5912             :          typedef node_collector_interface<Node> nci_t;
    5913             : 
    5914             :          typedef typename nci_t::node_ptr_t     node_ptr_t;
    5915             :          typedef typename nci_t::node_pp_t      node_pp_t;
    5916             :          typedef typename nci_t::noderef_list_t noderef_list_t;
    5917             : 
    5918     2886272 :          static void delete_nodes(node_ptr_t& root)
    5919             :          {
    5920     2886272 :             std::vector<node_pp_t> node_delete_list;
    5921     2886272 :             node_delete_list.reserve(1000);
    5922             : 
    5923     2886272 :             collect_nodes(root, node_delete_list);
    5924             : 
    5925     8836395 :             for (std::size_t i = 0; i < node_delete_list.size(); ++i)
    5926             :             {
    5927     5950123 :                node_ptr_t& node = *node_delete_list[i];
    5928             :                exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node)));
    5929     5950123 :                delete node;
    5930     5950123 :                node = reinterpret_cast<node_ptr_t>(0);
    5931             :             }
    5932     2886272 :          }
    5933             : 
    5934             :       private:
    5935             : 
    5936     2886272 :          static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list)
    5937             :          {
    5938     2886272 :             std::deque<node_ptr_t> node_list;
    5939     2886272 :             node_list.push_back(root);
    5940     2886272 :             node_delete_list.push_back(&root);
    5941             : 
    5942     2886272 :             noderef_list_t child_node_delete_list;
    5943     2886272 :             child_node_delete_list.reserve(1000);
    5944             : 
    5945     8836395 :             while (!node_list.empty())
    5946             :             {
    5947     5950123 :                node_list.front()->collect_nodes(child_node_delete_list);
    5948             : 
    5949     5950123 :                if (!child_node_delete_list.empty())
    5950             :                {
    5951     4957198 :                   for (std::size_t i = 0; i < child_node_delete_list.size(); ++i)
    5952             :                   {
    5953     3063851 :                      node_pp_t& node = child_node_delete_list[i];
    5954             : 
    5955     3063851 :                      if (0 == (*node))
    5956             :                      {
    5957             :                         exprtk_debug(("ncd::collect_nodes() - null node encountered.\n"));
    5958             :                      }
    5959             : 
    5960     3063851 :                      node_list.push_back(*node);
    5961             :                   }
    5962             : 
    5963     3786694 :                   node_delete_list.insert(
    5964     1893347 :                      node_delete_list.end(),
    5965             :                      child_node_delete_list.begin(), child_node_delete_list.end());
    5966             : 
    5967     1893347 :                   child_node_delete_list.clear();
    5968             :                }
    5969             : 
    5970     5950123 :                node_list.pop_front();
    5971             :             }
    5972             : 
    5973     2886272 :             std::reverse(node_delete_list.begin(), node_delete_list.end());
    5974     2886272 :          }
    5975             :       };
    5976             : 
    5977             :       template <typename NodeAllocator, typename T, std::size_t N>
    5978        9229 :       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
    5979             :       {
    5980       27742 :          for (std::size_t i = 0; i < N; ++i)
    5981             :          {
    5982       18513 :             free_node(node_allocator,b[i]);
    5983             :          }
    5984        9229 :       }
    5985             : 
    5986             :       template <typename NodeAllocator,
    5987             :                 typename T,
    5988             :                 typename Allocator,
    5989             :                 template <typename, typename> class Sequence>
    5990           0 :       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
    5991             :       {
    5992           0 :          for (std::size_t i = 0; i < b.size(); ++i)
    5993             :          {
    5994           0 :             free_node(node_allocator,b[i]);
    5995             :          }
    5996             : 
    5997           0 :          b.clear();
    5998           0 :       }
    5999             : 
    6000             :       template <typename NodeAllocator, typename T>
    6001     2497640 :       inline void free_node(NodeAllocator&, expression_node<T>*& node)
    6002             :       {
    6003     2497640 :          if ((0 == node) || is_variable_node(node) || is_string_node(node))
    6004             :          {
    6005      321202 :             return;
    6006             :          }
    6007             : 
    6008             :          node_collection_destructor<expression_node<T> >
    6009     2176438 :             ::delete_nodes(node);
    6010             :       }
    6011             : 
    6012             :       template <typename T>
    6013      709834 :       inline void destroy_node(expression_node<T>*& node)
    6014             :       {
    6015      709834 :          if (0 != node)
    6016             :          {
    6017             :             node_collection_destructor<expression_node<T> >
    6018      709834 :                ::delete_nodes(node);
    6019             :          }
    6020      709834 :       }
    6021             : 
    6022             :       template <typename Node>
    6023             :       struct node_depth_base
    6024             :       {
    6025             :          typedef Node* node_ptr_t;
    6026             :          typedef std::pair<node_ptr_t,bool> nb_pair_t;
    6027             : 
    6028     6606989 :          node_depth_base()
    6029     6606989 :          : depth_set(false)
    6030     6606989 :          , depth(0)
    6031     6606989 :          {}
    6032             : 
    6033     6606989 :          virtual ~node_depth_base()
    6034     6606989 :          {}
    6035             : 
    6036     9991221 :          virtual std::size_t node_depth() const { return 1; }
    6037             : 
    6038      209347 :          std::size_t compute_node_depth(const Node* const& node) const
    6039             :          {
    6040      209347 :             if (!depth_set)
    6041             :             {
    6042       69114 :                depth = 1 + (node ? node->node_depth() : 0);
    6043       69114 :                depth_set = true;
    6044             :             }
    6045             : 
    6046      209347 :             return depth;
    6047             :          }
    6048             : 
    6049     2162054 :          std::size_t compute_node_depth(const nb_pair_t& branch) const
    6050             :          {
    6051     2162054 :             if (!depth_set)
    6052             :             {
    6053      806335 :                depth = 1 + (branch.first ? branch.first->node_depth() : 0);
    6054      806335 :                depth_set = true;
    6055             :             }
    6056             : 
    6057     2162054 :             return depth;
    6058             :          }
    6059             : 
    6060             :          template <std::size_t N>
    6061     2893682 :          std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const
    6062             :          {
    6063     2893682 :             if (!depth_set)
    6064             :             {
    6065     1027188 :                depth = 0;
    6066             : 
    6067     3164470 :                for (std::size_t i = 0; i < N; ++i)
    6068             :                {
    6069     2137282 :                   if (branch[i].first)
    6070             :                   {
    6071     1937233 :                      depth = std::max(depth,branch[i].first->node_depth());
    6072             :                   }
    6073             :                }
    6074             : 
    6075     1027188 :                depth += 1;
    6076     1027188 :                depth_set = true;
    6077             :             }
    6078             : 
    6079     2893682 :             return depth;
    6080             :          }
    6081             : 
    6082             :          template <typename BranchType>
    6083        5958 :          std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const
    6084             :          {
    6085        5958 :             return std::max(compute_node_depth(n0), compute_node_depth(n1));
    6086             :          }
    6087             : 
    6088             :          template <typename BranchType>
    6089        3740 :          std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const
    6090             :          {
    6091        3740 :             return std::max(compute_node_depth(n0),
    6092        7480 :                    std::max(compute_node_depth(n1), compute_node_depth(n2)));
    6093             :          }
    6094             : 
    6095             :          template <typename BranchType>
    6096        2723 :          std::size_t max_node_depth(const BranchType& n0, const BranchType& n1,
    6097             :                                     const BranchType& n2, const BranchType& n3) const
    6098             :          {
    6099        2723 :             return std::max(
    6100        2723 :                      std::max(compute_node_depth(n0), compute_node_depth(n1)),
    6101        5446 :                      std::max(compute_node_depth(n2), compute_node_depth(n3)));
    6102             :          }
    6103             : 
    6104             :          template <typename BranchType>
    6105       13384 :          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
    6106             :          {
    6107       13384 :             if (!depth_set)
    6108             :             {
    6109        5958 :                depth = 1 + max_node_depth(n0, n1);
    6110        5958 :                depth_set = true;
    6111             :             }
    6112             : 
    6113       13384 :             return depth;
    6114             :          }
    6115             : 
    6116             :          template <typename BranchType>
    6117        9258 :          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
    6118             :                                         const BranchType& n2) const
    6119             :          {
    6120        9258 :             if (!depth_set)
    6121             :             {
    6122        3740 :                depth = 1 + max_node_depth(n0, n1, n2);
    6123        3740 :                depth_set = true;
    6124             :             }
    6125             : 
    6126        9258 :             return depth;
    6127             :          }
    6128             : 
    6129             :          template <typename BranchType>
    6130        6774 :          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
    6131             :                                         const BranchType& n2, const BranchType& n3) const
    6132             :          {
    6133        6774 :             if (!depth_set)
    6134             :             {
    6135        2723 :                depth = 1 + max_node_depth(n0, n1, n2, n3);
    6136        2723 :                depth_set = true;
    6137             :             }
    6138             : 
    6139        6774 :             return depth;
    6140             :          }
    6141             : 
    6142             :          template <typename Allocator,
    6143             :                    template <typename, typename> class Sequence>
    6144       64453 :          std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const
    6145             :          {
    6146       64453 :             if (!depth_set)
    6147             :             {
    6148       91003 :                for (std::size_t i = 0; i < branch_list.size(); ++i)
    6149             :                {
    6150       67047 :                   if (branch_list[i])
    6151             :                   {
    6152       67047 :                      depth = std::max(depth, compute_node_depth(branch_list[i]));
    6153             :                   }
    6154             :                }
    6155       23956 :                depth_set = true;
    6156             :             }
    6157             : 
    6158       64453 :             return depth;
    6159             :          }
    6160             : 
    6161             :          template <typename Allocator,
    6162             :                    template <typename, typename> class Sequence>
    6163       72363 :          std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const
    6164             :          {
    6165       72363 :             if (!depth_set)
    6166             :             {
    6167      192092 :                for (std::size_t i = 0; i < branch_list.size(); ++i)
    6168             :                {
    6169      142300 :                   if (branch_list[i].first)
    6170             :                   {
    6171      142300 :                      depth = std::max(depth, compute_node_depth(branch_list[i].first));
    6172             :                   }
    6173             :                }
    6174             : 
    6175       49792 :                depth_set = true;
    6176             :             }
    6177             : 
    6178       72363 :             return depth;
    6179             :          }
    6180             : 
    6181             :          mutable bool depth_set;
    6182             :          mutable std::size_t depth;
    6183             : 
    6184             :          template <typename NodeSequence>
    6185     3182804 :          void collect(node_ptr_t const& node,
    6186             :                       const bool deletable,
    6187             :                       NodeSequence& delete_node_list) const
    6188             :          {
    6189     3182804 :             if ((0 != node) && deletable)
    6190             :             {
    6191     3063782 :                delete_node_list.push_back(const_cast<node_ptr_t*>(&node));
    6192             :             }
    6193     3182804 :          }
    6194             : 
    6195             :          template <typename NodeSequence>
    6196      828027 :          void collect(const nb_pair_t& branch,
    6197             :                       NodeSequence& delete_node_list) const
    6198             :          {
    6199      828027 :             collect(branch.first, branch.second, delete_node_list);
    6200      828027 :          }
    6201             : 
    6202             :          template <typename NodeSequence>
    6203             :          void collect(Node*& node,
    6204             :                       NodeSequence& delete_node_list) const
    6205             :          {
    6206             :             collect(node, branch_deletable(node), delete_node_list);
    6207             :          }
    6208             : 
    6209             :          template <std::size_t N, typename NodeSequence>
    6210     1027188 :          void collect(const nb_pair_t(&branch)[N],
    6211             :                       NodeSequence& delete_node_list) const
    6212             :          {
    6213     3164470 :             for (std::size_t i = 0; i < N; ++i)
    6214             :             {
    6215     2137282 :                collect(branch[i].first, branch[i].second, delete_node_list);
    6216             :             }
    6217     1027188 :          }
    6218             : 
    6219             :          template <typename Allocator,
    6220             :                    template <typename, typename> class Sequence,
    6221             :                    typename NodeSequence>
    6222       49792 :          void collect(const Sequence<nb_pair_t, Allocator>& branch,
    6223             :                       NodeSequence& delete_node_list) const
    6224             :          {
    6225      200357 :             for (std::size_t i = 0; i < branch.size(); ++i)
    6226             :             {
    6227      150565 :                collect(branch[i].first, branch[i].second, delete_node_list);
    6228             :             }
    6229       49792 :          }
    6230             : 
    6231             :          template <typename Allocator,
    6232             :                    template <typename, typename> class Sequence,
    6233             :                    typename NodeSequence>
    6234       23907 :          void collect(const Sequence<node_ptr_t, Allocator>& branch_list,
    6235             :                       NodeSequence& delete_node_list) const
    6236             :          {
    6237       90837 :             for (std::size_t i = 0; i < branch_list.size(); ++i)
    6238             :             {
    6239       66930 :                collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list);
    6240             :             }
    6241       23907 :          }
    6242             : 
    6243             :          template <typename Boolean,
    6244             :                    typename AllocatorT,
    6245             :                    typename AllocatorB,
    6246             :                    template <typename, typename> class Sequence,
    6247             :                    typename NodeSequence>
    6248             :          void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list,
    6249             :                       const Sequence<Boolean, AllocatorB>& branch_deletable_list,
    6250             :                       NodeSequence& delete_node_list) const
    6251             :          {
    6252             :             for (std::size_t i = 0; i < branch_list.size(); ++i)
    6253             :             {
    6254             :                collect(branch_list[i], branch_deletable_list[i], delete_node_list);
    6255             :             }
    6256             :          }
    6257             :       };
    6258             : 
    6259             :       template <typename Type>
    6260             :       class vector_holder
    6261             :       {
    6262             :       private:
    6263             : 
    6264             :          typedef Type value_type;
    6265             :          typedef value_type* value_ptr;
    6266             :          typedef const value_ptr const_value_ptr;
    6267             :          typedef vector_holder<Type> vector_holder_t;
    6268             : 
    6269             :          class vector_holder_base
    6270             :          {
    6271             :          public:
    6272             : 
    6273           0 :             virtual ~vector_holder_base()
    6274           0 :             {}
    6275             : 
    6276       88871 :             inline value_ptr operator[](const std::size_t& index) const
    6277             :             {
    6278       88871 :                return value_at(index);
    6279             :             }
    6280             : 
    6281      226115 :             inline std::size_t size() const
    6282             :             {
    6283      226115 :                return vector_size();
    6284             :             }
    6285             : 
    6286      151627 :             inline std::size_t base_size() const
    6287             :             {
    6288      151627 :                return vector_base_size();
    6289             :             }
    6290             : 
    6291       10391 :             inline value_ptr data() const
    6292             :             {
    6293       10391 :                return value_at(0);
    6294             :             }
    6295             : 
    6296      171868 :             virtual inline bool rebaseable() const
    6297             :             {
    6298      171868 :                return false;
    6299             :             }
    6300             : 
    6301           0 :             virtual void set_ref(value_ptr*)
    6302           0 :             {}
    6303             : 
    6304         478 :             virtual void remove_ref(value_ptr*)
    6305         478 :             {}
    6306             : 
    6307           0 :             virtual vector_view<Type>* rebaseable_instance()
    6308             :             {
    6309           0 :                return reinterpret_cast<vector_view<Type>*>(0);
    6310             :             }
    6311             : 
    6312             :          protected:
    6313             : 
    6314             :             virtual value_ptr value_at(const std::size_t&) const = 0;
    6315             :             virtual std::size_t vector_size()              const = 0;
    6316             :             virtual std::size_t vector_base_size()         const = 0;
    6317             :          };
    6318             : 
    6319             :          class array_vector_impl exprtk_final : public vector_holder_base
    6320             :          {
    6321             :          public:
    6322             : 
    6323       47281 :             array_vector_impl(const Type* vec, const std::size_t& vec_size)
    6324       47281 :             : vec_(vec)
    6325       47281 :             , size_(vec_size)
    6326       47281 :             {}
    6327             : 
    6328             :          protected:
    6329             : 
    6330       91444 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6331             :             {
    6332       91444 :                assert(index < size_);
    6333       91444 :                return const_cast<const_value_ptr>(vec_ + index);
    6334             :             }
    6335             : 
    6336      357633 :             std::size_t vector_size() const exprtk_override
    6337             :             {
    6338      357633 :                return size_;
    6339             :             }
    6340             : 
    6341      148211 :             std::size_t vector_base_size() const exprtk_override
    6342             :             {
    6343      148211 :                return vector_size();
    6344             :             }
    6345             : 
    6346             :          private:
    6347             : 
    6348             :             array_vector_impl(const array_vector_impl&) exprtk_delete;
    6349             :             array_vector_impl& operator=(const array_vector_impl&) exprtk_delete;
    6350             : 
    6351             :             const Type* vec_;
    6352             :             const std::size_t size_;
    6353             :          };
    6354             : 
    6355             :          template <typename Allocator,
    6356             :                    template <typename, typename> class Sequence>
    6357             :          class sequence_vector_impl exprtk_final : public vector_holder_base
    6358             :          {
    6359             :          public:
    6360             : 
    6361             :             typedef Sequence<Type,Allocator> sequence_t;
    6362             : 
    6363          84 :             explicit sequence_vector_impl(sequence_t& seq)
    6364          84 :             : sequence_(seq)
    6365          84 :             {}
    6366             : 
    6367             :          protected:
    6368             : 
    6369          10 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6370             :             {
    6371          10 :                assert(index < sequence_.size());
    6372          10 :                return (&sequence_[index]);
    6373             :             }
    6374             : 
    6375          60 :             std::size_t vector_size() const exprtk_override
    6376             :             {
    6377          60 :                return sequence_.size();
    6378             :             }
    6379             : 
    6380          20 :             std::size_t vector_base_size() const exprtk_override
    6381             :             {
    6382          20 :                return vector_size();
    6383             :             }
    6384             : 
    6385             :          private:
    6386             : 
    6387             :             sequence_vector_impl(const sequence_vector_impl&) exprtk_delete;
    6388             :             sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete;
    6389             : 
    6390             :             sequence_t& sequence_;
    6391             :          };
    6392             : 
    6393             :          class vector_view_impl exprtk_final : public vector_holder_base
    6394             :          {
    6395             :          public:
    6396             : 
    6397             :             typedef exprtk::vector_view<Type> vector_view_t;
    6398             : 
    6399        4195 :             vector_view_impl(vector_view_t& vec_view)
    6400        4195 :             : vec_view_(vec_view)
    6401             :             {
    6402        4195 :                assert(vec_view_.size() > 0);
    6403        4195 :             }
    6404             : 
    6405        3559 :             void set_ref(value_ptr* ref) exprtk_override
    6406             :             {
    6407        3559 :                vec_view_.set_ref(ref);
    6408        3559 :             }
    6409             : 
    6410        3559 :             void remove_ref(value_ptr* ref) exprtk_override
    6411             :             {
    6412        3559 :                vec_view_.remove_ref(ref);
    6413        3559 :             }
    6414             : 
    6415       10649 :             bool rebaseable() const exprtk_override
    6416             :             {
    6417       10649 :                return true;
    6418             :             }
    6419             : 
    6420         658 :             vector_view<Type>* rebaseable_instance() exprtk_override
    6421             :             {
    6422         658 :                return &vec_view_;
    6423             :             }
    6424             : 
    6425             :          protected:
    6426             : 
    6427        7555 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6428             :             {
    6429        7555 :                assert(index < vec_view_.size());
    6430        7555 :                return (&vec_view_[index]);
    6431             :             }
    6432             : 
    6433       15714 :             std::size_t vector_size() const exprtk_override
    6434             :             {
    6435       15714 :                return vec_view_.size();
    6436             :             }
    6437             : 
    6438        2662 :             std::size_t vector_base_size() const exprtk_override
    6439             :             {
    6440        2662 :                return vec_view_.base_size();
    6441             :             }
    6442             : 
    6443             :          private:
    6444             : 
    6445             :             vector_view_impl(const vector_view_impl&) exprtk_delete;
    6446             :             vector_view_impl& operator=(const vector_view_impl&) exprtk_delete;
    6447             : 
    6448             :             vector_view_t& vec_view_;
    6449             :          };
    6450             : 
    6451             :          class resizable_vector_impl exprtk_final : public vector_holder_base
    6452             :          {
    6453             :          public:
    6454             : 
    6455         478 :             resizable_vector_impl(vector_holder& vec_view_holder,
    6456             :                                   const Type* vec,
    6457             :                                   const std::size_t& vec_size)
    6458         478 :             : vec_(vec)
    6459         478 :             , size_(vec_size)
    6460         478 :             , vec_view_holder_(*vec_view_holder.rebaseable_instance())
    6461             :             {
    6462         478 :                assert(vec_view_holder.rebaseable_instance());
    6463         478 :                assert(size_ <= vector_base_size());
    6464         478 :             }
    6465             : 
    6466           0 :             virtual ~resizable_vector_impl()
    6467           0 :             {}
    6468             : 
    6469             :          protected:
    6470             : 
    6471         253 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6472             :             {
    6473         253 :                assert(index < vector_size());
    6474         253 :                return const_cast<const_value_ptr>(vec_ + index);
    6475             :             }
    6476             : 
    6477        1192 :             std::size_t vector_size() const exprtk_override
    6478             :             {
    6479        1192 :                return vec_view_holder_.size();
    6480             :             }
    6481             : 
    6482        1212 :             std::size_t vector_base_size() const exprtk_override
    6483             :             {
    6484        1212 :                return vec_view_holder_.base_size();
    6485             :             }
    6486             : 
    6487         903 :             bool rebaseable() const exprtk_override
    6488             :             {
    6489         903 :                return true;
    6490             :             }
    6491             : 
    6492         520 :             virtual vector_view<Type>* rebaseable_instance() exprtk_override
    6493             :             {
    6494         520 :                return &vec_view_holder_;
    6495             :             }
    6496             : 
    6497             :          private:
    6498             : 
    6499             :             resizable_vector_impl(const resizable_vector_impl&) exprtk_delete;
    6500             :             resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete;
    6501             : 
    6502             :             const Type* vec_;
    6503             :             const std::size_t size_;
    6504             :             vector_view<Type>& vec_view_holder_;
    6505             :          };
    6506             : 
    6507             :       public:
    6508             : 
    6509             :          typedef typename details::vec_data_store<Type> vds_t;
    6510             : 
    6511       25420 :          vector_holder(Type* vec, const std::size_t& vec_size)
    6512       25420 :          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
    6513       25420 :          {}
    6514             : 
    6515       21861 :          explicit vector_holder(const vds_t& vds)
    6516       21861 :          : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
    6517       21861 :          {}
    6518             : 
    6519             :          template <typename Allocator>
    6520          84 :          explicit vector_holder(std::vector<Type,Allocator>& vec)
    6521          84 :          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
    6522          84 :          {}
    6523             : 
    6524        4195 :          explicit vector_holder(exprtk::vector_view<Type>& vec)
    6525        4195 :          : vector_holder_base_(new(buffer)vector_view_impl(vec))
    6526        4195 :          {}
    6527             : 
    6528         478 :          explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds)
    6529         478 :          : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size()))
    6530         478 :          {}
    6531             : 
    6532       88871 :          inline value_ptr operator[](const std::size_t& index) const
    6533             :          {
    6534       88871 :             return (*vector_holder_base_)[index];
    6535             :          }
    6536             : 
    6537      226115 :          inline std::size_t size() const
    6538             :          {
    6539      226115 :             return vector_holder_base_->size();
    6540             :          }
    6541             : 
    6542      151627 :          inline std::size_t base_size() const
    6543             :          {
    6544      151627 :             return vector_holder_base_->base_size();
    6545             :          }
    6546             : 
    6547       10391 :          inline value_ptr data() const
    6548             :          {
    6549       10391 :             return vector_holder_base_->data();
    6550             :          }
    6551             : 
    6552       49912 :          void set_ref(value_ptr* ref)
    6553             :          {
    6554       49912 :             if (rebaseable())
    6555             :             {
    6556        3559 :                vector_holder_base_->set_ref(ref);
    6557             :             }
    6558       49912 :          }
    6559             : 
    6560       72251 :          void remove_ref(value_ptr* ref)
    6561             :          {
    6562       72251 :             if (rebaseable())
    6563             :             {
    6564        4037 :                vector_holder_base_->remove_ref(ref);
    6565             :             }
    6566       72251 :          }
    6567             : 
    6568      183420 :          bool rebaseable() const
    6569             :          {
    6570      183420 :             return vector_holder_base_->rebaseable();
    6571             :          }
    6572             : 
    6573        1178 :          vector_view<Type>* rebaseable_instance()
    6574             :          {
    6575        1178 :             return vector_holder_base_->rebaseable_instance();
    6576             :          }
    6577             : 
    6578             :       private:
    6579             : 
    6580             :          vector_holder(const vector_holder<Type>&) exprtk_delete;
    6581             :          vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete;
    6582             : 
    6583             :          mutable vector_holder_base* vector_holder_base_;
    6584             :          uchar_t buffer[64];
    6585             :       };
    6586             : 
    6587             :       template <typename T>
    6588             :       class null_node exprtk_final : public expression_node<T>
    6589             :       {
    6590             :       public:
    6591             : 
    6592         377 :          inline T value() const exprtk_override
    6593             :          {
    6594         377 :             return std::numeric_limits<T>::quiet_NaN();
    6595             :          }
    6596             : 
    6597      693627 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6598             :          {
    6599      693627 :             return expression_node<T>::e_null;
    6600             :          }
    6601             :       };
    6602             : 
    6603             :       template <typename T, std::size_t N>
    6604     9668080 :       inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N],
    6605             :                                         expression_node<T>* b,
    6606             :                                         const std::size_t& index)
    6607             :       {
    6608     9668080 :          if (b && (index < N))
    6609             :          {
    6610     1937233 :             branch[index] = std::make_pair(b,branch_deletable(b));
    6611             :          }
    6612     9668080 :       }
    6613             : 
    6614             :       template <typename T>
    6615      970327 :       inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b)
    6616             :       {
    6617      970327 :          if (b)
    6618             :          {
    6619      970112 :             branch = std::make_pair(b,branch_deletable(b));
    6620             :          }
    6621      970327 :       }
    6622             : 
    6623             :       template <std::size_t N, typename T>
    6624      966808 :       inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
    6625             :                                 expression_node<T>* b0,
    6626             :                                 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
    6627             :                                 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
    6628             :                                 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
    6629             :                                 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
    6630             :                                 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
    6631             :                                 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
    6632             :                                 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
    6633             :                                 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
    6634             :                                 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
    6635             :       {
    6636      966808 :          construct_branch_pair(branch, b0, 0);
    6637      966808 :          construct_branch_pair(branch, b1, 1);
    6638      966808 :          construct_branch_pair(branch, b2, 2);
    6639      966808 :          construct_branch_pair(branch, b3, 3);
    6640      966808 :          construct_branch_pair(branch, b4, 4);
    6641      966808 :          construct_branch_pair(branch, b5, 5);
    6642      966808 :          construct_branch_pair(branch, b6, 6);
    6643      966808 :          construct_branch_pair(branch, b7, 7);
    6644      966808 :          construct_branch_pair(branch, b8, 8);
    6645      966808 :          construct_branch_pair(branch, b9, 9);
    6646      966808 :       }
    6647             : 
    6648             :       template <typename T>
    6649             :       class null_eq_node exprtk_final : public expression_node<T>
    6650             :       {
    6651             :       public:
    6652             : 
    6653             :          typedef expression_node<T>* expression_ptr;
    6654             :          typedef std::pair<expression_ptr,bool> branch_t;
    6655             : 
    6656         195 :          explicit null_eq_node(expression_ptr branch, const bool equality = true)
    6657         195 :          : equality_(equality)
    6658             :          {
    6659         195 :             construct_branch_pair(branch_, branch);
    6660         195 :             assert(valid());
    6661         195 :          }
    6662             : 
    6663         195 :          inline T value() const exprtk_override
    6664             :          {
    6665         195 :             const T v = branch_.first->value();
    6666         195 :             const bool result = details::numeric::is_nan(v);
    6667             : 
    6668         195 :             if (result)
    6669         195 :                return equality_ ? T(1) : T(0);
    6670             :             else
    6671           0 :                return equality_ ? T(0) : T(1);
    6672             :          }
    6673             : 
    6674        1170 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6675             :          {
    6676        1170 :             return expression_node<T>::e_nulleq;
    6677             :          }
    6678             : 
    6679           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6680             :          {
    6681           0 :             return branch_.first;
    6682             :          }
    6683             : 
    6684         225 :          inline bool valid() const exprtk_override
    6685             :          {
    6686         225 :             return branch_.first;
    6687             :          }
    6688             : 
    6689         195 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6690             :          {
    6691         195 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    6692         195 :          }
    6693             : 
    6694         405 :          std::size_t node_depth() const exprtk_override
    6695             :          {
    6696         405 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
    6697             :          }
    6698             : 
    6699             :       private:
    6700             : 
    6701             :          bool equality_;
    6702             :          branch_t branch_;
    6703             :       };
    6704             : 
    6705             :       template <typename T>
    6706             :       class literal_node exprtk_final : public expression_node<T>
    6707             :       {
    6708             :       public:
    6709             : 
    6710     2174244 :          explicit literal_node(const T& v)
    6711     2174244 :          : value_(v)
    6712     2174244 :          {}
    6713             : 
    6714   139260863 :          inline T value() const exprtk_override
    6715             :          {
    6716   139260863 :             return value_;
    6717             :          }
    6718             : 
    6719    31374113 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6720             :          {
    6721    31374113 :             return expression_node<T>::e_constant;
    6722             :          }
    6723             : 
    6724           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6725             :          {
    6726           0 :             return reinterpret_cast<expression_node<T>*>(0);
    6727             :          }
    6728             : 
    6729             :       private:
    6730             : 
    6731             :          literal_node(const literal_node<T>&) exprtk_delete;
    6732             :          literal_node<T>& operator=(const literal_node<T>&) exprtk_delete;
    6733             : 
    6734             :          const T value_;
    6735             :       };
    6736             : 
    6737             :       template <typename T>
    6738             :       struct range_pack;
    6739             : 
    6740             :       template <typename T>
    6741             :       struct range_data_type;
    6742             : 
    6743             :       template <typename T>
    6744             :       class range_interface
    6745             :       {
    6746             :       public:
    6747             : 
    6748             :          typedef range_pack<T> range_t;
    6749             : 
    6750      245984 :          virtual ~range_interface()
    6751      245984 :          {}
    6752             : 
    6753             :          virtual range_t& range_ref() = 0;
    6754             : 
    6755             :          virtual const range_t& range_ref() const = 0;
    6756             :       };
    6757             : 
    6758             :       #ifndef exprtk_disable_string_capabilities
    6759             :       template <typename T>
    6760             :       class string_base_node
    6761             :       {
    6762             :       public:
    6763             : 
    6764             :          typedef range_data_type<T> range_data_type_t;
    6765             : 
    6766      245984 :          virtual ~string_base_node()
    6767      245984 :          {}
    6768             : 
    6769             :          virtual std::string str () const = 0;
    6770             : 
    6771             :          virtual char_cptr   base() const = 0;
    6772             : 
    6773             :          virtual std::size_t size() const = 0;
    6774             :       };
    6775             : 
    6776             :       template <typename T>
    6777             :       class string_literal_node exprtk_final
    6778             :                                 : public expression_node <T>
    6779             :                                 , public string_base_node<T>
    6780             :                                 , public range_interface <T>
    6781             :       {
    6782             :       public:
    6783             : 
    6784             :          typedef range_pack<T> range_t;
    6785             : 
    6786       55957 :          explicit string_literal_node(const std::string& v)
    6787       55957 :          : value_(v)
    6788             :          {
    6789       55957 :             rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0);
    6790       55957 :             rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size());
    6791       55957 :             rp_.cache.first  = rp_.n0_c.second;
    6792       55957 :             rp_.cache.second = rp_.n1_c.second;
    6793       55957 :          }
    6794             : 
    6795       24518 :          inline T value() const exprtk_override
    6796             :          {
    6797       24518 :             return std::numeric_limits<T>::quiet_NaN();
    6798             :          }
    6799             : 
    6800      928968 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6801             :          {
    6802      928968 :             return expression_node<T>::e_stringconst;
    6803             :          }
    6804             : 
    6805           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6806             :          {
    6807           0 :             return reinterpret_cast<expression_node<T>*>(0);
    6808             :          }
    6809             : 
    6810       33183 :          std::string str() const exprtk_override
    6811             :          {
    6812       33183 :             return value_;
    6813             :          }
    6814             : 
    6815       21628 :          char_cptr base() const exprtk_override
    6816             :          {
    6817       21628 :             return value_.data();
    6818             :          }
    6819             : 
    6820       24478 :          std::size_t size() const exprtk_override
    6821             :          {
    6822       24478 :             return value_.size();
    6823             :          }
    6824             : 
    6825       20382 :          range_t& range_ref() exprtk_override
    6826             :          {
    6827       20382 :             return rp_;
    6828             :          }
    6829             : 
    6830           0 :          const range_t& range_ref() const exprtk_override
    6831             :          {
    6832           0 :             return rp_;
    6833             :          }
    6834             : 
    6835             :       private:
    6836             : 
    6837             :          string_literal_node(const string_literal_node<T>&) exprtk_delete;
    6838             :          string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete;
    6839             : 
    6840             :          const std::string value_;
    6841             :          range_t rp_;
    6842             :       };
    6843             :       #endif
    6844             : 
    6845             :       template <typename T>
    6846             :       class unary_node : public expression_node<T>
    6847             :       {
    6848             :       public:
    6849             : 
    6850             :          typedef expression_node<T>* expression_ptr;
    6851             :          typedef std::pair<expression_ptr,bool> branch_t;
    6852             : 
    6853      103460 :          unary_node(const operator_type& opr, expression_ptr branch)
    6854      103460 :          : operation_(opr)
    6855             :          {
    6856      103460 :             construct_branch_pair(branch_,branch);
    6857      103460 :             assert(valid());
    6858      103460 :          }
    6859             : 
    6860      100770 :          inline T value() const exprtk_override
    6861             :          {
    6862             :             return numeric::process<T>
    6863      100770 :                      (operation_,branch_.first->value());
    6864             :          }
    6865             : 
    6866      201540 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6867             :          {
    6868      201540 :             return expression_node<T>::e_unary;
    6869             :          }
    6870             : 
    6871             :          inline operator_type operation()
    6872             :          {
    6873             :             return operation_;
    6874             :          }
    6875             : 
    6876       10744 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6877             :          {
    6878       10744 :             return branch_.first;
    6879             :          }
    6880             : 
    6881      120624 :          inline bool valid() const exprtk_override
    6882             :          {
    6883      120624 :             return branch_.first && branch_.first->valid();
    6884             :          }
    6885             : 
    6886             :          inline void release()
    6887             :          {
    6888             :             branch_.second = false;
    6889             :          }
    6890             : 
    6891      103460 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6892             :          {
    6893      103460 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    6894      103460 :          }
    6895             : 
    6896      208158 :          std::size_t node_depth() const exprtk_final
    6897             :          {
    6898      208158 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
    6899             :          }
    6900             : 
    6901             :       private:
    6902             : 
    6903             :          operator_type operation_;
    6904             :          branch_t branch_;
    6905             :       };
    6906             : 
    6907             :       template <typename T>
    6908             :       class binary_node : public expression_node<T>
    6909             :       {
    6910             :       public:
    6911             : 
    6912             :          typedef expression_node<T>* expression_ptr;
    6913             :          typedef std::pair<expression_ptr,bool> branch_t;
    6914             : 
    6915      556999 :          binary_node(const operator_type& opr,
    6916             :                      expression_ptr branch0,
    6917             :                      expression_ptr branch1)
    6918      556999 :          : operation_(opr)
    6919             :          {
    6920      556999 :             init_branches<2>(branch_, branch0, branch1);
    6921      556999 :             assert(valid());
    6922      556999 :          }
    6923             : 
    6924      449085 :          inline T value() const exprtk_override
    6925             :          {
    6926             :             return numeric::process<T>
    6927     1796340 :                    (
    6928      449085 :                       operation_,
    6929      449085 :                       branch_[0].first->value(),
    6930      449085 :                       branch_[1].first->value()
    6931      449085 :                    );
    6932             :          }
    6933             : 
    6934     2290787 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6935             :          {
    6936     2290787 :             return expression_node<T>::e_binary;
    6937             :          }
    6938             : 
    6939             :          inline operator_type operation()
    6940             :          {
    6941             :             return operation_;
    6942             :          }
    6943             : 
    6944   208795773 :          inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
    6945             :          {
    6946   208795773 :             assert(index < 2);
    6947   208795773 :             return branch_[index].first;
    6948             :          }
    6949             : 
    6950     1080684 :          inline bool valid() const exprtk_override
    6951             :          {
    6952             :             return
    6953     1080684 :                branch_[0].first && branch_[0].first->valid() &&
    6954     2161368 :                branch_[1].first && branch_[1].first->valid() ;
    6955             :          }
    6956             : 
    6957      556999 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6958             :          {
    6959      556999 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    6960      556999 :          }
    6961             : 
    6962     1497235 :          std::size_t node_depth() const exprtk_final
    6963             :          {
    6964     1497235 :             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
    6965             :          }
    6966             : 
    6967             :       private:
    6968             : 
    6969             :          operator_type operation_;
    6970             :          branch_t branch_[2];
    6971             :       };
    6972             : 
    6973             :       template <typename T, typename Operation>
    6974             :       class binary_ext_node exprtk_final : public expression_node<T>
    6975             :       {
    6976             :       public:
    6977             : 
    6978             :          typedef expression_node<T>* expression_ptr;
    6979             :          typedef std::pair<expression_ptr,bool> branch_t;
    6980             : 
    6981      407007 :          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
    6982      407007 :          {
    6983      407007 :             init_branches<2>(branch_, branch0, branch1);
    6984      407007 :             assert(valid());
    6985      407007 :          }
    6986             : 
    6987    63295748 :          inline T value() const exprtk_override
    6988             :          {
    6989    63295748 :             const T arg0 = branch_[0].first->value();
    6990    63295748 :             const T arg1 = branch_[1].first->value();
    6991   126591496 :             return Operation::process(arg0,arg1);
    6992             :          }
    6993             : 
    6994    11834392 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6995             :          {
    6996    11834392 :             return expression_node<T>::e_binary_ext;
    6997             :          }
    6998             : 
    6999             :          inline operator_type operation()
    7000             :          {
    7001             :             return Operation::operation();
    7002             :          }
    7003             : 
    7004           0 :          inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
    7005             :          {
    7006           0 :             assert(index < 2);
    7007           0 :             return branch_[index].first;
    7008             :          }
    7009             : 
    7010     2723515 :          inline bool valid() const exprtk_override
    7011             :          {
    7012             :             return
    7013     2723515 :                branch_[0].first && branch_[0].first->valid() &&
    7014     5447030 :                branch_[1].first && branch_[1].first->valid() ;
    7015             :          }
    7016             : 
    7017      407007 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7018             :          {
    7019      407007 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    7020      407007 :          }
    7021             : 
    7022     1213243 :          std::size_t node_depth() const exprtk_override
    7023             :          {
    7024     1213243 :             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
    7025             :          }
    7026             : 
    7027             :       protected:
    7028             : 
    7029             :          branch_t branch_[2];
    7030             :       };
    7031             : 
    7032             :       template <typename T>
    7033             :       class trinary_node : public expression_node<T>
    7034             :       {
    7035             :       public:
    7036             : 
    7037             :          typedef expression_node<T>* expression_ptr;
    7038             :          typedef std::pair<expression_ptr,bool> branch_t;
    7039             : 
    7040        1987 :          trinary_node(const operator_type& opr,
    7041             :                       expression_ptr branch0,
    7042             :                       expression_ptr branch1,
    7043             :                       expression_ptr branch2)
    7044        1987 :          : operation_(opr)
    7045             :          {
    7046        1987 :             init_branches<3>(branch_, branch0, branch1, branch2);
    7047        1987 :             assert(valid());
    7048        1987 :          }
    7049             : 
    7050    40000116 :          inline T value() const exprtk_override
    7051             :          {
    7052    40000116 :             const T arg0 = branch_[0].first->value();
    7053    40000116 :             const T arg1 = branch_[1].first->value();
    7054    40000116 :             const T arg2 = branch_[2].first->value();
    7055             : 
    7056    40000116 :             switch (operation_)
    7057             :             {
    7058          30 :                case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
    7059             : 
    7060    40000086 :                case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
    7061             : 
    7062           0 :                case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
    7063           0 :                                    return arg1;
    7064             :                                 else
    7065           0 :                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
    7066             : 
    7067           0 :                default        : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
    7068           0 :                                 return std::numeric_limits<T>::quiet_NaN();
    7069             :             }
    7070             :          }
    7071             : 
    7072        1705 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7073             :          {
    7074        1705 :             return expression_node<T>::e_trinary;
    7075             :          }
    7076             : 
    7077        1998 :          inline bool valid() const exprtk_override
    7078             :          {
    7079             :             return
    7080        1998 :                branch_[0].first && branch_[0].first->valid() &&
    7081        1998 :                branch_[1].first && branch_[1].first->valid() &&
    7082        3996 :                branch_[2].first && branch_[2].first->valid() ;
    7083             :          }
    7084             : 
    7085        1987 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7086             :          {
    7087        1987 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    7088        1987 :          }
    7089             : 
    7090        5497 :          std::size_t node_depth() const exprtk_override exprtk_final
    7091             :          {
    7092        5497 :             return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
    7093             :          }
    7094             : 
    7095             :       protected:
    7096             : 
    7097             :          operator_type operation_;
    7098             :          branch_t branch_[3];
    7099             :       };
    7100             : 
    7101             :       template <typename T>
    7102             :       class quaternary_node : public expression_node<T>
    7103             :       {
    7104             :       public:
    7105             : 
    7106             :          typedef expression_node<T>* expression_ptr;
    7107             :          typedef std::pair<expression_ptr,bool> branch_t;
    7108             : 
    7109         815 :          quaternary_node(const operator_type& opr,
    7110             :                          expression_ptr branch0,
    7111             :                          expression_ptr branch1,
    7112             :                          expression_ptr branch2,
    7113             :                          expression_ptr branch3)
    7114         815 :          : operation_(opr)
    7115             :          {
    7116         815 :             init_branches<4>(branch_, branch0, branch1, branch2, branch3);
    7117         815 :          }
    7118             : 
    7119           0 :          inline T value() const exprtk_override
    7120             :          {
    7121           0 :             return std::numeric_limits<T>::quiet_NaN();
    7122             :          }
    7123             : 
    7124        1630 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7125             :          {
    7126        1630 :             return expression_node<T>::e_quaternary;
    7127             :          }
    7128             : 
    7129         815 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7130             :          {
    7131         815 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    7132         815 :          }
    7133             : 
    7134        1630 :          std::size_t node_depth() const exprtk_override exprtk_final
    7135             :          {
    7136        1630 :             return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
    7137             :          }
    7138             : 
    7139           0 :          inline bool valid() const exprtk_override
    7140             :          {
    7141             :             return
    7142           0 :                branch_[0].first && branch_[0].first->valid() &&
    7143           0 :                branch_[1].first && branch_[1].first->valid() &&
    7144           0 :                branch_[2].first && branch_[2].first->valid() &&
    7145           0 :                branch_[3].first && branch_[3].first->valid() ;
    7146             :          }
    7147             : 
    7148             :       protected:
    7149             : 
    7150             :          operator_type operation_;
    7151             :          branch_t branch_[4];
    7152             :       };
    7153             : 
    7154             :       template <typename T>
    7155             :       class conditional_node exprtk_final : public expression_node<T>
    7156             :       {
    7157             :       public:
    7158             : 
    7159             :          typedef expression_node<T>* expression_ptr;
    7160             :          typedef std::pair<expression_ptr,bool> branch_t;
    7161             : 
    7162        2847 :          conditional_node(expression_ptr condition,
    7163             :                           expression_ptr consequent,
    7164             :                           expression_ptr alternative)
    7165        2847 :          {
    7166        2847 :             construct_branch_pair(condition_  , condition  );
    7167        2847 :             construct_branch_pair(consequent_ , consequent );
    7168        2847 :             construct_branch_pair(alternative_, alternative);
    7169        2847 :             assert(valid());
    7170        2847 :          }
    7171             : 
    7172    57799451 :          inline T value() const exprtk_override
    7173             :          {
    7174    57799451 :             if (is_true(condition_))
    7175    21746104 :                return consequent_.first->value();
    7176             :             else
    7177    36053347 :                return alternative_.first->value();
    7178             :          }
    7179             : 
    7180       54062 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7181             :          {
    7182       54062 :             return expression_node<T>::e_conditional;
    7183             :          }
    7184             : 
    7185        9662 :          inline bool valid() const exprtk_override
    7186             :          {
    7187             :             return
    7188        9662 :                condition_  .first && condition_  .first->valid() &&
    7189        9662 :                consequent_ .first && consequent_ .first->valid() &&
    7190       19324 :                alternative_.first && alternative_.first->valid() ;
    7191             :          }
    7192             : 
    7193        2847 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7194             :          {
    7195        2847 :             expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
    7196        2847 :             expression_node<T>::ndb_t::collect(consequent_  , node_delete_list);
    7197        2847 :             expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
    7198        2847 :          }
    7199             : 
    7200        6979 :          std::size_t node_depth() const exprtk_override
    7201             :          {
    7202             :             return expression_node<T>::ndb_t::compute_node_depth
    7203        6979 :                (condition_, consequent_, alternative_);
    7204             :          }
    7205             : 
    7206             :       private:
    7207             : 
    7208             :          branch_t condition_;
    7209             :          branch_t consequent_;
    7210             :          branch_t alternative_;
    7211             :       };
    7212             : 
    7213             :       template <typename T>
    7214             :       class cons_conditional_node exprtk_final : public expression_node<T>
    7215             :       {
    7216             :       public:
    7217             : 
    7218             :          // Consequent only conditional statement node
    7219             :          typedef expression_node<T>* expression_ptr;
    7220             :          typedef std::pair<expression_ptr,bool> branch_t;
    7221             : 
    7222        1031 :          cons_conditional_node(expression_ptr condition,
    7223             :                                expression_ptr consequent)
    7224        1031 :          {
    7225        1031 :             construct_branch_pair(condition_ , condition );
    7226        1031 :             construct_branch_pair(consequent_, consequent);
    7227        1031 :             assert(valid());
    7228        1031 :          }
    7229             : 
    7230    10006020 :          inline T value() const exprtk_override
    7231             :          {
    7232    10006020 :             if (is_true(condition_))
    7233      666067 :                return consequent_.first->value();
    7234             :             else
    7235     9339953 :                return std::numeric_limits<T>::quiet_NaN();
    7236             :          }
    7237             : 
    7238       14489 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7239             :          {
    7240       14489 :             return expression_node<T>::e_conditional;
    7241             :          }
    7242             : 
    7243        4738 :          inline bool valid() const exprtk_override
    7244             :          {
    7245             :             return
    7246        4738 :                condition_ .first && condition_ .first->valid() &&
    7247        9476 :                consequent_.first && consequent_.first->valid() ;
    7248             :          }
    7249             : 
    7250        1031 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7251             :          {
    7252        1031 :             expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
    7253        1031 :             expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
    7254        1031 :          }
    7255             : 
    7256        2261 :          std::size_t node_depth() const exprtk_override
    7257             :          {
    7258             :             return expression_node<T>::ndb_t::
    7259        2261 :                compute_node_depth(condition_, consequent_);
    7260             :          }
    7261             : 
    7262             :       private:
    7263             : 
    7264             :          branch_t condition_;
    7265             :          branch_t consequent_;
    7266             :       };
    7267             : 
    7268             :       #ifndef exprtk_disable_break_continue
    7269             :       template <typename T>
    7270             :       class break_exception
    7271             :       {
    7272             :       public:
    7273             : 
    7274      372198 :          explicit break_exception(const T& v)
    7275      372198 :          : value(v)
    7276      372198 :          {}
    7277             : 
    7278             :          T value;
    7279             :       };
    7280             : 
    7281             :       class continue_exception {};
    7282             : 
    7283             :       template <typename T>
    7284             :       class break_node exprtk_final : public expression_node<T>
    7285             :       {
    7286             :       public:
    7287             : 
    7288             :          typedef expression_node<T>* expression_ptr;
    7289             :          typedef std::pair<expression_ptr,bool> branch_t;
    7290             : 
    7291         483 :          explicit break_node(expression_ptr ret = expression_ptr(0))
    7292         483 :          {
    7293         483 :             construct_branch_pair(return_, ret);
    7294         483 :          }
    7295             : 
    7296      372198 :          inline T value() const exprtk_override
    7297             :          {
    7298      372198 :             const T result = return_.first ?
    7299        1738 :                              return_.first->value() :
    7300      370460 :                              std::numeric_limits<T>::quiet_NaN();
    7301             : 
    7302      372198 :             throw break_exception<T>(result);
    7303             : 
    7304             :             #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    7305             :             return std::numeric_limits<T>::quiet_NaN();
    7306             :             #endif
    7307             :          }
    7308             : 
    7309        3418 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7310             :          {
    7311        3418 :             return expression_node<T>::e_break;
    7312             :          }
    7313             : 
    7314         483 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7315             :          {
    7316         483 :             expression_node<T>::ndb_t::collect(return_, node_delete_list);
    7317         483 :          }
    7318             : 
    7319        1528 :          std::size_t node_depth() const exprtk_override
    7320             :          {
    7321        1528 :             return expression_node<T>::ndb_t::compute_node_depth(return_);
    7322             :          }
    7323             : 
    7324             :       private:
    7325             : 
    7326             :          branch_t return_;
    7327             :       };
    7328             : 
    7329             :       template <typename T>
    7330             :       class continue_node exprtk_final : public expression_node<T>
    7331             :       {
    7332             :       public:
    7333             : 
    7334        1480 :          inline T value() const exprtk_override
    7335             :          {
    7336        1480 :             throw continue_exception();
    7337             :             #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    7338             :             return std::numeric_limits<T>::quiet_NaN();
    7339             :             #endif
    7340             :          }
    7341             : 
    7342        2560 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7343             :          {
    7344        2560 :             return expression_node<T>::e_break;
    7345             :          }
    7346             :       };
    7347             :       #endif
    7348             : 
    7349             :       struct loop_runtime_checker
    7350             :       {
    7351           0 :          loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check,
    7352             :                               loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid)
    7353           0 :          : iteration_count_(0)
    7354           0 :          , loop_runtime_check_(loop_runtime_check)
    7355           0 :          , max_loop_iterations_(loop_runtime_check_->max_loop_iterations)
    7356           0 :          , loop_type_(lp_typ)
    7357             :          {
    7358           0 :             assert(loop_runtime_check_);
    7359           0 :          }
    7360             : 
    7361           0 :          inline void reset(const _uint64_t initial_value = 0) const
    7362             :          {
    7363           0 :             iteration_count_ = initial_value;
    7364           0 :          }
    7365             : 
    7366           0 :          inline bool check() const
    7367             :          {
    7368           0 :             assert(loop_runtime_check_);
    7369             : 
    7370           0 :             if (
    7371           0 :                  (++iteration_count_ <= max_loop_iterations_) &&
    7372           0 :                  loop_runtime_check_->check()
    7373             :                )
    7374             :             {
    7375           0 :                return true;
    7376             :             }
    7377             : 
    7378             :             loop_runtime_check::violation_context ctxt;
    7379           0 :             ctxt.loop      = loop_type_;
    7380           0 :             ctxt.violation = loop_runtime_check::e_iteration_count;
    7381             : 
    7382           0 :             loop_runtime_check_->handle_runtime_violation(ctxt);
    7383             : 
    7384           0 :             return false;
    7385             :          }
    7386             : 
    7387           0 :          bool valid() const
    7388             :          {
    7389           0 :             return 0 != loop_runtime_check_;
    7390             :          }
    7391             : 
    7392             :          mutable _uint64_t iteration_count_;
    7393             :          mutable loop_runtime_check_ptr loop_runtime_check_;
    7394             :          const details::_uint64_t& max_loop_iterations_;
    7395             :          loop_runtime_check::loop_types loop_type_;
    7396             :       };
    7397             : 
    7398             :       template <typename T>
    7399             :       class while_loop_node : public expression_node<T>
    7400             :       {
    7401             :       public:
    7402             : 
    7403             :          typedef expression_node<T>* expression_ptr;
    7404             :          typedef std::pair<expression_ptr,bool> branch_t;
    7405             : 
    7406          22 :          while_loop_node(expression_ptr condition,
    7407             :                          expression_ptr loop_body)
    7408          22 :          {
    7409          22 :             construct_branch_pair(condition_, condition);
    7410          22 :             construct_branch_pair(loop_body_, loop_body);
    7411          22 :             assert(valid());
    7412          22 :          }
    7413             : 
    7414         176 :          inline T value() const exprtk_override
    7415             :          {
    7416         176 :             T result = T(0);
    7417             : 
    7418       26728 :             while (is_true(condition_))
    7419             :             {
    7420       26552 :                result = loop_body_.first->value();
    7421             :             }
    7422             : 
    7423         176 :             return result;
    7424             :          }
    7425             : 
    7426         231 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7427             :          {
    7428         231 :             return expression_node<T>::e_while;
    7429             :          }
    7430             : 
    7431          75 :          inline bool valid() const exprtk_override
    7432             :          {
    7433             :             return
    7434          75 :                condition_.first && condition_.first->valid() &&
    7435         150 :                loop_body_.first && loop_body_.first->valid() ;
    7436             :          }
    7437             : 
    7438          22 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7439             :          {
    7440          22 :             expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
    7441          22 :             expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
    7442          22 :          }
    7443             : 
    7444          45 :          std::size_t node_depth() const exprtk_override
    7445             :          {
    7446          45 :             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
    7447             :          }
    7448             : 
    7449             :       protected:
    7450             : 
    7451             :          branch_t condition_;
    7452             :          branch_t loop_body_;
    7453             :       };
    7454             : 
    7455             :       template <typename T>
    7456             :       class while_loop_rtc_node exprtk_final
    7457             :                                 : public while_loop_node<T>
    7458             :                                 , public loop_runtime_checker
    7459             :       {
    7460             :       public:
    7461             : 
    7462             :          typedef while_loop_node<T>  parent_t;
    7463             :          typedef expression_node<T>* expression_ptr;
    7464             : 
    7465           0 :          while_loop_rtc_node(expression_ptr condition,
    7466             :                              expression_ptr loop_body,
    7467             :                              loop_runtime_check_ptr loop_rt_chk)
    7468             :          : parent_t(condition, loop_body)
    7469           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
    7470             :          {
    7471           0 :             assert(valid());
    7472           0 :          }
    7473             : 
    7474           0 :          inline T value() const exprtk_override
    7475             :          {
    7476             : 
    7477           0 :             T result = T(0);
    7478             : 
    7479           0 :             loop_runtime_checker::reset();
    7480             : 
    7481           0 :             while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7482             :             {
    7483           0 :                result = parent_t::loop_body_.first->value();
    7484             :             }
    7485             : 
    7486           0 :             return result;
    7487             :          }
    7488             : 
    7489             :          using parent_t::valid;
    7490             : 
    7491           0 :          bool valid() const exprtk_override exprtk_final
    7492             :          {
    7493           0 :             return parent_t::valid() &&
    7494           0 :                    loop_runtime_checker::valid();
    7495             :          }
    7496             :       };
    7497             : 
    7498             :       template <typename T>
    7499             :       class repeat_until_loop_node : public expression_node<T>
    7500             :       {
    7501             :       public:
    7502             : 
    7503             :          typedef expression_node<T>* expression_ptr;
    7504             :          typedef std::pair<expression_ptr,bool> branch_t;
    7505             : 
    7506           2 :          repeat_until_loop_node(expression_ptr condition,
    7507             :                                 expression_ptr loop_body)
    7508           2 :          {
    7509           2 :             construct_branch_pair(condition_, condition);
    7510           2 :             construct_branch_pair(loop_body_, loop_body);
    7511           2 :             assert(valid());
    7512           2 :          }
    7513             : 
    7514          30 :          inline T value() const exprtk_override
    7515             :          {
    7516          30 :             T result = T(0);
    7517             : 
    7518             :             do
    7519             :             {
    7520         465 :                result = loop_body_.first->value();
    7521             :             }
    7522         465 :             while (is_false(condition_.first));
    7523             : 
    7524          30 :             return result;
    7525             :          }
    7526             : 
    7527           9 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7528             :          {
    7529           9 :             return expression_node<T>::e_repeat;
    7530             :          }
    7531             : 
    7532           7 :          inline bool valid() const exprtk_override
    7533             :          {
    7534             :             return
    7535           7 :                condition_.first && condition_.first->valid() &&
    7536          14 :                loop_body_.first && loop_body_.first->valid() ;
    7537             :          }
    7538             : 
    7539           2 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7540             :          {
    7541           2 :             expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
    7542           2 :             expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
    7543           2 :          }
    7544             : 
    7545           4 :          std::size_t node_depth() const exprtk_override
    7546             :          {
    7547           4 :             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
    7548             :          }
    7549             : 
    7550             :       protected:
    7551             : 
    7552             :          branch_t condition_;
    7553             :          branch_t loop_body_;
    7554             :       };
    7555             : 
    7556             :       template <typename T>
    7557             :       class repeat_until_loop_rtc_node exprtk_final
    7558             :                                        : public repeat_until_loop_node<T>
    7559             :                                        , public loop_runtime_checker
    7560             :       {
    7561             :       public:
    7562             : 
    7563             :          typedef repeat_until_loop_node<T> parent_t;
    7564             :          typedef expression_node<T>*       expression_ptr;
    7565             : 
    7566           0 :          repeat_until_loop_rtc_node(expression_ptr condition,
    7567             :                                     expression_ptr loop_body,
    7568             :                                     loop_runtime_check_ptr loop_rt_chk)
    7569             :          : parent_t(condition, loop_body)
    7570           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
    7571             :          {
    7572           0 :             assert(valid());
    7573           0 :          }
    7574             : 
    7575           0 :          inline T value() const exprtk_override
    7576             :          {
    7577           0 :             T result = T(0);
    7578             : 
    7579           0 :             loop_runtime_checker::reset(1);
    7580             : 
    7581             :             do
    7582             :             {
    7583           0 :                result = parent_t::loop_body_.first->value();
    7584             :             }
    7585           0 :             while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
    7586             : 
    7587           0 :             return result;
    7588             :          }
    7589             : 
    7590             :          using parent_t::valid;
    7591             : 
    7592           0 :          inline bool valid() const exprtk_override exprtk_final
    7593             :          {
    7594           0 :             return parent_t::valid() &&
    7595           0 :                    loop_runtime_checker::valid();
    7596             :          }
    7597             :       };
    7598             : 
    7599             :       template <typename T>
    7600             :       class for_loop_node : public expression_node<T>
    7601             :       {
    7602             :       public:
    7603             : 
    7604             :          typedef expression_node<T>* expression_ptr;
    7605             :          typedef std::pair<expression_ptr,bool> branch_t;
    7606             : 
    7607        2723 :          for_loop_node(expression_ptr initialiser,
    7608             :                        expression_ptr condition,
    7609             :                        expression_ptr incrementor,
    7610             :                        expression_ptr loop_body)
    7611        2723 :          {
    7612        2723 :             construct_branch_pair(initialiser_, initialiser);
    7613        2723 :             construct_branch_pair(condition_  , condition  );
    7614        2723 :             construct_branch_pair(incrementor_, incrementor);
    7615        2723 :             construct_branch_pair(loop_body_  , loop_body  );
    7616        2723 :             assert(valid());
    7617        2723 :          }
    7618             : 
    7619        6776 :          inline T value() const exprtk_override
    7620             :          {
    7621        6776 :             T result = T(0);
    7622             : 
    7623        6776 :             if (initialiser_.first)
    7624        6776 :                initialiser_.first->value();
    7625             : 
    7626        6776 :             if (incrementor_.first)
    7627             :             {
    7628    93358890 :                while (is_true(condition_))
    7629             :                {
    7630    93352241 :                   result = loop_body_.first->value();
    7631    93352234 :                   incrementor_.first->value();
    7632             :                }
    7633             :             }
    7634             :             else
    7635             :             {
    7636        1020 :                while (is_true(condition_))
    7637             :                {
    7638         900 :                   result = loop_body_.first->value();
    7639             :                }
    7640             :             }
    7641             : 
    7642        6769 :             return result;
    7643             :          }
    7644             : 
    7645       39051 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7646             :          {
    7647       39051 :             return expression_node<T>::e_for;
    7648             :          }
    7649             : 
    7650        9045 :          inline bool valid() const exprtk_override
    7651             :          {
    7652        9045 :             return condition_.first && loop_body_.first;
    7653             :          }
    7654             : 
    7655        2723 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7656             :          {
    7657        2723 :             expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list);
    7658        2723 :             expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
    7659        2723 :             expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list);
    7660        2723 :             expression_node<T>::ndb_t::collect(loop_body_   , node_delete_list);
    7661        2723 :          }
    7662             : 
    7663        6774 :          std::size_t node_depth() const exprtk_override
    7664             :          {
    7665             :             return expression_node<T>::ndb_t::compute_node_depth
    7666        6774 :                (initialiser_, condition_, incrementor_, loop_body_);
    7667             :          }
    7668             : 
    7669             :       protected:
    7670             : 
    7671             :          branch_t initialiser_;
    7672             :          branch_t condition_  ;
    7673             :          branch_t incrementor_;
    7674             :          branch_t loop_body_  ;
    7675             :       };
    7676             : 
    7677             :       template <typename T>
    7678             :       class for_loop_rtc_node exprtk_final
    7679             :                               : public for_loop_node<T>
    7680             :                               , public loop_runtime_checker
    7681             :       {
    7682             :       public:
    7683             : 
    7684             :          typedef for_loop_node<T>    parent_t;
    7685             :          typedef expression_node<T>* expression_ptr;
    7686             : 
    7687           0 :          for_loop_rtc_node(expression_ptr initialiser,
    7688             :                            expression_ptr condition,
    7689             :                            expression_ptr incrementor,
    7690             :                            expression_ptr loop_body,
    7691             :                            loop_runtime_check_ptr loop_rt_chk)
    7692             :          : parent_t(initialiser, condition, incrementor, loop_body)
    7693           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
    7694             :          {
    7695           0 :             assert(valid());
    7696           0 :          }
    7697             : 
    7698           0 :          inline T value() const exprtk_override
    7699             :          {
    7700           0 :             T result = T(0);
    7701             : 
    7702           0 :             loop_runtime_checker::reset();
    7703             : 
    7704           0 :             if (parent_t::initialiser_.first)
    7705           0 :                parent_t::initialiser_.first->value();
    7706             : 
    7707           0 :             if (parent_t::incrementor_.first)
    7708             :             {
    7709           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7710             :                {
    7711           0 :                   result = parent_t::loop_body_.first->value();
    7712           0 :                   parent_t::incrementor_.first->value();
    7713             :                }
    7714             :             }
    7715             :             else
    7716             :             {
    7717           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7718             :                {
    7719           0 :                   result = parent_t::loop_body_.first->value();
    7720             :                }
    7721             :             }
    7722             : 
    7723           0 :             return result;
    7724             :          }
    7725             : 
    7726             :          using parent_t::valid;
    7727             : 
    7728           0 :          inline bool valid() const exprtk_override exprtk_final
    7729             :          {
    7730           0 :             return parent_t::valid() &&
    7731           0 :                    loop_runtime_checker::valid();
    7732             :          }
    7733             :       };
    7734             : 
    7735             :       #ifndef exprtk_disable_break_continue
    7736             :       template <typename T>
    7737             :       class while_loop_bc_node : public while_loop_node<T>
    7738             :       {
    7739             :       public:
    7740             : 
    7741             :          typedef while_loop_node<T>  parent_t;
    7742             :          typedef expression_node<T>* expression_ptr;
    7743             : 
    7744          10 :          while_loop_bc_node(expression_ptr condition,
    7745             :                             expression_ptr loop_body)
    7746          10 :          : parent_t(condition, loop_body)
    7747             :          {
    7748          10 :             assert(parent_t::valid());
    7749          10 :          }
    7750             : 
    7751         100 :          inline T value() const exprtk_override
    7752             :          {
    7753         100 :             T result = T(0);
    7754             : 
    7755         650 :             while (is_true(parent_t::condition_))
    7756             :             {
    7757             :                try
    7758             :                {
    7759         650 :                   result = parent_t::loop_body_.first->value();
    7760             :                }
    7761         100 :                catch(const break_exception<T>& e)
    7762             :                {
    7763         100 :                   return e.value;
    7764             :                }
    7765           0 :                catch(const continue_exception&)
    7766             :                {}
    7767             :             }
    7768             : 
    7769           0 :             return result;
    7770             :          }
    7771             :       };
    7772             : 
    7773             :       template <typename T>
    7774             :       class while_loop_bc_rtc_node exprtk_final
    7775             :                                    : public while_loop_bc_node<T>
    7776             :                                    , public loop_runtime_checker
    7777             :       {
    7778             :       public:
    7779             : 
    7780             :          typedef while_loop_bc_node<T> parent_t;
    7781             :          typedef expression_node<T>*   expression_ptr;
    7782             : 
    7783           0 :          while_loop_bc_rtc_node(expression_ptr condition,
    7784             :                                 expression_ptr loop_body,
    7785             :                                 loop_runtime_check_ptr loop_rt_chk)
    7786             :          : parent_t(condition, loop_body)
    7787           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
    7788             :          {
    7789           0 :             assert(valid());
    7790           0 :          }
    7791             : 
    7792           0 :          inline T value() const exprtk_override
    7793             :          {
    7794           0 :             T result = T(0);
    7795             : 
    7796           0 :             loop_runtime_checker::reset();
    7797             : 
    7798           0 :             while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7799             :             {
    7800             :                try
    7801             :                {
    7802           0 :                   result = parent_t::loop_body_.first->value();
    7803             :                }
    7804           0 :                catch(const break_exception<T>& e)
    7805             :                {
    7806           0 :                   return e.value;
    7807             :                }
    7808           0 :                catch(const continue_exception&)
    7809             :                {}
    7810             :             }
    7811             : 
    7812           0 :             return result;
    7813             :          }
    7814             : 
    7815             :          using parent_t::valid;
    7816             : 
    7817           0 :          inline bool valid() const exprtk_override exprtk_final
    7818             :          {
    7819           0 :             return parent_t::valid() &&
    7820           0 :                    loop_runtime_checker::valid();
    7821             :          }
    7822             :       };
    7823             : 
    7824             :       template <typename T>
    7825             :       class repeat_until_loop_bc_node : public repeat_until_loop_node<T>
    7826             :       {
    7827             :       public:
    7828             : 
    7829             :          typedef repeat_until_loop_node<T> parent_t;
    7830             :          typedef expression_node<T>*       expression_ptr;
    7831             : 
    7832           1 :          repeat_until_loop_bc_node(expression_ptr condition,
    7833             :                                    expression_ptr loop_body)
    7834           1 :          : parent_t(condition, loop_body)
    7835             :          {
    7836           1 :             assert(parent_t::valid());
    7837           1 :          }
    7838             : 
    7839          98 :          inline T value() const exprtk_override
    7840             :          {
    7841          98 :             T result = T(0);
    7842             : 
    7843             :             do
    7844             :             {
    7845             :                try
    7846             :                {
    7847         548 :                   result = parent_t::loop_body_.first->value();
    7848             :                }
    7849          98 :                catch(const break_exception<T>& e)
    7850             :                {
    7851          98 :                   return e.value;
    7852             :                }
    7853           0 :                catch(const continue_exception&)
    7854             :                {}
    7855             :             }
    7856         450 :             while (is_false(parent_t::condition_.first));
    7857             : 
    7858           0 :             return result;
    7859             :          }
    7860             :       };
    7861             : 
    7862             :       template <typename T>
    7863             :       class repeat_until_loop_bc_rtc_node exprtk_final
    7864             :                                           : public repeat_until_loop_bc_node<T>
    7865             :                                           , public loop_runtime_checker
    7866             :       {
    7867             :       public:
    7868             : 
    7869             :          typedef repeat_until_loop_bc_node<T> parent_t;
    7870             :          typedef expression_node<T>*          expression_ptr;
    7871             : 
    7872           0 :          repeat_until_loop_bc_rtc_node(expression_ptr condition,
    7873             :                                        expression_ptr loop_body,
    7874             :                                        loop_runtime_check_ptr loop_rt_chk)
    7875             :          : parent_t(condition, loop_body)
    7876           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
    7877             :          {
    7878           0 :             assert(valid());
    7879           0 :          }
    7880             : 
    7881           0 :          inline T value() const exprtk_override
    7882             :          {
    7883           0 :             T result = T(0);
    7884             : 
    7885           0 :             loop_runtime_checker::reset();
    7886             : 
    7887             :             do
    7888             :             {
    7889             :                try
    7890             :                {
    7891           0 :                   result = parent_t::loop_body_.first->value();
    7892             :                }
    7893           0 :                catch(const break_exception<T>& e)
    7894             :                {
    7895           0 :                   return e.value;
    7896             :                }
    7897           0 :                catch(const continue_exception&)
    7898             :                {}
    7899             :             }
    7900           0 :             while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
    7901             : 
    7902           0 :             return result;
    7903             :          }
    7904             : 
    7905             :          using parent_t::valid;
    7906             : 
    7907           0 :          inline bool valid() const exprtk_override exprtk_final
    7908             :          {
    7909           0 :             return parent_t::valid() &&
    7910           0 :                    loop_runtime_checker::valid();
    7911             :          }
    7912             :       };
    7913             : 
    7914             :       template <typename T>
    7915             :       class for_loop_bc_node : public for_loop_node<T>
    7916             :       {
    7917             :       public:
    7918             : 
    7919             :          typedef for_loop_node<T>    parent_t;
    7920             :          typedef expression_node<T>* expression_ptr;
    7921             : 
    7922         612 :          for_loop_bc_node(expression_ptr initialiser,
    7923             :                           expression_ptr condition,
    7924             :                           expression_ptr incrementor,
    7925             :                           expression_ptr loop_body)
    7926         612 :          : parent_t(initialiser, condition, incrementor, loop_body)
    7927             :          {
    7928         612 :             assert(parent_t::valid());
    7929         612 :          }
    7930             : 
    7931      486072 :          inline T value() const exprtk_override
    7932             :          {
    7933      486072 :             T result = T(0);
    7934             : 
    7935      486072 :             if (parent_t::initialiser_.first)
    7936      486072 :                parent_t::initialiser_.first->value();
    7937             : 
    7938      486072 :             if (parent_t::incrementor_.first)
    7939             :             {
    7940     5131214 :                while (is_true(parent_t::condition_))
    7941             :                {
    7942             :                   try
    7943             :                   {
    7944     5017142 :                      result = parent_t::loop_body_.first->value();
    7945             :                   }
    7946      373480 :                   catch(const break_exception<T>& e)
    7947             :                   {
    7948      372000 :                      return e.value;
    7949             :                   }
    7950        1480 :                   catch(const continue_exception&)
    7951             :                   {}
    7952             : 
    7953     4645142 :                   parent_t::incrementor_.first->value();
    7954             :                }
    7955             :             }
    7956             :             else
    7957             :             {
    7958           0 :                while (is_true(parent_t::condition_))
    7959             :                {
    7960             :                   try
    7961             :                   {
    7962           0 :                      result = parent_t::loop_body_.first->value();
    7963             :                   }
    7964           0 :                   catch(const break_exception<T>& e)
    7965             :                   {
    7966           0 :                      return e.value;
    7967             :                   }
    7968           0 :                   catch(const continue_exception&)
    7969             :                   {}
    7970             :                }
    7971             :             }
    7972             : 
    7973      114072 :             return result;
    7974             :          }
    7975             :       };
    7976             : 
    7977             :       template <typename T>
    7978             :       class for_loop_bc_rtc_node exprtk_final
    7979             :                                  : public for_loop_bc_node<T>
    7980             :                                  , public loop_runtime_checker
    7981             :       {
    7982             :       public:
    7983             : 
    7984             :          typedef for_loop_bc_node<T> parent_t;
    7985             :          typedef expression_node<T>* expression_ptr;
    7986             : 
    7987           0 :          for_loop_bc_rtc_node(expression_ptr initialiser,
    7988             :                               expression_ptr condition,
    7989             :                               expression_ptr incrementor,
    7990             :                               expression_ptr loop_body,
    7991             :                               loop_runtime_check_ptr loop_rt_chk)
    7992             :          : parent_t(initialiser, condition, incrementor, loop_body)
    7993           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
    7994             :          {
    7995           0 :             assert(valid());
    7996           0 :          }
    7997             : 
    7998           0 :          inline T value() const exprtk_override
    7999             :          {
    8000           0 :             T result = T(0);
    8001             : 
    8002           0 :             loop_runtime_checker::reset();
    8003             : 
    8004           0 :             if (parent_t::initialiser_.first)
    8005           0 :                parent_t::initialiser_.first->value();
    8006             : 
    8007           0 :             if (parent_t::incrementor_.first)
    8008             :             {
    8009           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    8010             :                {
    8011             :                   try
    8012             :                   {
    8013           0 :                      result = parent_t::loop_body_.first->value();
    8014             :                   }
    8015           0 :                   catch(const break_exception<T>& e)
    8016             :                   {
    8017           0 :                      return e.value;
    8018             :                   }
    8019           0 :                   catch(const continue_exception&)
    8020             :                   {}
    8021             : 
    8022           0 :                   parent_t::incrementor_.first->value();
    8023             :                }
    8024             :             }
    8025             :             else
    8026             :             {
    8027           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    8028             :                {
    8029             :                   try
    8030             :                   {
    8031           0 :                      result = parent_t::loop_body_.first->value();
    8032             :                   }
    8033           0 :                   catch(const break_exception<T>& e)
    8034             :                   {
    8035           0 :                      return e.value;
    8036             :                   }
    8037           0 :                   catch(const continue_exception&)
    8038             :                   {}
    8039             :                }
    8040             :             }
    8041             : 
    8042           0 :             return result;
    8043             :          }
    8044             : 
    8045             :          using parent_t::valid;
    8046             : 
    8047           0 :          inline bool valid() const exprtk_override exprtk_final
    8048             :          {
    8049           0 :             return parent_t::valid() &&
    8050           0 :                    loop_runtime_checker::valid();
    8051             :          }
    8052             :       };
    8053             :       #endif
    8054             : 
    8055             :       template <typename T>
    8056             :       class switch_node : public expression_node<T>
    8057             :       {
    8058             :       public:
    8059             : 
    8060             :          typedef expression_node<T>* expression_ptr;
    8061             :          typedef std::pair<expression_ptr,bool> branch_t;
    8062             : 
    8063             :          template <typename Allocator,
    8064             :                    template <typename, typename> class Sequence>
    8065        1005 :          explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
    8066        1005 :          {
    8067        1005 :             if (1 != (arg_list.size() & 1))
    8068           0 :                return;
    8069             : 
    8070        1005 :             arg_list_.resize(arg_list.size());
    8071             : 
    8072        4560 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
    8073             :             {
    8074        3555 :                if (arg_list[i] && arg_list[i]->valid())
    8075             :                {
    8076        3555 :                   construct_branch_pair(arg_list_[i], arg_list[i]);
    8077             :                }
    8078             :                else
    8079             :                {
    8080           0 :                   arg_list_.clear();
    8081           0 :                   return;
    8082             :                }
    8083             :             }
    8084             : 
    8085        1005 :             assert(valid());
    8086           0 :          }
    8087             : 
    8088           0 :          inline T value() const exprtk_override
    8089             :          {
    8090           0 :             const std::size_t upper_bound = (arg_list_.size() - 1);
    8091             : 
    8092           0 :             for (std::size_t i = 0; i < upper_bound; i += 2)
    8093             :             {
    8094           0 :                expression_ptr condition  = arg_list_[i    ].first;
    8095           0 :                expression_ptr consequent = arg_list_[i + 1].first;
    8096             : 
    8097           0 :                if (is_true(condition))
    8098             :                {
    8099           0 :                   return consequent->value();
    8100             :                }
    8101             :             }
    8102             : 
    8103           0 :             return arg_list_[upper_bound].first->value();
    8104             :          }
    8105             : 
    8106        4802 :          inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
    8107             :          {
    8108        4802 :             return expression_node<T>::e_switch;
    8109             :          }
    8110             : 
    8111        1282 :          inline bool valid() const exprtk_override
    8112             :          {
    8113        1282 :             return !arg_list_.empty();
    8114             :          }
    8115             : 
    8116        1005 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8117             :          {
    8118        1005 :             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
    8119        1005 :          }
    8120             : 
    8121        2020 :          std::size_t node_depth() const exprtk_override exprtk_final
    8122             :          {
    8123        2020 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
    8124             :          }
    8125             : 
    8126             :       protected:
    8127             : 
    8128             :          std::vector<branch_t> arg_list_;
    8129             :       };
    8130             : 
    8131             :       template <typename T, typename Switch_N>
    8132             :       class switch_n_node exprtk_final : public switch_node<T>
    8133             :       {
    8134             :       public:
    8135             : 
    8136             :          typedef expression_node<T>* expression_ptr;
    8137             : 
    8138             :          template <typename Allocator,
    8139             :                    template <typename, typename> class Sequence>
    8140        1005 :          explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
    8141        1005 :          : switch_node<T>(arg_list)
    8142        1005 :          {}
    8143             : 
    8144    11459417 :          inline T value() const exprtk_override
    8145             :          {
    8146    11459417 :             return Switch_N::process(switch_node<T>::arg_list_);
    8147             :          }
    8148             :       };
    8149             : 
    8150             :       template <typename T>
    8151             :       class multi_switch_node exprtk_final : public expression_node<T>
    8152             :       {
    8153             :       public:
    8154             : 
    8155             :          typedef expression_node<T>* expression_ptr;
    8156             :          typedef std::pair<expression_ptr,bool> branch_t;
    8157             : 
    8158             :          template <typename Allocator,
    8159             :                    template <typename, typename> class Sequence>
    8160         180 :          explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
    8161         180 :          {
    8162         180 :             if (0 != (arg_list.size() & 1))
    8163           0 :                return;
    8164             : 
    8165         180 :             arg_list_.resize(arg_list.size());
    8166             : 
    8167         900 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
    8168             :             {
    8169         720 :                if (arg_list[i] && arg_list[i]->valid())
    8170             :                {
    8171         720 :                   construct_branch_pair(arg_list_[i], arg_list[i]);
    8172             :                }
    8173             :                else
    8174             :                {
    8175           0 :                   arg_list_.clear();
    8176           0 :                   return;
    8177             :                }
    8178             :             }
    8179             : 
    8180         180 :             assert(valid());
    8181           0 :          }
    8182             : 
    8183         180 :          inline T value() const exprtk_override
    8184             :          {
    8185         180 :             const std::size_t upper_bound = (arg_list_.size() - 1);
    8186             : 
    8187         180 :             T result = T(0);
    8188             : 
    8189         540 :             for (std::size_t i = 0; i < upper_bound; i += 2)
    8190             :             {
    8191         360 :                expression_ptr condition  = arg_list_[i    ].first;
    8192         360 :                expression_ptr consequent = arg_list_[i + 1].first;
    8193             : 
    8194         360 :                if (is_true(condition))
    8195             :                {
    8196         120 :                   result = consequent->value();
    8197             :                }
    8198             :             }
    8199             : 
    8200         180 :             return result;
    8201             :          }
    8202             : 
    8203         900 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8204             :          {
    8205         900 :             return expression_node<T>::e_mswitch;
    8206             :          }
    8207             : 
    8208         180 :          inline bool valid() const exprtk_override
    8209             :          {
    8210         180 :             return !arg_list_.empty() && (0 == (arg_list_.size() % 2));
    8211             :          }
    8212             : 
    8213         180 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8214             :          {
    8215         180 :             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
    8216         180 :          }
    8217             : 
    8218         360 :          std::size_t node_depth() const exprtk_override exprtk_final
    8219             :          {
    8220         360 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
    8221             :          }
    8222             : 
    8223             :       private:
    8224             : 
    8225             :          std::vector<branch_t> arg_list_;
    8226             :       };
    8227             : 
    8228             :       template <typename T>
    8229             :       class ivariable
    8230             :       {
    8231             :       public:
    8232             : 
    8233      506744 :          virtual ~ivariable()
    8234      506744 :          {}
    8235             : 
    8236             :          virtual T& ref() = 0;
    8237             :          virtual const T& ref() const = 0;
    8238             :       };
    8239             : 
    8240             :       template <typename T>
    8241             :       class variable_node exprtk_final
    8242             :                           : public expression_node<T>
    8243             :                           , public ivariable      <T>
    8244             :       {
    8245             :       public:
    8246             : 
    8247             :          static T null_value;
    8248             : 
    8249             :          explicit variable_node()
    8250             :          : value_(&null_value)
    8251             :          {}
    8252             : 
    8253      499841 :          explicit variable_node(T& v)
    8254      499841 :          : value_(&v)
    8255      499841 :          {}
    8256             : 
    8257             :          inline bool operator <(const variable_node<T>& v) const
    8258             :          {
    8259             :             return this < (&v);
    8260             :          }
    8261             : 
    8262   127759453 :          inline T value() const exprtk_override
    8263             :          {
    8264   127759453 :             return (*value_);
    8265             :          }
    8266             : 
    8267   199245326 :          inline T& ref() exprtk_override
    8268             :          {
    8269   199245326 :             return (*value_);
    8270             :          }
    8271             : 
    8272         960 :          inline const T& ref() const exprtk_override
    8273             :          {
    8274         960 :             return (*value_);
    8275             :          }
    8276             : 
    8277    29015411 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8278             :          {
    8279    29015411 :             return expression_node<T>::e_variable;
    8280             :          }
    8281             : 
    8282             :       private:
    8283             : 
    8284             :          T* value_;
    8285             :       };
    8286             : 
    8287             :       template <typename T>
    8288             :       T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
    8289             : 
    8290             :       template <typename T>
    8291             :       struct range_pack
    8292             :       {
    8293             :          typedef expression_node<T>*           expression_node_ptr;
    8294             :          typedef std::pair<std::size_t,std::size_t> cached_range_t;
    8295             : 
    8296      230560 :          range_pack()
    8297      230560 :          : n0_e (std::make_pair(false,expression_node_ptr(0)))
    8298      230560 :          , n1_e (std::make_pair(false,expression_node_ptr(0)))
    8299      230560 :          , n0_c (std::make_pair(false,0))
    8300      230560 :          , n1_c (std::make_pair(false,0))
    8301      230560 :          , cache(std::make_pair(0,0))
    8302      230560 :          {}
    8303             : 
    8304       78072 :          void clear()
    8305             :          {
    8306       78072 :             n0_e  = std::make_pair(false,expression_node_ptr(0));
    8307       78072 :             n1_e  = std::make_pair(false,expression_node_ptr(0));
    8308       78072 :             n0_c  = std::make_pair(false,0);
    8309       78072 :             n1_c  = std::make_pair(false,0);
    8310       78072 :             cache = std::make_pair(0,0);
    8311       78072 :          }
    8312             : 
    8313       46016 :          void free()
    8314             :          {
    8315       46016 :             if (n0_e.first && n0_e.second)
    8316             :             {
    8317        5206 :                n0_e.first = false;
    8318             : 
    8319        5206 :                if (
    8320        6509 :                     !is_variable_node(n0_e.second) &&
    8321        1303 :                     !is_string_node  (n0_e.second)
    8322             :                   )
    8323             :                {
    8324        1303 :                   destroy_node(n0_e.second);
    8325             :                }
    8326             :             }
    8327             : 
    8328       46016 :             if (n1_e.first && n1_e.second)
    8329             :             {
    8330        7056 :                n1_e.first = false;
    8331             : 
    8332        7056 :                if (
    8333       12109 :                     !is_variable_node(n1_e.second) &&
    8334        5053 :                     !is_string_node  (n1_e.second)
    8335             :                   )
    8336             :                {
    8337        5053 :                   destroy_node(n1_e.second);
    8338             :                }
    8339             :             }
    8340       46016 :          }
    8341             : 
    8342       32310 :          bool const_range() const
    8343             :          {
    8344       54312 :            return ( n0_c.first &&  n1_c.first) &&
    8345       54312 :                   (!n0_e.first && !n1_e.first);
    8346             :          }
    8347             : 
    8348             :          bool var_range() const
    8349             :          {
    8350             :            return ( n0_e.first &&  n1_e.first) &&
    8351             :                   (!n0_c.first && !n1_c.first);
    8352             :          }
    8353             : 
    8354       99616 :          bool operator() (std::size_t& r0, std::size_t& r1,
    8355             :                           const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
    8356             :          {
    8357       99616 :             if (n0_c.first)
    8358       94416 :                r0 = n0_c.second;
    8359        5200 :             else if (n0_e.first)
    8360             :             {
    8361        5200 :                r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value()));
    8362             :             }
    8363             :             else
    8364           0 :                return false;
    8365             : 
    8366       99616 :             if (n1_c.first)
    8367       92566 :                r1 = n1_c.second;
    8368        7050 :             else if (n1_e.first)
    8369             :             {
    8370        7050 :                r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value()));
    8371             :             }
    8372             :             else
    8373           0 :                return false;
    8374             : 
    8375       99616 :             if (
    8376      177484 :                  (std::numeric_limits<std::size_t>::max() != size) &&
    8377       77868 :                  (std::numeric_limits<std::size_t>::max() == r1  )
    8378             :                )
    8379             :             {
    8380        9665 :                r1 = size;
    8381             :             }
    8382             : 
    8383       99616 :             cache.first  = r0;
    8384       99616 :             cache.second = r1;
    8385             : 
    8386             :             #ifndef exprtk_enable_range_runtime_checks
    8387       99616 :             return (r0 <= r1);
    8388             :             #else
    8389             :             return range_runtime_check(r0, r1, size);
    8390             :             #endif
    8391             :          }
    8392             : 
    8393           0 :          inline std::size_t const_size() const
    8394             :          {
    8395           0 :             return (n1_c.second - n0_c.second);
    8396             :          }
    8397             : 
    8398        3250 :          inline std::size_t cache_size() const
    8399             :          {
    8400        3250 :             return (cache.second - cache.first);
    8401             :          }
    8402             : 
    8403             :          std::pair<bool,expression_node_ptr> n0_e;
    8404             :          std::pair<bool,expression_node_ptr> n1_e;
    8405             :          std::pair<bool,std::size_t        > n0_c;
    8406             :          std::pair<bool,std::size_t        > n1_c;
    8407             :          mutable cached_range_t             cache;
    8408             : 
    8409             :          #ifdef exprtk_enable_range_runtime_checks
    8410             :          bool range_runtime_check(const std::size_t r0,
    8411             :                                   const std::size_t r1,
    8412             :                                   const std::size_t size) const
    8413             :          {
    8414             :             if (r0 > size)
    8415             :             {
    8416             :                throw std::runtime_error("range error: (r0 < 0) || (r0 > size)");
    8417             :                #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    8418             :                return false;
    8419             :                #endif
    8420             :             }
    8421             : 
    8422             :             if (r1 > size)
    8423             :             {
    8424             :                throw std::runtime_error("range error: (r1 < 0) || (r1 > size)");
    8425             :                #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    8426             :                return false;
    8427             :                #endif
    8428             :             }
    8429             : 
    8430             :             return (r0 <= r1);
    8431             :          }
    8432             :          #endif
    8433             :       };
    8434             : 
    8435             :       template <typename T>
    8436             :       class string_base_node;
    8437             : 
    8438             :       template <typename T>
    8439             :       struct range_data_type
    8440             :       {
    8441             :          typedef range_pack<T> range_t;
    8442             :          typedef string_base_node<T>* strbase_ptr_t;
    8443             : 
    8444        3724 :          range_data_type()
    8445        3724 :          : range(0)
    8446        3724 :          , data (0)
    8447        3724 :          , size (0)
    8448        3724 :          , type_size(0)
    8449        3724 :          , str_node (0)
    8450        3724 :          {}
    8451             : 
    8452             :          range_t*      range;
    8453             :          void*         data;
    8454             :          std::size_t   size;
    8455             :          std::size_t   type_size;
    8456             :          strbase_ptr_t str_node;
    8457             :       };
    8458             : 
    8459             :       template <typename T> class vector_node;
    8460             : 
    8461             :       template <typename T>
    8462             :       class vector_interface
    8463             :       {
    8464             :       public:
    8465             : 
    8466             :          typedef vector_node<T>*   vector_node_ptr;
    8467             :          typedef vec_data_store<T> vds_t;
    8468             : 
    8469      100185 :          virtual ~vector_interface()
    8470      100185 :          {}
    8471             : 
    8472             :          virtual std::size_t size     () const = 0;
    8473             : 
    8474             :          virtual std::size_t base_size() const = 0;
    8475             : 
    8476             :          virtual vector_node_ptr vec  () const = 0;
    8477             : 
    8478             :          virtual vector_node_ptr vec  ()       = 0;
    8479             : 
    8480             :          virtual       vds_t& vds     ()       = 0;
    8481             : 
    8482             :          virtual const vds_t& vds     () const = 0;
    8483             : 
    8484         822 :          virtual bool side_effect     () const { return false; }
    8485             :       };
    8486             : 
    8487             :       template <typename T>
    8488             :       class vector_node exprtk_final
    8489             :                         : public expression_node <T>
    8490             :                         , public vector_interface<T>
    8491             :       {
    8492             :       public:
    8493             : 
    8494             :          typedef expression_node<T>* expression_ptr;
    8495             :          typedef vector_holder<T>    vector_holder_t;
    8496             :          typedef vector_node<T>*     vector_node_ptr;
    8497             :          typedef vec_data_store<T>   vds_t;
    8498             : 
    8499       49912 :          explicit vector_node(vector_holder_t* vh)
    8500       49912 :          : vector_holder_(vh)
    8501       49912 :          , vds_((*vector_holder_).size(),(*vector_holder_)[0])
    8502             :          {
    8503       49912 :             vector_holder_->set_ref(&vds_.ref());
    8504       49912 :          }
    8505             : 
    8506       22339 :          vector_node(const vds_t& vds, vector_holder_t* vh)
    8507       22339 :          : vector_holder_(vh)
    8508       22339 :          , vds_(vds)
    8509       22339 :          {}
    8510             : 
    8511      144502 :         ~vector_node()
    8512             :          {
    8513       72251 :             assert(valid());
    8514       72251 :             vector_holder_->remove_ref(&vds_.ref());
    8515      216753 :          }
    8516             : 
    8517    32899074 :          inline T value() const exprtk_override
    8518             :          {
    8519    32899074 :             return vds().data()[0];
    8520             :          }
    8521             : 
    8522           0 :          vector_node_ptr vec() const exprtk_override
    8523             :          {
    8524           0 :             return const_cast<vector_node_ptr>(this);
    8525             :          }
    8526             : 
    8527        5722 :          vector_node_ptr vec() exprtk_override
    8528             :          {
    8529        5722 :             return this;
    8530             :          }
    8531             : 
    8532      461205 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8533             :          {
    8534      461205 :             return expression_node<T>::e_vector;
    8535             :          }
    8536             : 
    8537      197849 :          inline bool valid() const exprtk_override
    8538             :          {
    8539      197849 :             return vector_holder_;
    8540             :          }
    8541             : 
    8542       34991 :          std::size_t size() const exprtk_override
    8543             :          {
    8544       34991 :             return vec_holder().size();
    8545             :          }
    8546             : 
    8547        4647 :          std::size_t base_size() const exprtk_override
    8548             :          {
    8549        4647 :             return vec_holder().base_size();
    8550             :          }
    8551             : 
    8552       60520 :          vds_t& vds() exprtk_override
    8553             :          {
    8554       60520 :             return vds_;
    8555             :          }
    8556             : 
    8557    32899074 :          const vds_t& vds() const exprtk_override
    8558             :          {
    8559    32899074 :             return vds_;
    8560             :          }
    8561             : 
    8562      275121 :          inline vector_holder_t& vec_holder()
    8563             :          {
    8564      275121 :             return (*vector_holder_);
    8565             :          }
    8566             : 
    8567       39638 :          inline vector_holder_t& vec_holder() const
    8568             :          {
    8569       39638 :             return (*vector_holder_);
    8570             :          }
    8571             : 
    8572             :       private:
    8573             : 
    8574             :          vector_holder_t* vector_holder_;
    8575             :          vds_t                      vds_;
    8576             :       };
    8577             : 
    8578             :       template <typename T>
    8579             :       class vector_size_node exprtk_final
    8580             :                         : public expression_node <T>
    8581             :       {
    8582             :       public:
    8583             : 
    8584             :          typedef expression_node<T>* expression_ptr;
    8585             :          typedef vector_holder<T>    vector_holder_t;
    8586             : 
    8587         188 :          explicit vector_size_node(vector_holder_t* vh)
    8588         188 :          : vector_holder_(vh)
    8589         188 :          {}
    8590             : 
    8591         376 :         ~vector_size_node()
    8592             :          {
    8593         188 :             assert(valid());
    8594         564 :          }
    8595             : 
    8596        1022 :          inline T value() const exprtk_override
    8597             :          {
    8598        1022 :             assert(vector_holder_);
    8599        1022 :             return static_cast<T>(vector_holder_->size());
    8600             :          }
    8601             : 
    8602        6781 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8603             :          {
    8604        6781 :             return expression_node<T>::e_vecsize;
    8605             :          }
    8606             : 
    8607         807 :          inline bool valid() const exprtk_override
    8608             :          {
    8609         807 :             return vector_holder_ && vector_holder_->size();
    8610             :          }
    8611             : 
    8612           0 :          inline vector_holder_t* vec_holder()
    8613             :          {
    8614           0 :             return vector_holder_;
    8615             :          }
    8616             : 
    8617             :       private:
    8618             : 
    8619             :          vector_holder_t* vector_holder_;
    8620             :       };
    8621             : 
    8622             :       template <typename T>
    8623             :       class vector_elem_node exprtk_final
    8624             :                              : public expression_node<T>
    8625             :                              , public ivariable      <T>
    8626             :       {
    8627             :       public:
    8628             : 
    8629             :          typedef expression_node<T>*            expression_ptr;
    8630             :          typedef vector_holder<T>               vector_holder_t;
    8631             :          typedef vector_holder_t*               vector_holder_ptr;
    8632             :          typedef std::pair<expression_ptr,bool> branch_t;
    8633             : 
    8634        3711 :          vector_elem_node(expression_ptr vec_node,
    8635             :                           expression_ptr index,
    8636             :                           vector_holder_ptr vec_holder)
    8637        3711 :          : vector_holder_(vec_holder)
    8638        3711 :          , vector_base_((*vec_holder)[0])
    8639             :          {
    8640        3711 :             construct_branch_pair(vector_node_, vec_node);
    8641        3711 :             construct_branch_pair(index_      , index   );
    8642        3711 :             assert(valid());
    8643        3711 :          }
    8644             : 
    8645    10008123 :          inline T value() const exprtk_override
    8646             :          {
    8647    10008123 :             return *access_vector();
    8648             :          }
    8649             : 
    8650    22853974 :          inline T& ref() exprtk_override
    8651             :          {
    8652    22853974 :             return *access_vector();
    8653             :          }
    8654             : 
    8655           0 :          inline const T& ref() const exprtk_override
    8656             :          {
    8657           0 :             return *access_vector();
    8658             :          }
    8659             : 
    8660       77355 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8661             :          {
    8662       77355 :             return expression_node<T>::e_vecelem;
    8663             :          }
    8664             : 
    8665       18277 :          inline bool valid() const exprtk_override
    8666             :          {
    8667             :             return
    8668       36554 :                vector_holder_        &&
    8669       18277 :                index_.first          &&
    8670       18277 :                vector_node_.first    &&
    8671       54831 :                index_.first->valid() &&
    8672       36554 :                vector_node_.first->valid();
    8673             :          }
    8674             : 
    8675           0 :          inline vector_holder_t& vec_holder()
    8676             :          {
    8677           0 :             return (*vector_holder_);
    8678             :          }
    8679             : 
    8680        3711 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8681             :          {
    8682        3711 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8683        3711 :             expression_node<T>::ndb_t::collect(index_      , node_delete_list);
    8684        3711 :          }
    8685             : 
    8686        8226 :          std::size_t node_depth() const exprtk_override
    8687             :          {
    8688             :             return expression_node<T>::ndb_t::compute_node_depth
    8689        8226 :                (vector_node_, index_);
    8690             :          }
    8691             : 
    8692             :       private:
    8693             : 
    8694    32862097 :          inline T* access_vector() const
    8695             :          {
    8696    32862097 :             vector_node_.first->value();
    8697    32862097 :             return (vector_base_ + details::numeric::to_uint64(index_.first->value()));
    8698             :          }
    8699             : 
    8700             :          vector_holder_ptr vector_holder_;
    8701             :          T* vector_base_;
    8702             :          branch_t vector_node_;
    8703             :          branch_t index_;
    8704             :       };
    8705             : 
    8706             :       template <typename T>
    8707             :       class vector_celem_node exprtk_final
    8708             :                               : public expression_node<T>
    8709             :                               , public ivariable      <T>
    8710             :       {
    8711             :       public:
    8712             : 
    8713             :          typedef expression_node<T>*            expression_ptr;
    8714             :          typedef vector_holder<T>               vector_holder_t;
    8715             :          typedef vector_holder_t*               vector_holder_ptr;
    8716             :          typedef std::pair<expression_ptr,bool> branch_t;
    8717             : 
    8718         190 :          vector_celem_node(expression_ptr vec_node,
    8719             :                            const std::size_t index,
    8720             :                            vector_holder_ptr vec_holder)
    8721         190 :          : index_(index)
    8722         190 :          , vector_holder_(vec_holder)
    8723         190 :          , vector_base_((*vec_holder)[0])
    8724             :          {
    8725         190 :             construct_branch_pair(vector_node_, vec_node);
    8726         190 :             assert(valid());
    8727         190 :          }
    8728             : 
    8729         190 :          inline T value() const exprtk_override
    8730             :          {
    8731         190 :             return *access_vector();
    8732             :          }
    8733             : 
    8734           0 :          inline T& ref() exprtk_override
    8735             :          {
    8736           0 :             return *access_vector();
    8737             :          }
    8738             : 
    8739           0 :          inline const T& ref() const exprtk_override
    8740             :          {
    8741           0 :             return *access_vector();
    8742             :          }
    8743             : 
    8744        5890 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8745             :          {
    8746        5890 :             return expression_node<T>::e_veccelem;
    8747             :          }
    8748             : 
    8749         760 :          inline bool valid() const exprtk_override
    8750             :          {
    8751             :             return
    8752        1520 :                vector_holder_     &&
    8753        1520 :                vector_node_.first &&
    8754        1520 :                vector_node_.first->valid();
    8755             :          }
    8756             : 
    8757             :          inline vector_holder_t& vec_holder()
    8758             :          {
    8759             :             return (*vector_holder_);
    8760             :          }
    8761             : 
    8762         190 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8763             :          {
    8764         190 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8765         190 :          }
    8766             : 
    8767         380 :          std::size_t node_depth() const exprtk_override
    8768             :          {
    8769         380 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    8770             :          }
    8771             : 
    8772             :       private:
    8773             : 
    8774         190 :          inline T* access_vector() const
    8775             :          {
    8776         190 :             vector_node_.first->value();
    8777         190 :             return (vector_base_ + index_);
    8778             :          }
    8779             : 
    8780             :          const std::size_t index_;
    8781             :          vector_holder_ptr vector_holder_;
    8782             :          T* vector_base_;
    8783             :          branch_t vector_node_;
    8784             :       };
    8785             : 
    8786             :       template <typename T>
    8787             :       class vector_elem_rtc_node exprtk_final
    8788             :                                  : public expression_node<T>
    8789             :                                  , public ivariable      <T>
    8790             :       {
    8791             :       public:
    8792             : 
    8793             :          typedef expression_node<T>*            expression_ptr;
    8794             :          typedef vector_holder<T>               vector_holder_t;
    8795             :          typedef vector_holder_t*               vector_holder_ptr;
    8796             :          typedef std::pair<expression_ptr,bool> branch_t;
    8797             : 
    8798          92 :          vector_elem_rtc_node(expression_ptr vec_node,
    8799             :                               expression_ptr index,
    8800             :                               vector_holder_ptr vec_holder,
    8801             :                               vector_access_runtime_check_ptr vec_rt_chk)
    8802          92 :          : vector_holder_(vec_holder)
    8803           0 :          , vector_base_((*vec_holder)[0])
    8804          92 :          , vec_rt_chk_(vec_rt_chk)
    8805          92 :          , max_vector_index_(vector_holder_->size() - 1)
    8806             :          {
    8807          92 :             construct_branch_pair(vector_node_, vec_node);
    8808          92 :             construct_branch_pair(index_      , index   );
    8809          92 :             assert(valid());
    8810          92 :          }
    8811             : 
    8812         243 :          inline T value() const exprtk_override
    8813             :          {
    8814         243 :             return *access_vector();
    8815             :          }
    8816             : 
    8817         335 :          inline T& ref() exprtk_override
    8818             :          {
    8819         335 :             return *access_vector();
    8820             :          }
    8821             : 
    8822           0 :          inline const T& ref() const exprtk_override
    8823             :          {
    8824           0 :             return *access_vector();
    8825             :          }
    8826             : 
    8827        1428 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8828             :          {
    8829        1428 :             return expression_node<T>::e_vecelemrtc;
    8830             :          }
    8831             : 
    8832         446 :          inline bool valid() const exprtk_override
    8833             :          {
    8834             :             return
    8835         892 :                vector_holder_        &&
    8836         446 :                index_.first          &&
    8837         446 :                vector_node_.first    &&
    8838        1338 :                index_.first->valid() &&
    8839         892 :                vector_node_.first->valid();
    8840             :          }
    8841             : 
    8842             :          inline vector_holder_t& vec_holder()
    8843             :          {
    8844             :             return (*vector_holder_);
    8845             :          }
    8846             : 
    8847          92 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8848             :          {
    8849          92 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8850          92 :             expression_node<T>::ndb_t::collect(index_,       node_delete_list);
    8851          92 :          }
    8852             : 
    8853         226 :          std::size_t node_depth() const exprtk_override
    8854             :          {
    8855             :             return expression_node<T>::ndb_t::compute_node_depth
    8856         226 :                (vector_node_, index_);
    8857             :          }
    8858             : 
    8859             :       private:
    8860             : 
    8861         578 :          inline T* access_vector() const
    8862             :          {
    8863         578 :             const _uint64_t index = details::numeric::to_uint64(index_.first->value());
    8864         578 :             vector_node_.first->value();
    8865             : 
    8866         578 :             if (index <= max_vector_index_)
    8867             :             {
    8868         156 :                return (vector_holder_->data() + index);
    8869             :             }
    8870             : 
    8871         422 :             assert(vec_rt_chk_);
    8872             : 
    8873             :             vector_access_runtime_check::violation_context context;
    8874         422 :             context.base_ptr   = reinterpret_cast<void*>(vector_base_);
    8875         422 :             context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
    8876         422 :             context.access_ptr = reinterpret_cast<void*>(vector_base_ + index);
    8877         422 :             context.type_size  = sizeof(T);
    8878             : 
    8879         422 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    8880             :                reinterpret_cast<T*>(context.access_ptr) :
    8881         422 :                vector_base_ ;
    8882             :          }
    8883             : 
    8884             :          vector_holder_ptr vector_holder_;
    8885             :          T*                vector_base_;
    8886             :          branch_t          vector_node_;
    8887             :          branch_t          index_;
    8888             :          vector_access_runtime_check_ptr vec_rt_chk_;
    8889             :          const std::size_t max_vector_index_;
    8890             :       };
    8891             : 
    8892             :       template <typename T>
    8893             :       class vector_celem_rtc_node exprtk_final
    8894             :                                  : public expression_node<T>
    8895             :                                  , public ivariable      <T>
    8896             :       {
    8897             :       public:
    8898             : 
    8899             :          typedef expression_node<T>*            expression_ptr;
    8900             :          typedef vector_holder<T>               vector_holder_t;
    8901             :          typedef vector_holder_t*               vector_holder_ptr;
    8902             :          typedef std::pair<expression_ptr,bool> branch_t;
    8903             : 
    8904           0 :          vector_celem_rtc_node(expression_ptr vec_node,
    8905             :                                const std::size_t index,
    8906             :                                vector_holder_ptr vec_holder,
    8907             :                                vector_access_runtime_check_ptr vec_rt_chk)
    8908           0 :          : index_(index)
    8909           0 :          , max_vector_index_(vec_holder->size() - 1)
    8910           0 :          , vector_holder_(vec_holder)
    8911           0 :          , vector_base_((*vec_holder)[0])
    8912           0 :          , vec_rt_chk_(vec_rt_chk)
    8913             :          {
    8914           0 :             construct_branch_pair(vector_node_, vec_node);
    8915           0 :             assert(valid());
    8916           0 :          }
    8917             : 
    8918           0 :          inline T value() const exprtk_override
    8919             :          {
    8920           0 :             return *access_vector();
    8921             :          }
    8922             : 
    8923           0 :          inline T& ref() exprtk_override
    8924             :          {
    8925           0 :             return *access_vector();
    8926             :          }
    8927             : 
    8928           0 :          inline const T& ref() const exprtk_override
    8929             :          {
    8930           0 :             return *access_vector();
    8931             :          }
    8932             : 
    8933           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8934             :          {
    8935           0 :             return expression_node<T>::e_veccelemrtc;
    8936             :          }
    8937             : 
    8938           0 :          inline bool valid() const exprtk_override
    8939             :          {
    8940             :             return
    8941           0 :                vector_holder_     &&
    8942           0 :                vector_node_.first &&
    8943           0 :                vector_node_.first->valid();
    8944             :          }
    8945             : 
    8946             :          inline vector_holder_t& vec_holder()
    8947             :          {
    8948             :             return (*vector_holder_);
    8949             :          }
    8950             : 
    8951           0 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8952             :          {
    8953           0 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8954           0 :          }
    8955             : 
    8956           0 :          std::size_t node_depth() const exprtk_override
    8957             :          {
    8958           0 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    8959             :          }
    8960             : 
    8961             :       private:
    8962             : 
    8963           0 :          inline T* access_vector() const
    8964             :          {
    8965           0 :             vector_node_.first->value();
    8966             : 
    8967           0 :             if (index_ <= max_vector_index_)
    8968             :             {
    8969           0 :                return (vector_holder_->data() + index_);
    8970             :             }
    8971             : 
    8972           0 :             assert(vec_rt_chk_);
    8973             : 
    8974             :             vector_access_runtime_check::violation_context context;
    8975           0 :             context.base_ptr   = reinterpret_cast<void*>(vector_base_);
    8976           0 :             context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
    8977           0 :             context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
    8978           0 :             context.type_size  = sizeof(T);
    8979             : 
    8980           0 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    8981             :                reinterpret_cast<T*>(context.access_ptr) :
    8982           0 :                vector_base_ ;
    8983             :          }
    8984             : 
    8985             :          const std::size_t index_;
    8986             :          const std::size_t max_vector_index_;
    8987             :          vector_holder_ptr vector_holder_;
    8988             :          T*                vector_base_;
    8989             :          branch_t          vector_node_;
    8990             :          vector_access_runtime_check_ptr vec_rt_chk_;
    8991             :       };
    8992             : 
    8993             :       template <typename T>
    8994             :       class rebasevector_elem_node exprtk_final
    8995             :                                    : public expression_node<T>
    8996             :                                    , public ivariable      <T>
    8997             :       {
    8998             :       public:
    8999             : 
    9000             :          typedef expression_node<T>*            expression_ptr;
    9001             :          typedef vector_holder<T>               vector_holder_t;
    9002             :          typedef vector_holder_t*               vector_holder_ptr;
    9003             :          typedef vec_data_store<T>              vds_t;
    9004             :          typedef std::pair<expression_ptr,bool> branch_t;
    9005             : 
    9006        1014 :          rebasevector_elem_node(expression_ptr vec_node,
    9007             :                                 expression_ptr index,
    9008             :                                 vector_holder_ptr vec_holder)
    9009        1014 :          : vector_holder_(vec_holder)
    9010             :          {
    9011        1014 :             construct_branch_pair(vector_node_, vec_node);
    9012        1014 :             construct_branch_pair(index_      , index   );
    9013        1014 :             assert(valid());
    9014        1014 :          }
    9015             : 
    9016         863 :          inline T value() const exprtk_override
    9017             :          {
    9018         863 :             return *access_vector();
    9019             :          }
    9020             : 
    9021         600 :          inline T& ref() exprtk_override
    9022             :          {
    9023         600 :             return *access_vector();
    9024             :          }
    9025             : 
    9026           0 :          inline const T& ref() const exprtk_override
    9027             :          {
    9028           0 :             return *access_vector();
    9029             :          }
    9030             : 
    9031       25074 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9032             :          {
    9033       25074 :             return expression_node<T>::e_rbvecelem;
    9034             :          }
    9035             : 
    9036        4631 :          inline bool valid() const exprtk_override
    9037             :          {
    9038             :             return
    9039        9262 :                vector_holder_        &&
    9040        4631 :                index_.first          &&
    9041        4631 :                vector_node_.first    &&
    9042       13893 :                index_.first->valid() &&
    9043        9262 :                vector_node_.first->valid();
    9044             :          }
    9045             : 
    9046             :          inline vector_holder_t& vec_holder()
    9047             :          {
    9048             :             return (*vector_holder_);
    9049             :          }
    9050             : 
    9051        1014 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9052             :          {
    9053        1014 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9054        1014 :             expression_node<T>::ndb_t::collect(index_,       node_delete_list);
    9055        1014 :          }
    9056             : 
    9057        2394 :          std::size_t node_depth() const exprtk_override
    9058             :          {
    9059             :             return expression_node<T>::ndb_t::compute_node_depth
    9060        2394 :                (vector_node_, index_);
    9061             :          }
    9062             : 
    9063             :       private:
    9064             : 
    9065        1463 :          inline T* access_vector() const
    9066             :          {
    9067        1463 :             vector_node_.first->value();
    9068        1463 :             return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value()));
    9069             :          }
    9070             : 
    9071             :          vector_holder_ptr vector_holder_;
    9072             :          branch_t          vector_node_;
    9073             :          branch_t          index_;
    9074             :       };
    9075             : 
    9076             :       template <typename T>
    9077             :       class rebasevector_celem_node exprtk_final
    9078             :                                     : public expression_node<T>
    9079             :                                     , public ivariable      <T>
    9080             :       {
    9081             :       public:
    9082             : 
    9083             :          typedef expression_node<T>* expression_ptr;
    9084             :          typedef vector_holder<T>    vector_holder_t;
    9085             :          typedef vector_holder_t*    vector_holder_ptr;
    9086             :          typedef std::pair<expression_ptr,bool> branch_t;
    9087             : 
    9088        1894 :          rebasevector_celem_node(expression_ptr vec_node,
    9089             :                                  const std::size_t index,
    9090             :                                  vector_holder_ptr vec_holder)
    9091        1894 :          : index_(index)
    9092        1894 :          , vector_holder_(vec_holder)
    9093             :          {
    9094        1894 :             construct_branch_pair(vector_node_, vec_node);
    9095        1894 :             assert(valid());
    9096        1894 :          }
    9097             : 
    9098        1909 :          inline T value() const exprtk_override
    9099             :          {
    9100        1909 :             vector_node_.first->value();
    9101        1909 :             return ref();;
    9102             :          }
    9103             : 
    9104         600 :          inline T& ref() exprtk_override
    9105             :          {
    9106         600 :             return *(vector_holder_->data() + index_);
    9107             :          }
    9108             : 
    9109        1909 :          inline const T& ref() const exprtk_override
    9110             :          {
    9111        1909 :             return *(vector_holder_->data() + index_);
    9112             :          }
    9113             : 
    9114       40354 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9115             :          {
    9116       40354 :             return expression_node<T>::e_rbveccelem;
    9117             :          }
    9118             : 
    9119       10916 :          inline bool valid() const exprtk_override
    9120             :          {
    9121             :             return
    9122       21832 :                vector_holder_     &&
    9123       21832 :                vector_node_.first &&
    9124       21832 :                vector_node_.first->valid();
    9125             :          }
    9126             : 
    9127             :          inline vector_holder_t& vec_holder()
    9128             :          {
    9129             :             return (*vector_holder_);
    9130             :          }
    9131             : 
    9132        1894 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9133             :          {
    9134        1894 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9135        1894 :          }
    9136             : 
    9137        4990 :          std::size_t node_depth() const exprtk_override
    9138             :          {
    9139        4990 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    9140             :          }
    9141             : 
    9142             :       private:
    9143             : 
    9144             :          const std::size_t index_;
    9145             :          vector_holder_ptr vector_holder_;
    9146             :          branch_t          vector_node_;
    9147             :       };
    9148             : 
    9149             :       template <typename T>
    9150             :       class rebasevector_elem_rtc_node exprtk_final
    9151             :                                        : public expression_node<T>
    9152             :                                        , public ivariable      <T>
    9153             :       {
    9154             :       public:
    9155             : 
    9156             :          typedef expression_node<T>*            expression_ptr;
    9157             :          typedef vector_holder<T>               vector_holder_t;
    9158             :          typedef vector_holder_t*               vector_holder_ptr;
    9159             :          typedef std::pair<expression_ptr,bool> branch_t;
    9160             : 
    9161           2 :          rebasevector_elem_rtc_node(expression_ptr vec_node,
    9162             :                                     expression_ptr index,
    9163             :                                     vector_holder_ptr vec_holder,
    9164             :                                     vector_access_runtime_check_ptr vec_rt_chk)
    9165           2 :          : vector_holder_(vec_holder)
    9166           2 :          , vec_rt_chk_(vec_rt_chk)
    9167             :          {
    9168           2 :             construct_branch_pair(vector_node_, vec_node);
    9169           2 :             construct_branch_pair(index_      , index   );
    9170           2 :             assert(valid());
    9171           2 :          }
    9172             : 
    9173          30 :          inline T value() const exprtk_override
    9174             :          {
    9175          30 :             return *access_vector();
    9176             :          }
    9177             : 
    9178           0 :          inline T& ref() exprtk_override
    9179             :          {
    9180           0 :             return *access_vector();
    9181             :          }
    9182             : 
    9183           0 :          inline const T& ref() const exprtk_override
    9184             :          {
    9185           0 :             return *access_vector();
    9186             :          }
    9187             : 
    9188          52 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9189             :          {
    9190          52 :             return expression_node<T>::e_rbvecelemrtc;
    9191             :          }
    9192             : 
    9193          12 :          inline bool valid() const exprtk_override
    9194             :          {
    9195             :             return
    9196          24 :                vector_holder_        &&
    9197          12 :                index_.first          &&
    9198          12 :                vector_node_.first    &&
    9199          36 :                index_.first->valid() &&
    9200          24 :                vector_node_.first->valid();
    9201             :          }
    9202             : 
    9203             :          inline vector_holder_t& vec_holder()
    9204             :          {
    9205             :             return (*vector_holder_);
    9206             :          }
    9207             : 
    9208           2 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9209             :          {
    9210           2 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9211           2 :             expression_node<T>::ndb_t::collect(index_      , node_delete_list);
    9212           2 :          }
    9213             : 
    9214           6 :          std::size_t node_depth() const exprtk_override
    9215             :          {
    9216             :             return expression_node<T>::ndb_t::compute_node_depth
    9217           6 :                (vector_node_, index_);
    9218             :          }
    9219             : 
    9220             :       private:
    9221             : 
    9222          30 :          inline T* access_vector() const
    9223             :          {
    9224          30 :             vector_node_.first->value();
    9225          30 :             const _uint64_t index = details::numeric::to_uint64(index_.first->value());
    9226             : 
    9227          30 :             if (index <= (vector_holder_->size() - 1))
    9228             :             {
    9229          15 :                return (vector_holder_->data() + index);
    9230             :             }
    9231             : 
    9232          15 :             assert(vec_rt_chk_);
    9233             : 
    9234             :             vector_access_runtime_check::violation_context context;
    9235          15 :             context.base_ptr   = reinterpret_cast<void*>(vector_holder_->data());
    9236          15 :             context.end_ptr    = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size());
    9237          15 :             context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index);
    9238          15 :             context.type_size  = sizeof(T);
    9239             : 
    9240          15 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    9241             :                    reinterpret_cast<T*>(context.access_ptr) :
    9242          15 :                    vector_holder_->data() ;
    9243             :          }
    9244             : 
    9245             :          vector_holder_ptr vector_holder_;
    9246             :          branch_t          vector_node_;
    9247             :          branch_t          index_;
    9248             :          vector_access_runtime_check_ptr vec_rt_chk_;
    9249             :       };
    9250             : 
    9251             :       template <typename T>
    9252             :       class rebasevector_celem_rtc_node exprtk_final
    9253             :                                     : public expression_node<T>
    9254             :                                     , public ivariable      <T>
    9255             :       {
    9256             :       public:
    9257             : 
    9258             :          typedef expression_node<T>*            expression_ptr;
    9259             :          typedef vector_holder<T>               vector_holder_t;
    9260             :          typedef vector_holder_t*               vector_holder_ptr;
    9261             :          typedef std::pair<expression_ptr,bool> branch_t;
    9262             : 
    9263           0 :          rebasevector_celem_rtc_node(expression_ptr vec_node,
    9264             :                                      const std::size_t index,
    9265             :                                      vector_holder_ptr vec_holder,
    9266             :                                      vector_access_runtime_check_ptr vec_rt_chk)
    9267           0 :          : index_(index)
    9268           0 :          , vector_holder_(vec_holder)
    9269           0 :          , vector_base_((*vec_holder)[0])
    9270           0 :          , vec_rt_chk_(vec_rt_chk)
    9271             :          {
    9272           0 :             construct_branch_pair(vector_node_, vec_node);
    9273           0 :             assert(valid());
    9274           0 :          }
    9275             : 
    9276           0 :          inline T value() const exprtk_override
    9277             :          {
    9278           0 :             return *access_vector();
    9279             :          }
    9280             : 
    9281           0 :          inline T& ref() exprtk_override
    9282             :          {
    9283           0 :             return *access_vector();
    9284             :          }
    9285             : 
    9286           0 :          inline const T& ref() const exprtk_override
    9287             :          {
    9288           0 :             return *access_vector();
    9289             :          }
    9290             : 
    9291           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9292             :          {
    9293           0 :             return expression_node<T>::e_rbveccelemrtc;
    9294             :          }
    9295             : 
    9296           0 :          inline bool valid() const exprtk_override
    9297             :          {
    9298             :             return
    9299           0 :                vector_holder_     &&
    9300           0 :                vector_node_.first &&
    9301           0 :                vector_node_.first->valid();
    9302             :          }
    9303             : 
    9304             :          inline vector_holder_t& vec_holder()
    9305             :          {
    9306             :             return (*vector_holder_);
    9307             :          }
    9308             : 
    9309           0 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9310             :          {
    9311           0 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9312           0 :          }
    9313             : 
    9314           0 :          std::size_t node_depth() const exprtk_override
    9315             :          {
    9316           0 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    9317             :          }
    9318             : 
    9319             :       private:
    9320             : 
    9321           0 :          inline T* access_vector() const
    9322             :          {
    9323           0 :             vector_node_.first->value();
    9324             : 
    9325           0 :             if (index_ <= vector_holder_->size() - 1)
    9326             :             {
    9327           0 :                return (vector_holder_->data() + index_);
    9328             :             }
    9329             : 
    9330           0 :             assert(vec_rt_chk_);
    9331             : 
    9332             :             vector_access_runtime_check::violation_context context;
    9333           0 :             context.base_ptr   = reinterpret_cast<void*>(vector_base_);
    9334           0 :             context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
    9335           0 :             context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
    9336           0 :             context.type_size  = sizeof(T);
    9337             : 
    9338           0 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    9339             :                reinterpret_cast<T*>(context.access_ptr) :
    9340           0 :                vector_base_ ;
    9341             :          }
    9342             : 
    9343             :          const std::size_t index_;
    9344             :          vector_holder_ptr vector_holder_;
    9345             :          T*                vector_base_;
    9346             :          branch_t          vector_node_;
    9347             :          vector_access_runtime_check_ptr vec_rt_chk_;
    9348             :       };
    9349             : 
    9350             :       template <typename T>
    9351             :       class vector_initialisation_node exprtk_final : public expression_node<T>
    9352             :       {
    9353             :       public:
    9354             : 
    9355             :          typedef expression_node<T>* expression_ptr;
    9356             : 
    9357       16614 :          vector_initialisation_node(T* vector_base,
    9358             :                                     const std::size_t& size,
    9359             :                                     const std::vector<expression_ptr>& initialiser_list,
    9360             :                                     const bool single_value_initialse)
    9361       16614 :          : vector_base_(vector_base)
    9362       16614 :          , initialiser_list_(initialiser_list)
    9363       16614 :          , size_(size)
    9364       16614 :          , single_value_initialse_(single_value_initialse)
    9365       16614 :          , zero_value_initialse_(false)
    9366       16614 :          , const_nonzero_literal_value_initialse_(false)
    9367       16614 :          , single_initialiser_value_(T(0))
    9368             :          {
    9369       16614 :             if (single_value_initialse_)
    9370             :             {
    9371           0 :                if (initialiser_list_.empty())
    9372           0 :                   zero_value_initialse_ = true;
    9373           0 :                else if (
    9374           0 :                          (initialiser_list_.size() == 1) &&
    9375           0 :                          details::is_constant_node(initialiser_list_[0]) &&
    9376           0 :                          (T(0) == initialiser_list_[0]->value())
    9377             :                        )
    9378             :                {
    9379           0 :                   zero_value_initialse_ = true;
    9380             :                }
    9381             :                else
    9382             :                {
    9383           0 :                   assert(initialiser_list_.size() == 1);
    9384             : 
    9385           0 :                   if (details::is_constant_node(initialiser_list_[0]))
    9386             :                   {
    9387           0 :                      const_nonzero_literal_value_initialse_ = true;
    9388           0 :                      single_initialiser_value_ = initialiser_list_[0]->value();
    9389           0 :                      assert(T(0) != single_initialiser_value_);
    9390             :                   }
    9391             :                }
    9392             :             }
    9393       16614 :          }
    9394             : 
    9395       17358 :          inline T value() const exprtk_override
    9396             :          {
    9397       17358 :             if (single_value_initialse_)
    9398             :             {
    9399           0 :                if (zero_value_initialse_)
    9400             :                {
    9401           0 :                   details::set_zero_value(vector_base_, size_);
    9402             :                }
    9403           0 :                else if (const_nonzero_literal_value_initialse_)
    9404             :                {
    9405           0 :                   for (std::size_t i = 0; i < size_; ++i)
    9406             :                   {
    9407           0 :                      *(vector_base_ + i) = single_initialiser_value_;
    9408             :                   }
    9409             :                }
    9410             :                else
    9411             :                {
    9412           0 :                   for (std::size_t i = 0; i < size_; ++i)
    9413             :                   {
    9414           0 :                      *(vector_base_ + i) = initialiser_list_[0]->value();
    9415             :                   }
    9416             :                }
    9417             :             }
    9418             :             else
    9419             :             {
    9420       17358 :                const std::size_t initialiser_list_size = initialiser_list_.size();
    9421             : 
    9422       79110 :                for (std::size_t i = 0; i < initialiser_list_size; ++i)
    9423             :                {
    9424       61752 :                   *(vector_base_ + i) = initialiser_list_[i]->value();
    9425             :                }
    9426             : 
    9427       17358 :                if (initialiser_list_size < size_)
    9428             :                {
    9429        1178 :                   details::set_zero_value(
    9430        1178 :                      vector_base_ + initialiser_list_size,
    9431        1178 :                      (size_ - initialiser_list_size));
    9432             :                }
    9433             :             }
    9434             : 
    9435       17358 :             return *(vector_base_);
    9436             :          }
    9437             : 
    9438      210588 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9439             :          {
    9440      210588 :             return expression_node<T>::e_vecinit;
    9441             :          }
    9442             : 
    9443       33338 :          inline bool valid() const exprtk_override
    9444             :          {
    9445       33338 :             return vector_base_;
    9446             :          }
    9447             : 
    9448       16614 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9449             :          {
    9450       16614 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9451       16614 :          }
    9452             : 
    9453       41836 :          std::size_t node_depth() const exprtk_override
    9454             :          {
    9455       41836 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9456             :          }
    9457             : 
    9458             :       private:
    9459             : 
    9460             :          vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete;
    9461             :          vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete;
    9462             : 
    9463             :          mutable T* vector_base_;
    9464             :          std::vector<expression_ptr> initialiser_list_;
    9465             :          const std::size_t size_;
    9466             :          const bool single_value_initialse_;
    9467             :          bool zero_value_initialse_;
    9468             :          bool const_nonzero_literal_value_initialse_;
    9469             :          T single_initialiser_value_;
    9470             :       };
    9471             : 
    9472             :       template <typename T>
    9473             :       class vector_init_zero_value_node exprtk_final : public expression_node<T>
    9474             :       {
    9475             :       public:
    9476             : 
    9477             :          typedef expression_node<T>* expression_ptr;
    9478             : 
    9479         839 :          vector_init_zero_value_node(T* vector_base,
    9480             :                                      const std::size_t& size,
    9481             :                                      const std::vector<expression_ptr>& initialiser_list)
    9482         839 :          : vector_base_(vector_base)
    9483         839 :          , size_(size)
    9484         839 :          , initialiser_list_(initialiser_list)
    9485         839 :          {}
    9486             : 
    9487         833 :          inline T value() const exprtk_override
    9488             :          {
    9489         833 :             details::set_zero_value(vector_base_, size_);
    9490         833 :             return *(vector_base_);
    9491             :          }
    9492             : 
    9493       11650 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9494             :          {
    9495       11650 :             return expression_node<T>::e_vecinit;
    9496             :          }
    9497             : 
    9498        1672 :          inline bool valid() const exprtk_override
    9499             :          {
    9500        1672 :             return vector_base_;
    9501             :          }
    9502             : 
    9503         839 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9504             :          {
    9505         839 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9506         839 :          }
    9507             : 
    9508        2499 :          std::size_t node_depth() const exprtk_override
    9509             :          {
    9510        2499 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9511             :          }
    9512             : 
    9513             :       private:
    9514             : 
    9515             :          vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete;
    9516             :          vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete;
    9517             : 
    9518             :          mutable T* vector_base_;
    9519             :          const std::size_t size_;
    9520             :          std::vector<expression_ptr> initialiser_list_;
    9521             :       };
    9522             : 
    9523             :       template <typename T>
    9524             :       class vector_init_single_constvalue_node exprtk_final : public expression_node<T>
    9525             :       {
    9526             :       public:
    9527             : 
    9528             :          typedef expression_node<T>* expression_ptr;
    9529             : 
    9530        6149 :          vector_init_single_constvalue_node(T* vector_base,
    9531             :                                             const std::size_t& size,
    9532             :                                             const std::vector<expression_ptr>& initialiser_list)
    9533        6149 :          : vector_base_(vector_base)
    9534        6149 :          , size_(size)
    9535        6149 :          , initialiser_list_(initialiser_list)
    9536             :          {
    9537        6149 :             single_initialiser_value_ = initialiser_list_[0]->value();
    9538        6149 :             assert(valid());
    9539        6149 :          }
    9540             : 
    9541        6157 :          inline T value() const exprtk_override
    9542             :          {
    9543   117022071 :             for (std::size_t i = 0; i < size_; ++i)
    9544             :             {
    9545   117015914 :                *(vector_base_ + i) = single_initialiser_value_;
    9546             :             }
    9547             : 
    9548        6157 :             return *(vector_base_);
    9549             :          }
    9550             : 
    9551      125692 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9552             :          {
    9553      125692 :             return expression_node<T>::e_vecinit;
    9554             :          }
    9555             : 
    9556       23047 :          inline bool valid() const exprtk_override
    9557             :          {
    9558       23047 :             return vector_base_ &&
    9559       23047 :                    (initialiser_list_.size() == 1) &&
    9560       69141 :                    (details::is_constant_node(initialiser_list_[0])) &&
    9561       46094 :                    (single_initialiser_value_ != T(0));
    9562             :          }
    9563             : 
    9564        6149 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9565             :          {
    9566        6149 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9567        6149 :          }
    9568             : 
    9569       19249 :          std::size_t node_depth() const exprtk_override
    9570             :          {
    9571       19249 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9572             :          }
    9573             : 
    9574             :       private:
    9575             : 
    9576             :          vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete;
    9577             :          vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete;
    9578             : 
    9579             :          mutable T* vector_base_;
    9580             :          const std::size_t size_;
    9581             :          std::vector<expression_ptr> initialiser_list_;
    9582             :          T single_initialiser_value_;
    9583             :       };
    9584             : 
    9585             :       template <typename T>
    9586             :       class vector_init_single_value_node exprtk_final : public expression_node<T>
    9587             :       {
    9588             :       public:
    9589             : 
    9590             :          typedef expression_node<T>* expression_ptr;
    9591             : 
    9592          90 :          vector_init_single_value_node(T* vector_base,
    9593             :                                        const std::size_t& size,
    9594             :                                        const std::vector<expression_ptr>& initialiser_list)
    9595          90 :          : vector_base_(vector_base)
    9596          90 :          , size_(size)
    9597          90 :          , initialiser_list_(initialiser_list)
    9598             :          {
    9599          90 :             assert(valid());
    9600          90 :          }
    9601             : 
    9602          90 :          inline T value() const exprtk_override
    9603             :          {
    9604          90 :             expression_node<T>& node = *initialiser_list_[0];
    9605             : 
    9606         520 :             for (std::size_t i = 0; i < size_; ++i)
    9607             :             {
    9608         430 :                *(vector_base_ + i) = node.value();
    9609             :             }
    9610             : 
    9611          90 :             return *(vector_base_);
    9612             :          }
    9613             : 
    9614         990 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9615             :          {
    9616         990 :             return expression_node<T>::e_vecinit;
    9617             :          }
    9618             : 
    9619         270 :          inline bool valid() const exprtk_override
    9620             :          {
    9621         270 :             return vector_base_ &&
    9622         540 :                    (initialiser_list_.size() == 1) &&
    9623         540 :                    !details::is_constant_node(initialiser_list_[0]);
    9624             :          }
    9625             : 
    9626          90 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9627             :          {
    9628          90 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9629          90 :          }
    9630             : 
    9631         180 :          std::size_t node_depth() const exprtk_override
    9632             :          {
    9633         180 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9634             :          }
    9635             : 
    9636             :       private:
    9637             : 
    9638             :          vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete;
    9639             :          vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete;
    9640             : 
    9641             :          mutable T* vector_base_;
    9642             :          const std::size_t size_;
    9643             :          std::vector<expression_ptr> initialiser_list_;
    9644             :       };
    9645             : 
    9646             :       template <typename T>
    9647             :       class vector_init_iota_constconst_node exprtk_final : public expression_node<T>
    9648             :       {
    9649             :       public:
    9650             : 
    9651             :          typedef expression_node<T>* expression_ptr;
    9652             : 
    9653         135 :          vector_init_iota_constconst_node(T* vector_base,
    9654             :                                           const std::size_t& size,
    9655             :                                           const std::vector<expression_ptr>& initialiser_list)
    9656         135 :          : vector_base_(vector_base)
    9657         135 :          , size_(size)
    9658         135 :          , initialiser_list_(initialiser_list)
    9659             :          {
    9660         135 :             base_value_      = initialiser_list_[0]->value();
    9661         135 :             increment_value_ = initialiser_list_[1]->value();
    9662             : 
    9663         135 :             assert(valid());
    9664         135 :          }
    9665             : 
    9666         135 :          inline T value() const exprtk_override
    9667             :          {
    9668         135 :             T value = base_value_;
    9669             : 
    9670         615 :             for (std::size_t i = 0; i < size_; ++i, value += increment_value_)
    9671             :             {
    9672         480 :                *(vector_base_ + i) = value;
    9673             :             }
    9674             : 
    9675         135 :             return *(vector_base_);
    9676             :          }
    9677             : 
    9678        1830 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9679             :          {
    9680        1830 :             return expression_node<T>::e_vecinit;
    9681             :          }
    9682             : 
    9683         405 :          inline bool valid() const exprtk_override
    9684             :          {
    9685         405 :             return vector_base_ &&
    9686         405 :                    (initialiser_list_.size() == 2) &&
    9687        1215 :                    (details::is_constant_node(initialiser_list_[0])) &&
    9688         810 :                    (details::is_constant_node(initialiser_list_[1])) ;
    9689             :          }
    9690             : 
    9691         135 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9692             :          {
    9693         135 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9694         135 :          }
    9695             : 
    9696         385 :          std::size_t node_depth() const exprtk_override
    9697             :          {
    9698         385 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9699             :          }
    9700             : 
    9701             :       private:
    9702             : 
    9703             :          vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete;
    9704             :          vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete;
    9705             : 
    9706             :          mutable T* vector_base_;
    9707             :          const std::size_t size_;
    9708             :          std::vector<expression_ptr> initialiser_list_;
    9709             :          T base_value_;
    9710             :          T increment_value_;
    9711             :       };
    9712             : 
    9713             :       template <typename T>
    9714             :       class vector_init_iota_constnconst_node exprtk_final : public expression_node<T>
    9715             :       {
    9716             :       public:
    9717             : 
    9718             :          typedef expression_node<T>* expression_ptr;
    9719             : 
    9720          40 :          vector_init_iota_constnconst_node(T* vector_base,
    9721             :                                            const std::size_t& size,
    9722             :                                            const std::vector<expression_ptr>& initialiser_list)
    9723          40 :          : vector_base_(vector_base)
    9724          40 :          , size_(size)
    9725          40 :          , initialiser_list_(initialiser_list)
    9726             :          {
    9727          40 :             assert(valid());
    9728          40 :             base_value_ = initialiser_list_[0]->value();
    9729          40 :          }
    9730             : 
    9731          40 :          inline T value() const exprtk_override
    9732             :          {
    9733          40 :             T value = base_value_;
    9734          40 :             expression_node<T>& increment = *initialiser_list_[1];
    9735             : 
    9736         160 :             for (std::size_t i = 0; i < size_; ++i, value += increment.value())
    9737             :             {
    9738         120 :                *(vector_base_ + i) = value;
    9739             :             }
    9740             : 
    9741          40 :             return *(vector_base_);
    9742             :          }
    9743             : 
    9744         440 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9745             :          {
    9746         440 :             return expression_node<T>::e_vecinit;
    9747             :          }
    9748             : 
    9749         120 :          inline bool valid() const exprtk_override
    9750             :          {
    9751         120 :             return vector_base_ &&
    9752         120 :                   (initialiser_list_.size() == 2) &&
    9753         360 :                   ( details::is_constant_node(initialiser_list_[0])) &&
    9754         240 :                   (!details::is_constant_node(initialiser_list_[1]));
    9755             :          }
    9756             : 
    9757          40 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9758             :          {
    9759          40 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9760          40 :          }
    9761             : 
    9762          80 :          std::size_t node_depth() const exprtk_override
    9763             :          {
    9764          80 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9765             :          }
    9766             : 
    9767             :       private:
    9768             : 
    9769             :          vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete;
    9770             :          vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete;
    9771             : 
    9772             :          mutable T* vector_base_;
    9773             :          const std::size_t size_;
    9774             :          std::vector<expression_ptr> initialiser_list_;
    9775             :          T base_value_;
    9776             :       };
    9777             : 
    9778             :       template <typename T>
    9779             :       class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T>
    9780             :       {
    9781             :       public:
    9782             : 
    9783             :          typedef expression_node<T>* expression_ptr;
    9784             : 
    9785          20 :          vector_init_iota_nconstconst_node(T* vector_base,
    9786             :                                            const std::size_t& size,
    9787             :                                            const std::vector<expression_ptr>& initialiser_list)
    9788          20 :          : vector_base_(vector_base)
    9789          20 :          , size_(size)
    9790          20 :          , initialiser_list_(initialiser_list)
    9791             :          {
    9792          20 :             assert(valid());
    9793          20 :          }
    9794             : 
    9795          20 :          inline T value() const exprtk_override
    9796             :          {
    9797          20 :             T value = initialiser_list_[0]->value();
    9798          20 :             const T increment = initialiser_list_[1]->value();
    9799             : 
    9800          80 :             for (std::size_t i = 0; i < size_; ++i, value += increment)
    9801             :             {
    9802          60 :                *(vector_base_ + i) = value;
    9803             :             }
    9804             : 
    9805          20 :             return *(vector_base_);
    9806             :          }
    9807             : 
    9808         220 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9809             :          {
    9810         220 :             return expression_node<T>::e_vecinit;
    9811             :          }
    9812             : 
    9813          60 :          inline bool valid() const exprtk_override
    9814             :          {
    9815          60 :             return vector_base_ &&
    9816          60 :                    (initialiser_list_.size() == 2) &&
    9817         180 :                    (!details::is_constant_node(initialiser_list_[0])) &&
    9818         120 :                    (details::is_constant_node(initialiser_list_[1]));
    9819             :          }
    9820             : 
    9821          20 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9822             :          {
    9823          20 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9824          20 :          }
    9825             : 
    9826          40 :          std::size_t node_depth() const exprtk_override
    9827             :          {
    9828          40 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9829             :          }
    9830             : 
    9831             :       private:
    9832             : 
    9833             :          vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete;
    9834             :          vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete;
    9835             : 
    9836             :          mutable T* vector_base_;
    9837             :          const std::size_t size_;
    9838             :          std::vector<expression_ptr> initialiser_list_;
    9839             :       };
    9840             : 
    9841             :       template <typename T>
    9842             :       class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T>
    9843             :       {
    9844             :       public:
    9845             : 
    9846             :          typedef expression_node<T>* expression_ptr;
    9847             : 
    9848          20 :          vector_init_iota_nconstnconst_node(T* vector_base,
    9849             :                                             const std::size_t& size,
    9850             :                                             const std::vector<expression_ptr>& initialiser_list)
    9851          20 :          : vector_base_(vector_base)
    9852          20 :          , size_(size)
    9853          20 :          , initialiser_list_(initialiser_list)
    9854             :          {
    9855          20 :             assert(valid());
    9856          20 :          }
    9857             : 
    9858          20 :          inline T value() const exprtk_override
    9859             :          {
    9860          20 :             T value = initialiser_list_[0]->value();
    9861          20 :             expression_node<T>& increment = *initialiser_list_[1];
    9862             : 
    9863          80 :             for (std::size_t i = 0; i < size_; ++i, value += increment.value())
    9864             :             {
    9865          60 :                *(vector_base_ + i) = value;
    9866             :             }
    9867             : 
    9868          20 :             return *(vector_base_);
    9869             :          }
    9870             : 
    9871         220 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9872             :          {
    9873         220 :             return expression_node<T>::e_vecinit;
    9874             :          }
    9875             : 
    9876          60 :          inline bool valid() const exprtk_override
    9877             :          {
    9878          60 :             return vector_base_ &&
    9879          60 :                    (initialiser_list_.size() == 2) &&
    9880         180 :                    (!details::is_constant_node(initialiser_list_[0])) &&
    9881         120 :                    (!details::is_constant_node(initialiser_list_[1]));
    9882             :          }
    9883             : 
    9884          20 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9885             :          {
    9886          20 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9887          20 :          }
    9888             : 
    9889          40 :          std::size_t node_depth() const exprtk_override
    9890             :          {
    9891          40 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9892             :          }
    9893             : 
    9894             :       private:
    9895             : 
    9896             :          vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete;
    9897             :          vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete;
    9898             : 
    9899             :          mutable T* vector_base_;
    9900             :          const std::size_t size_;
    9901             :          std::vector<expression_ptr> initialiser_list_;
    9902             :       };
    9903             : 
    9904             :       template <typename T>
    9905             :       class swap_node exprtk_final : public expression_node<T>
    9906             :       {
    9907             :       public:
    9908             : 
    9909             :          typedef expression_node<T>* expression_ptr;
    9910             :          typedef variable_node<T>*   variable_node_ptr;
    9911             : 
    9912         480 :          swap_node(variable_node_ptr var0, variable_node_ptr var1)
    9913         480 :          : var0_(var0)
    9914         480 :          , var1_(var1)
    9915         480 :          {}
    9916             : 
    9917         480 :          inline T value() const exprtk_override
    9918             :          {
    9919         480 :             std::swap(var0_->ref(),var1_->ref());
    9920         480 :             return var1_->ref();
    9921             :          }
    9922             : 
    9923        5760 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9924             :          {
    9925        5760 :             return expression_node<T>::e_swap;
    9926             :          }
    9927             : 
    9928             :       private:
    9929             : 
    9930             :          variable_node_ptr var0_;
    9931             :          variable_node_ptr var1_;
    9932             :       };
    9933             : 
    9934             :       template <typename T>
    9935             :       class swap_generic_node exprtk_final : public binary_node<T>
    9936             :       {
    9937             :       public:
    9938             : 
    9939             :          typedef expression_node<T>* expression_ptr;
    9940             :          typedef ivariable<T>*       ivariable_ptr;
    9941             : 
    9942         646 :          swap_generic_node(expression_ptr var0, expression_ptr var1)
    9943        1292 :          : binary_node<T>(details::e_swap, var0, var1)
    9944         646 :          , var0_(dynamic_cast<ivariable_ptr>(var0))
    9945        1292 :          , var1_(dynamic_cast<ivariable_ptr>(var1))
    9946         646 :          {}
    9947             : 
    9948         685 :          inline T value() const exprtk_override
    9949             :          {
    9950         685 :             std::swap(var0_->ref(),var1_->ref());
    9951         685 :             return var1_->ref();
    9952             :          }
    9953             : 
    9954        7544 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9955             :          {
    9956        7544 :             return expression_node<T>::e_swap;
    9957             :          }
    9958             : 
    9959             :       private:
    9960             : 
    9961             :          ivariable_ptr var0_;
    9962             :          ivariable_ptr var1_;
    9963             :       };
    9964             : 
    9965             :       template <typename T>
    9966             :       class swap_vecvec_node exprtk_final
    9967             :                              : public binary_node     <T>
    9968             :                              , public vector_interface<T>
    9969             :       {
    9970             :       public:
    9971             : 
    9972             :          typedef expression_node<T>* expression_ptr;
    9973             :          typedef vector_node    <T>* vector_node_ptr;
    9974             :          typedef vec_data_store <T>  vds_t;
    9975             : 
    9976             :          using binary_node<T>::branch;
    9977             : 
    9978         662 :          swap_vecvec_node(expression_ptr branch0,
    9979             :                           expression_ptr branch1)
    9980           0 :          : binary_node<T>(details::e_swap, branch0, branch1)
    9981         662 :          , vec0_node_ptr_(0)
    9982         662 :          , vec1_node_ptr_(0)
    9983         662 :          , initialised_  (false)
    9984             :          {
    9985         662 :             if (is_ivector_node(branch(0)))
    9986             :             {
    9987         662 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
    9988             : 
    9989         662 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
    9990             :                {
    9991         662 :                   vec0_node_ptr_ = vi->vec();
    9992         662 :                   vds()          = vi->vds();
    9993             :                }
    9994             :             }
    9995             : 
    9996         662 :             if (is_ivector_node(branch(1)))
    9997             :             {
    9998         662 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
    9999             : 
   10000         662 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   10001             :                {
   10002         662 :                   vec1_node_ptr_ = vi->vec();
   10003             :                }
   10004             :             }
   10005             : 
   10006         662 :             if (vec0_node_ptr_ && vec1_node_ptr_)
   10007             :             {
   10008         662 :                initialised_ = size() <= base_size();
   10009             :             }
   10010             : 
   10011         662 :             assert(valid());
   10012         662 :          }
   10013             : 
   10014         662 :          inline T value() const exprtk_override
   10015             :          {
   10016         662 :             binary_node<T>::branch(0)->value();
   10017         662 :             binary_node<T>::branch(1)->value();
   10018             : 
   10019         662 :             T* vec0 = vec0_node_ptr_->vds().data();
   10020         662 :             T* vec1 = vec1_node_ptr_->vds().data();
   10021             : 
   10022         662 :             assert(size() <= base_size());
   10023         662 :             const std::size_t n = size();
   10024             : 
   10025        2186 :             for (std::size_t i = 0; i < n; ++i)
   10026             :             {
   10027        1524 :                std::swap(vec0[i],vec1[i]);
   10028             :             }
   10029             : 
   10030         662 :             return vec1_node_ptr_->value();
   10031             :          }
   10032             : 
   10033           0 :          vector_node_ptr vec() const exprtk_override
   10034             :          {
   10035           0 :             return vec0_node_ptr_;
   10036             :          }
   10037             : 
   10038           0 :          vector_node_ptr vec() exprtk_override
   10039             :          {
   10040           0 :             return vec0_node_ptr_;
   10041             :          }
   10042             : 
   10043        7282 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10044             :          {
   10045        7282 :             return expression_node<T>::e_vecvecswap;
   10046             :          }
   10047             : 
   10048        1986 :          inline bool valid() const exprtk_override
   10049             :          {
   10050        1986 :             return initialised_ && binary_node<T>::valid();
   10051             :          }
   10052             : 
   10053        1986 :          std::size_t size() const exprtk_override
   10054             :          {
   10055        1986 :             return std::min(
   10056        1986 :                vec0_node_ptr_->vec_holder().size(),
   10057        3972 :                vec1_node_ptr_->vec_holder().size());
   10058             :          }
   10059             : 
   10060        1324 :          std::size_t base_size() const exprtk_override
   10061             :          {
   10062        1324 :             return std::min(
   10063        1324 :                vec0_node_ptr_->vec_holder().base_size(),
   10064        2648 :                vec1_node_ptr_->vec_holder().base_size());
   10065             :          }
   10066             : 
   10067         662 :          vds_t& vds() exprtk_override
   10068             :          {
   10069         662 :             return vds_;
   10070             :          }
   10071             : 
   10072           0 :          const vds_t& vds() const exprtk_override
   10073             :          {
   10074           0 :             return vds_;
   10075             :          }
   10076             : 
   10077             :       private:
   10078             : 
   10079             :          vector_node<T>* vec0_node_ptr_;
   10080             :          vector_node<T>* vec1_node_ptr_;
   10081             :          bool            initialised_;
   10082             :          vds_t           vds_;
   10083             :       };
   10084             : 
   10085             :       #ifndef exprtk_disable_string_capabilities
   10086             :       template <typename T>
   10087             :       class stringvar_node exprtk_final
   10088             :                            : public expression_node <T>
   10089             :                            , public string_base_node<T>
   10090             :                            , public range_interface <T>
   10091             :       {
   10092             :       public:
   10093             : 
   10094             :          typedef typename range_interface<T>::range_t range_t;
   10095             : 
   10096             :          static std::string null_value;
   10097             : 
   10098             :          explicit stringvar_node()
   10099             :          : value_(&null_value)
   10100             :          {}
   10101             : 
   10102      132050 :          explicit stringvar_node(std::string& v)
   10103      132050 :          : value_(&v)
   10104             :          {
   10105      132050 :             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   10106      132050 :             rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size());
   10107      132050 :             rp_.cache.first  = rp_.n0_c.second;
   10108      132050 :             rp_.cache.second = rp_.n1_c.second;
   10109      132050 :          }
   10110             : 
   10111             :          inline bool operator <(const stringvar_node<T>& v) const
   10112             :          {
   10113             :             return this < (&v);
   10114             :          }
   10115             : 
   10116       29712 :          inline T value() const exprtk_override
   10117             :          {
   10118       29712 :             rp_.n1_c.second  = (*value_).size();
   10119       29712 :             rp_.cache.second = rp_.n1_c.second;
   10120             : 
   10121       29712 :             return std::numeric_limits<T>::quiet_NaN();
   10122             :          }
   10123             : 
   10124        1740 :          std::string str() const exprtk_override
   10125             :          {
   10126        1740 :             return ref();
   10127             :          }
   10128             : 
   10129       25505 :          char_cptr base() const exprtk_override
   10130             :          {
   10131       25505 :             return &(*value_)[0];
   10132             :          }
   10133             : 
   10134       10853 :          std::size_t size() const exprtk_override
   10135             :          {
   10136       10853 :             return ref().size();
   10137             :          }
   10138             : 
   10139       73519 :          std::string& ref()
   10140             :          {
   10141       73519 :             return (*value_);
   10142             :          }
   10143             : 
   10144       12593 :          const std::string& ref() const
   10145             :          {
   10146       12593 :             return (*value_);
   10147             :          }
   10148             : 
   10149       10629 :          range_t& range_ref() exprtk_override
   10150             :          {
   10151       10629 :             return rp_;
   10152             :          }
   10153             : 
   10154           0 :          const range_t& range_ref() const exprtk_override
   10155             :          {
   10156           0 :             return rp_;
   10157             :          }
   10158             : 
   10159      979868 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10160             :          {
   10161      979868 :             return expression_node<T>::e_stringvar;
   10162             :          }
   10163             : 
   10164             :          void rebase(std::string& s)
   10165             :          {
   10166             :             value_ = &s;
   10167             :             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   10168             :             rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1);
   10169             :             rp_.cache.first  = rp_.n0_c.second;
   10170             :             rp_.cache.second = rp_.n1_c.second;
   10171             :          }
   10172             : 
   10173             :       private:
   10174             : 
   10175             :          std::string* value_;
   10176             :          mutable range_t rp_;
   10177             :       };
   10178             : 
   10179             :       template <typename T>
   10180             :       std::string stringvar_node<T>::null_value = std::string("");
   10181             : 
   10182             :       template <typename T>
   10183             :       class string_range_node exprtk_final
   10184             :                               : public expression_node <T>
   10185             :                               , public string_base_node<T>
   10186             :                               , public range_interface <T>
   10187             :       {
   10188             :       public:
   10189             : 
   10190             :          typedef typename range_interface<T>::range_t range_t;
   10191             : 
   10192             :          static std::string null_value;
   10193             : 
   10194       22401 :          explicit string_range_node(std::string& v, const range_t& rp)
   10195       22401 :          : value_(&v)
   10196       22401 :          , rp_(rp)
   10197       22401 :          {}
   10198             : 
   10199       44802 :          virtual ~string_range_node()
   10200             :          {
   10201       22401 :             rp_.free();
   10202       44802 :          }
   10203             : 
   10204             :          inline bool operator <(const string_range_node<T>& v) const
   10205             :          {
   10206             :             return this < (&v);
   10207             :          }
   10208             : 
   10209       13429 :          inline T value() const exprtk_override
   10210             :          {
   10211       13429 :             return std::numeric_limits<T>::quiet_NaN();
   10212             :          }
   10213             : 
   10214           0 :          inline std::string str() const exprtk_override
   10215             :          {
   10216           0 :             return (*value_);
   10217             :          }
   10218             : 
   10219       21168 :          char_cptr base() const exprtk_override
   10220             :          {
   10221       21168 :             return &(*value_)[0];
   10222             :          }
   10223             : 
   10224       13456 :          std::size_t size() const exprtk_override
   10225             :          {
   10226       13456 :             return ref().size();
   10227             :          }
   10228             : 
   10229        8960 :          inline range_t range() const
   10230             :          {
   10231        8960 :             return rp_;
   10232             :          }
   10233             : 
   10234        8960 :          inline virtual std::string& ref()
   10235             :          {
   10236        8960 :             return (*value_);
   10237             :          }
   10238             : 
   10239       13456 :          inline virtual const std::string& ref() const
   10240             :          {
   10241       13456 :             return (*value_);
   10242             :          }
   10243             : 
   10244       22416 :          inline range_t& range_ref() exprtk_override
   10245             :          {
   10246       22416 :             return rp_;
   10247             :          }
   10248             : 
   10249           0 :          inline const range_t& range_ref() const exprtk_override
   10250             :          {
   10251           0 :             return rp_;
   10252             :          }
   10253             : 
   10254      440261 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10255             :          {
   10256      440261 :             return expression_node<T>::e_stringvarrng;
   10257             :          }
   10258             : 
   10259             :       private:
   10260             : 
   10261             :          std::string* value_;
   10262             :          range_t      rp_;
   10263             :       };
   10264             : 
   10265             :       template <typename T>
   10266             :       std::string string_range_node<T>::null_value = std::string("");
   10267             : 
   10268             :       template <typename T>
   10269             :       class const_string_range_node exprtk_final
   10270             :                                     : public expression_node <T>
   10271             :                                     , public string_base_node<T>
   10272             :                                     , public range_interface <T>
   10273             :       {
   10274             :       public:
   10275             : 
   10276             :          typedef typename range_interface<T>::range_t range_t;
   10277             : 
   10278        5553 :          explicit const_string_range_node(const std::string& v, const range_t& rp)
   10279        5553 :          : value_(v)
   10280        5553 :          , rp_(rp)
   10281        5553 :          {}
   10282             : 
   10283       11106 :         ~const_string_range_node()
   10284             :          {
   10285        5553 :             rp_.free();
   10286       11106 :          }
   10287             : 
   10288         551 :          inline T value() const exprtk_override
   10289             :          {
   10290         551 :             return std::numeric_limits<T>::quiet_NaN();
   10291             :          }
   10292             : 
   10293        5000 :          std::string str() const exprtk_override
   10294             :          {
   10295        5000 :             return value_;
   10296             :          }
   10297             : 
   10298         551 :          char_cptr base() const exprtk_override
   10299             :          {
   10300         551 :             return value_.data();
   10301             :          }
   10302             : 
   10303         551 :          std::size_t size() const exprtk_override
   10304             :          {
   10305         551 :             return value_.size();
   10306             :          }
   10307             : 
   10308        5000 :          range_t range() const
   10309             :          {
   10310        5000 :             return rp_;
   10311             :          }
   10312             : 
   10313        5551 :          range_t& range_ref() exprtk_override
   10314             :          {
   10315        5551 :             return rp_;
   10316             :          }
   10317             : 
   10318           0 :          const range_t& range_ref() const exprtk_override
   10319             :          {
   10320           0 :             return rp_;
   10321             :          }
   10322             : 
   10323      110965 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10324             :          {
   10325      110965 :             return expression_node<T>::e_cstringvarrng;
   10326             :          }
   10327             : 
   10328             :       private:
   10329             : 
   10330             :          const_string_range_node(const const_string_range_node<T>&) exprtk_delete;
   10331             :          const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete;
   10332             : 
   10333             :          const std::string value_;
   10334             :          range_t rp_;
   10335             :       };
   10336             : 
   10337             :       template <typename T>
   10338             :       class generic_string_range_node exprtk_final
   10339             :                                       : public expression_node <T>
   10340             :                                       , public string_base_node<T>
   10341             :                                       , public range_interface <T>
   10342             :       {
   10343             :       public:
   10344             : 
   10345             :          typedef expression_node <T>* expression_ptr;
   10346             :          typedef stringvar_node  <T>* strvar_node_ptr;
   10347             :          typedef string_base_node<T>* str_base_ptr;
   10348             :          typedef typename range_interface<T>::range_t range_t;
   10349             :          typedef range_t*             range_ptr;
   10350             :          typedef range_interface<T>   irange_t;
   10351             :          typedef irange_t*            irange_ptr;
   10352             :          typedef std::pair<expression_ptr,bool>  branch_t;
   10353             : 
   10354        4102 :          generic_string_range_node(expression_ptr str_branch, const range_t& brange)
   10355        4102 :          : initialised_(false)
   10356        4102 :          , str_base_ptr_ (0)
   10357        4102 :          , str_range_ptr_(0)
   10358        4102 :          , base_range_(brange)
   10359             :          {
   10360        4102 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   10361        4102 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   10362        4102 :             range_.cache.first  = range_.n0_c.second;
   10363        4102 :             range_.cache.second = range_.n1_c.second;
   10364             : 
   10365        4102 :             construct_branch_pair(branch_, str_branch);
   10366             : 
   10367        4102 :             if (is_generally_string_node(branch_.first))
   10368             :             {
   10369        4102 :                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
   10370             : 
   10371        4102 :                if (0 == str_base_ptr_)
   10372           0 :                   return;
   10373             : 
   10374        4102 :                str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
   10375             : 
   10376        4102 :                if (0 == str_range_ptr_)
   10377           0 :                   return;
   10378             :             }
   10379             : 
   10380        4102 :             initialised_ = (str_base_ptr_ && str_range_ptr_);
   10381        4102 :             assert(valid());
   10382           0 :          }
   10383             : 
   10384        8204 :         ~generic_string_range_node()
   10385             :          {
   10386        4102 :             base_range_.free();
   10387        8204 :          }
   10388             : 
   10389        4100 :          inline T value() const exprtk_override
   10390             :          {
   10391        4100 :             branch_.first->value();
   10392             : 
   10393        4100 :             std::size_t str_r0 = 0;
   10394        4100 :             std::size_t str_r1 = 0;
   10395             : 
   10396        4100 :             std::size_t r0 = 0;
   10397        4100 :             std::size_t r1 = 0;
   10398             : 
   10399        4100 :             const range_t& range = str_range_ptr_->range_ref();
   10400             : 
   10401        4100 :             const std::size_t base_str_size = str_base_ptr_->size();
   10402             : 
   10403        4100 :             if (
   10404        8200 :                   range      (str_r0, str_r1, base_str_size         ) &&
   10405        8200 :                   base_range_(r0    , r1    , base_str_size - str_r0)
   10406             :                )
   10407             :             {
   10408        4100 :                const std::size_t size = r1 - r0;
   10409             : 
   10410        4100 :                range_.n1_c.second  = size;
   10411        4100 :                range_.cache.second = range_.n1_c.second;
   10412             : 
   10413        4100 :                value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
   10414             :             }
   10415             : 
   10416        8200 :             return std::numeric_limits<T>::quiet_NaN();
   10417             :          }
   10418             : 
   10419        1300 :          std::string str() const exprtk_override
   10420             :          {
   10421        1300 :             return value_;
   10422             :          }
   10423             : 
   10424        2250 :          char_cptr base() const exprtk_override
   10425             :          {
   10426        2250 :             return &value_[0];
   10427             :          }
   10428             : 
   10429        4100 :          std::size_t size() const exprtk_override
   10430             :          {
   10431        4100 :             return value_.size();
   10432             :          }
   10433             : 
   10434        3550 :          range_t& range_ref() exprtk_override
   10435             :          {
   10436        3550 :             return range_;
   10437             :          }
   10438             : 
   10439           0 :          const range_t& range_ref() const exprtk_override
   10440             :          {
   10441           0 :             return range_;
   10442             :          }
   10443             : 
   10444       35556 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10445             :          {
   10446       35556 :             return expression_node<T>::e_strgenrange;
   10447             :          }
   10448             : 
   10449        9504 :          inline bool valid() const exprtk_override
   10450             :          {
   10451        9504 :             return initialised_ && branch_.first;
   10452             :          }
   10453             : 
   10454        4102 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   10455             :          {
   10456        4102 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   10457        4102 :          }
   10458             : 
   10459        8202 :          std::size_t node_depth() const exprtk_override
   10460             :          {
   10461        8202 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   10462             :          }
   10463             : 
   10464             :       private:
   10465             : 
   10466             :          bool                initialised_;
   10467             :          branch_t            branch_;
   10468             :          str_base_ptr        str_base_ptr_;
   10469             :          irange_ptr          str_range_ptr_;
   10470             :          mutable range_t     base_range_;
   10471             :          mutable range_t     range_;
   10472             :          mutable std::string value_;
   10473             :       };
   10474             : 
   10475             :       template <typename T>
   10476             :       class string_concat_node exprtk_final
   10477             :                                : public binary_node     <T>
   10478             :                                , public string_base_node<T>
   10479             :                                , public range_interface <T>
   10480             :       {
   10481             :       public:
   10482             : 
   10483             :          typedef typename range_interface<T>::range_t range_t;
   10484             :          typedef range_interface<T>   irange_t;
   10485             :          typedef irange_t*            irange_ptr;
   10486             :          typedef range_t*             range_ptr;
   10487             :          typedef expression_node <T>* expression_ptr;
   10488             :          typedef string_base_node<T>* str_base_ptr;
   10489             : 
   10490             :          using binary_node<T>::branch;
   10491             : 
   10492        5172 :          string_concat_node(const operator_type& opr,
   10493             :                             expression_ptr branch0,
   10494             :                             expression_ptr branch1)
   10495             :          : binary_node<T>(opr, branch0, branch1)
   10496        5172 :          , initialised_(false)
   10497        5172 :          , str0_base_ptr_ (0)
   10498        5172 :          , str1_base_ptr_ (0)
   10499        5172 :          , str0_range_ptr_(0)
   10500        5172 :          , str1_range_ptr_(0)
   10501             :          {
   10502        5172 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   10503        5172 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   10504             : 
   10505        5172 :             range_.cache.first  = range_.n0_c.second;
   10506        5172 :             range_.cache.second = range_.n1_c.second;
   10507             : 
   10508        5172 :             if (is_generally_string_node(branch(0)))
   10509             :             {
   10510        5172 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   10511             : 
   10512        5172 :                if (0 == str0_base_ptr_)
   10513           0 :                   return;
   10514             : 
   10515        5172 :                str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
   10516             : 
   10517        5172 :                if (0 == str0_range_ptr_)
   10518           0 :                   return;
   10519             :             }
   10520             : 
   10521        5172 :             if (is_generally_string_node(branch(1)))
   10522             :             {
   10523        5172 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   10524             : 
   10525        5172 :                if (0 == str1_base_ptr_)
   10526           0 :                   return;
   10527             : 
   10528        5172 :                str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1));
   10529             : 
   10530        5172 :                if (0 == str1_range_ptr_)
   10531           0 :                   return;
   10532             :             }
   10533             : 
   10534       15516 :             initialised_ = str0_base_ptr_  &&
   10535        5172 :                            str1_base_ptr_  &&
   10536       15516 :                            str0_range_ptr_ &&
   10537        5172 :                            str1_range_ptr_ ;
   10538             : 
   10539        5172 :             assert(valid());
   10540           0 :          }
   10541             : 
   10542        6115 :          inline T value() const exprtk_override
   10543             :          {
   10544        6115 :             branch(0)->value();
   10545        6115 :             branch(1)->value();
   10546             : 
   10547        6115 :             std::size_t str0_r0 = 0;
   10548        6115 :             std::size_t str0_r1 = 0;
   10549             : 
   10550        6115 :             std::size_t str1_r0 = 0;
   10551        6115 :             std::size_t str1_r1 = 0;
   10552             : 
   10553        6115 :             const range_t& range0 = str0_range_ptr_->range_ref();
   10554        6115 :             const range_t& range1 = str1_range_ptr_->range_ref();
   10555             : 
   10556        6115 :             if (
   10557       12230 :                   range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
   10558       12230 :                   range1(str1_r0, str1_r1, str1_base_ptr_->size())
   10559             :                )
   10560             :             {
   10561        6115 :                const std::size_t size0 = (str0_r1 - str0_r0);
   10562        6115 :                const std::size_t size1 = (str1_r1 - str1_r0);
   10563             : 
   10564        6115 :                value_.assign(str0_base_ptr_->base() + str0_r0, size0);
   10565        6115 :                value_.append(str1_base_ptr_->base() + str1_r0, size1);
   10566             : 
   10567        6115 :                range_.n1_c.second  = value_.size();
   10568        6115 :                range_.cache.second = range_.n1_c.second;
   10569             :             }
   10570             : 
   10571       12230 :             return std::numeric_limits<T>::quiet_NaN();
   10572             :          }
   10573             : 
   10574        2696 :          std::string str() const exprtk_override
   10575             :          {
   10576        2696 :             return value_;
   10577             :          }
   10578             : 
   10579        3484 :          char_cptr base() const exprtk_override
   10580             :          {
   10581        3484 :             return &value_[0];
   10582             :          }
   10583             : 
   10584        6180 :          std::size_t size() const exprtk_override
   10585             :          {
   10586        6180 :             return value_.size();
   10587             :          }
   10588             : 
   10589        5181 :          range_t& range_ref() exprtk_override
   10590             :          {
   10591        5181 :             return range_;
   10592             :          }
   10593             : 
   10594           0 :          const range_t& range_ref() const exprtk_override
   10595             :          {
   10596           0 :             return range_;
   10597             :          }
   10598             : 
   10599       76214 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10600             :          {
   10601       76214 :             return expression_node<T>::e_strconcat;
   10602             :          }
   10603             : 
   10604       17073 :          inline bool valid() const exprtk_override
   10605             :          {
   10606       17073 :             return initialised_ && binary_node<T>::valid();
   10607             :          }
   10608             : 
   10609             :       private:
   10610             : 
   10611             :          bool                initialised_;
   10612             :          str_base_ptr        str0_base_ptr_;
   10613             :          str_base_ptr        str1_base_ptr_;
   10614             :          irange_ptr          str0_range_ptr_;
   10615             :          irange_ptr          str1_range_ptr_;
   10616             :          mutable range_t     range_;
   10617             :          mutable std::string value_;
   10618             :       };
   10619             : 
   10620             :       template <typename T>
   10621             :       class swap_string_node exprtk_final
   10622             :                              : public binary_node     <T>
   10623             :                              , public string_base_node<T>
   10624             :                              , public range_interface <T>
   10625             :       {
   10626             :       public:
   10627             : 
   10628             :          typedef typename range_interface<T>::range_t range_t;
   10629             :          typedef range_t*             range_ptr;
   10630             :          typedef range_interface<T>   irange_t;
   10631             :          typedef irange_t*            irange_ptr;
   10632             :          typedef expression_node <T>* expression_ptr;
   10633             :          typedef stringvar_node  <T>* strvar_node_ptr;
   10634             :          typedef string_base_node<T>* str_base_ptr;
   10635             : 
   10636             :          using binary_node<T>::branch;
   10637             : 
   10638           0 :          swap_string_node(expression_ptr branch0, expression_ptr branch1)
   10639           0 :          : binary_node<T>(details::e_swap, branch0, branch1)
   10640           0 :          , initialised_(false)
   10641           0 :          , str0_node_ptr_(0)
   10642           0 :          , str1_node_ptr_(0)
   10643             :          {
   10644           0 :             if (is_string_node(branch(0)))
   10645             :             {
   10646           0 :                str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
   10647             :             }
   10648             : 
   10649           0 :             if (is_string_node(branch(1)))
   10650             :             {
   10651           0 :                str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1));
   10652             :             }
   10653             : 
   10654           0 :             initialised_ = (str0_node_ptr_ && str1_node_ptr_);
   10655           0 :             assert(valid());
   10656           0 :          }
   10657             : 
   10658           0 :          inline T value() const exprtk_override
   10659             :          {
   10660           0 :             branch(0)->value();
   10661           0 :             branch(1)->value();
   10662             : 
   10663           0 :             std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
   10664             : 
   10665           0 :             return std::numeric_limits<T>::quiet_NaN();
   10666             :          }
   10667             : 
   10668           0 :          std::string str() const exprtk_override
   10669             :          {
   10670           0 :             return str0_node_ptr_->str();
   10671             :          }
   10672             : 
   10673           0 :          char_cptr base() const exprtk_override
   10674             :          {
   10675           0 :            return str0_node_ptr_->base();
   10676             :          }
   10677             : 
   10678           0 :          std::size_t size() const exprtk_override
   10679             :          {
   10680           0 :             return str0_node_ptr_->size();
   10681             :          }
   10682             : 
   10683           0 :          range_t& range_ref() exprtk_override
   10684             :          {
   10685           0 :             return str0_node_ptr_->range_ref();
   10686             :          }
   10687             : 
   10688           0 :          const range_t& range_ref() const exprtk_override
   10689             :          {
   10690           0 :             return str0_node_ptr_->range_ref();
   10691             :          }
   10692             : 
   10693           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10694             :          {
   10695           0 :             return expression_node<T>::e_strswap;
   10696             :          }
   10697             : 
   10698           0 :          inline bool valid() const exprtk_override
   10699             :          {
   10700           0 :             return initialised_ && binary_node<T>::valid();
   10701             :          }
   10702             : 
   10703             :       private:
   10704             : 
   10705             :          bool initialised_;
   10706             :          strvar_node_ptr str0_node_ptr_;
   10707             :          strvar_node_ptr str1_node_ptr_;
   10708             :       };
   10709             : 
   10710             :       template <typename T>
   10711             :       class swap_genstrings_node exprtk_final : public binary_node<T>
   10712             :       {
   10713             :       public:
   10714             : 
   10715             :          typedef typename range_interface<T>::range_t range_t;
   10716             :          typedef range_t*             range_ptr;
   10717             :          typedef range_interface<T>   irange_t;
   10718             :          typedef irange_t*            irange_ptr;
   10719             :          typedef expression_node <T>* expression_ptr;
   10720             :          typedef string_base_node<T>* str_base_ptr;
   10721             : 
   10722             :          using binary_node<T>::branch;
   10723             : 
   10724        1500 :          swap_genstrings_node(expression_ptr branch0,
   10725             :                               expression_ptr branch1)
   10726           0 :          : binary_node<T>(details::e_default, branch0, branch1)
   10727        1500 :          , str0_base_ptr_ (0)
   10728        1500 :          , str1_base_ptr_ (0)
   10729        1500 :          , str0_range_ptr_(0)
   10730        1500 :          , str1_range_ptr_(0)
   10731        1500 :          , initialised_(false)
   10732             :          {
   10733        1500 :             if (is_generally_string_node(branch(0)))
   10734             :             {
   10735        1500 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   10736             : 
   10737        1500 :                if (0 == str0_base_ptr_)
   10738           0 :                   return;
   10739             : 
   10740        1500 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
   10741             : 
   10742        1500 :                if (0 == range)
   10743           0 :                   return;
   10744             : 
   10745        1500 :                str0_range_ptr_ = &(range->range_ref());
   10746             :             }
   10747             : 
   10748        1500 :             if (is_generally_string_node(branch(1)))
   10749             :             {
   10750        1500 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   10751             : 
   10752        1500 :                if (0 == str1_base_ptr_)
   10753           0 :                   return;
   10754             : 
   10755        1500 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   10756             : 
   10757        1500 :                if (0 == range)
   10758           0 :                   return;
   10759             : 
   10760        1500 :                str1_range_ptr_ = &(range->range_ref());
   10761             :             }
   10762             : 
   10763        4500 :             initialised_ = str0_base_ptr_  &&
   10764        1500 :                            str1_base_ptr_  &&
   10765        4500 :                            str0_range_ptr_ &&
   10766        1500 :                            str1_range_ptr_ ;
   10767             : 
   10768        1500 :             assert(valid());
   10769           0 :          }
   10770             : 
   10771        1500 :          inline T value() const exprtk_override
   10772             :          {
   10773        1500 :             branch(0)->value();
   10774        1500 :             branch(1)->value();
   10775             : 
   10776        1500 :             std::size_t str0_r0 = 0;
   10777        1500 :             std::size_t str0_r1 = 0;
   10778             : 
   10779        1500 :             std::size_t str1_r0 = 0;
   10780        1500 :             std::size_t str1_r1 = 0;
   10781             : 
   10782        1500 :             const range_t& range0 = (*str0_range_ptr_);
   10783        1500 :             const range_t& range1 = (*str1_range_ptr_);
   10784             : 
   10785        1500 :             if (
   10786        3000 :                   range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
   10787        3000 :                   range1(str1_r0, str1_r1, str1_base_ptr_->size())
   10788             :                )
   10789             :             {
   10790        1500 :                const std::size_t size0    = range0.cache_size();
   10791        1500 :                const std::size_t size1    = range1.cache_size();
   10792        1500 :                const std::size_t max_size = std::min(size0,size1);
   10793             : 
   10794        1500 :                char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
   10795        1500 :                char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
   10796             : 
   10797        1500 :                loop_unroll::details lud(max_size);
   10798        1500 :                char_cptr upper_bound = s0 + lud.upper_bound;
   10799             : 
   10800        1500 :                while (s0 < upper_bound)
   10801             :                {
   10802             :                   #define exprtk_loop(N)   \
   10803             :                   std::swap(s0[N], s1[N]); \
   10804             : 
   10805           0 :                   exprtk_loop( 0) exprtk_loop( 1)
   10806           0 :                   exprtk_loop( 2) exprtk_loop( 3)
   10807             :                   #ifndef exprtk_disable_superscalar_unroll
   10808           0 :                   exprtk_loop( 4) exprtk_loop( 5)
   10809           0 :                   exprtk_loop( 6) exprtk_loop( 7)
   10810           0 :                   exprtk_loop( 8) exprtk_loop( 9)
   10811           0 :                   exprtk_loop(10) exprtk_loop(11)
   10812           0 :                   exprtk_loop(12) exprtk_loop(13)
   10813           0 :                   exprtk_loop(14) exprtk_loop(15)
   10814             :                   #endif
   10815             : 
   10816           0 :                   s0 += lud.batch_size;
   10817           0 :                   s1 += lud.batch_size;
   10818             :                }
   10819             : 
   10820        1500 :                int i = 0;
   10821             : 
   10822        1500 :                switch (lud.remainder)
   10823             :                {
   10824             :                   #define case_stmt(N)                       \
   10825             :                   case N : { std::swap(s0[i], s1[i]); ++i; } \
   10826             :                   exprtk_fallthrough                         \
   10827             : 
   10828             :                   #ifndef exprtk_disable_superscalar_unroll
   10829           0 :                   case_stmt(15) case_stmt(14)
   10830           0 :                   case_stmt(13) case_stmt(12)
   10831           0 :                   case_stmt(11) case_stmt(10)
   10832           0 :                   case_stmt( 9) case_stmt( 8)
   10833           0 :                   case_stmt( 7) case_stmt( 6)
   10834         600 :                   case_stmt( 5) case_stmt( 4)
   10835             :                   #endif
   10836        1200 :                   case_stmt( 3) case_stmt( 2)
   10837        1500 :                   case_stmt( 1)
   10838        1500 :                   default: break;
   10839             :                }
   10840             : 
   10841             :                #undef exprtk_loop
   10842             :                #undef case_stmt
   10843             :             }
   10844             : 
   10845        3000 :             return std::numeric_limits<T>::quiet_NaN();
   10846             :          }
   10847             : 
   10848       18000 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10849             :          {
   10850       18000 :             return expression_node<T>::e_strswap;
   10851             :          }
   10852             : 
   10853        4500 :          inline bool valid() const exprtk_override
   10854             :          {
   10855        4500 :             return initialised_ && binary_node<T>::valid();
   10856             :          }
   10857             : 
   10858             :       private:
   10859             : 
   10860             :          swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete;
   10861             :          swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete;
   10862             : 
   10863             :          str_base_ptr str0_base_ptr_;
   10864             :          str_base_ptr str1_base_ptr_;
   10865             :          range_ptr    str0_range_ptr_;
   10866             :          range_ptr    str1_range_ptr_;
   10867             :          bool         initialised_;
   10868             :       };
   10869             : 
   10870             :       template <typename T>
   10871             :       class stringvar_size_node exprtk_final : public expression_node<T>
   10872             :       {
   10873             :       public:
   10874             : 
   10875             :          static const std::string null_value;
   10876             : 
   10877             :          explicit stringvar_size_node()
   10878             :          : value_(&null_value)
   10879             :          {}
   10880             : 
   10881        3800 :          explicit stringvar_size_node(std::string& v)
   10882        3800 :          : value_(&v)
   10883        3800 :          {}
   10884             : 
   10885        3800 :          inline T value() const exprtk_override
   10886             :          {
   10887        3800 :             return T((*value_).size());
   10888             :          }
   10889             : 
   10890       80140 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10891             :          {
   10892       80140 :             return expression_node<T>::e_stringvarsize;
   10893             :          }
   10894             : 
   10895             :       private:
   10896             : 
   10897             :          const std::string* value_;
   10898             :       };
   10899             : 
   10900             :       template <typename T>
   10901             :       const std::string stringvar_size_node<T>::null_value = std::string("");
   10902             : 
   10903             :       template <typename T>
   10904             :       class string_size_node exprtk_final : public expression_node<T>
   10905             :       {
   10906             :       public:
   10907             : 
   10908             :          typedef expression_node <T>* expression_ptr;
   10909             :          typedef string_base_node<T>* str_base_ptr;
   10910             :          typedef std::pair<expression_ptr,bool>  branch_t;
   10911             : 
   10912         750 :          explicit string_size_node(expression_ptr branch)
   10913         750 :          : str_base_ptr_(0)
   10914             :          {
   10915         750 :             construct_branch_pair(branch_, branch);
   10916             : 
   10917         750 :             if (is_generally_string_node(branch_.first))
   10918             :             {
   10919         750 :                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
   10920             :             }
   10921             : 
   10922         750 :             assert(valid());
   10923         750 :          }
   10924             : 
   10925         750 :          inline T value() const exprtk_override
   10926             :          {
   10927         750 :             branch_.first->value();
   10928         750 :             return T(str_base_ptr_->size());
   10929             :          }
   10930             : 
   10931       23250 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10932             :          {
   10933       23250 :             return expression_node<T>::e_stringsize;
   10934             :          }
   10935             : 
   10936        1500 :          inline bool valid() const exprtk_override
   10937             :          {
   10938        1500 :             return str_base_ptr_;
   10939             :          }
   10940             : 
   10941         750 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   10942             :          {
   10943         750 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   10944         750 :          }
   10945             : 
   10946        1500 :          std::size_t node_depth() const exprtk_override
   10947             :          {
   10948        1500 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   10949             :          }
   10950             : 
   10951             :       private:
   10952             : 
   10953             :          branch_t     branch_;
   10954             :          str_base_ptr str_base_ptr_;
   10955             :       };
   10956             : 
   10957             :       struct asn_assignment
   10958             :       {
   10959       12990 :          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
   10960       12990 :          { s.assign(data,size); }
   10961             :       };
   10962             : 
   10963             :       struct asn_addassignment
   10964             :       {
   10965        6700 :          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
   10966        6700 :          { s.append(data,size); }
   10967             :       };
   10968             : 
   10969             :       template <typename T, typename AssignmentProcess = asn_assignment>
   10970             :       class assignment_string_node exprtk_final
   10971             :                                    : public binary_node     <T>
   10972             :                                    , public string_base_node<T>
   10973             :                                    , public range_interface <T>
   10974             :       {
   10975             :       public:
   10976             : 
   10977             :          typedef typename range_interface<T>::range_t range_t;
   10978             :          typedef range_t*             range_ptr;
   10979             :          typedef range_interface <T>  irange_t;
   10980             :          typedef irange_t*            irange_ptr;
   10981             :          typedef expression_node <T>* expression_ptr;
   10982             :          typedef stringvar_node  <T>* strvar_node_ptr;
   10983             :          typedef string_base_node<T>* str_base_ptr;
   10984             : 
   10985             :          using binary_node<T>::branch;
   10986             : 
   10987       14591 :          assignment_string_node(const operator_type& opr,
   10988             :                                 expression_ptr branch0,
   10989             :                                 expression_ptr branch1)
   10990             :          : binary_node<T>(opr, branch0, branch1)
   10991       14591 :          , initialised_(false)
   10992       14591 :          , str0_base_ptr_ (0)
   10993       14591 :          , str1_base_ptr_ (0)
   10994       14591 :          , str0_node_ptr_ (0)
   10995       14591 :          , str1_range_ptr_(0)
   10996             :          {
   10997       14591 :             if (is_string_node(branch(0)))
   10998             :             {
   10999       14591 :                str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
   11000       14591 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   11001             :             }
   11002             : 
   11003       14591 :             if (is_generally_string_node(branch(1)))
   11004             :             {
   11005       14591 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   11006             : 
   11007       14591 :                if (0 == str1_base_ptr_)
   11008           0 :                   return;
   11009             : 
   11010       14591 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   11011             : 
   11012       14591 :                if (0 == range)
   11013           0 :                   return;
   11014             : 
   11015       14591 :                str1_range_ptr_ = &(range->range_ref());
   11016             :             }
   11017             : 
   11018       43773 :             initialised_ = str0_base_ptr_  &&
   11019       14591 :                            str1_base_ptr_  &&
   11020       43773 :                            str0_node_ptr_  &&
   11021       14591 :                            str1_range_ptr_ ;
   11022             : 
   11023       14591 :             assert(valid());
   11024           0 :          }
   11025             : 
   11026       19690 :          inline T value() const exprtk_override
   11027             :          {
   11028       19690 :             branch(1)->value();
   11029             : 
   11030       19690 :             std::size_t r0 = 0;
   11031       19690 :             std::size_t r1 = 0;
   11032             : 
   11033       19690 :             const range_t& range = (*str1_range_ptr_);
   11034             : 
   11035       19690 :             if (range(r0, r1, str1_base_ptr_->size()))
   11036             :             {
   11037       19690 :                AssignmentProcess::execute(
   11038       19690 :                   str0_node_ptr_->ref(),
   11039       19690 :                   str1_base_ptr_->base() + r0, (r1 - r0));
   11040             : 
   11041       19690 :                branch(0)->value();
   11042             :             }
   11043             : 
   11044       39380 :             return std::numeric_limits<T>::quiet_NaN();
   11045             :          }
   11046             : 
   11047         300 :          std::string str() const exprtk_override
   11048             :          {
   11049         300 :             return str0_node_ptr_->str();
   11050             :          }
   11051             : 
   11052         201 :          char_cptr base() const exprtk_override
   11053             :          {
   11054         201 :            return str0_node_ptr_->base();
   11055             :          }
   11056             : 
   11057         701 :          std::size_t size() const exprtk_override
   11058             :          {
   11059         701 :             return str0_node_ptr_->size();
   11060             :          }
   11061             : 
   11062         501 :          range_t& range_ref() exprtk_override
   11063             :          {
   11064         501 :             return str0_node_ptr_->range_ref();
   11065             :          }
   11066             : 
   11067           0 :          const range_t& range_ref() const exprtk_override
   11068             :          {
   11069           0 :             return str0_node_ptr_->range_ref();
   11070             :          }
   11071             : 
   11072      174562 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11073             :          {
   11074      174562 :             return expression_node<T>::e_strass;
   11075             :          }
   11076             : 
   11077       44640 :          inline bool valid() const exprtk_override
   11078             :          {
   11079       44640 :             return initialised_ && binary_node<T>::valid();
   11080             :          }
   11081             : 
   11082             :       private:
   11083             : 
   11084             :          bool            initialised_;
   11085             :          str_base_ptr    str0_base_ptr_;
   11086             :          str_base_ptr    str1_base_ptr_;
   11087             :          strvar_node_ptr str0_node_ptr_;
   11088             :          range_ptr       str1_range_ptr_;
   11089             :       };
   11090             : 
   11091             :       template <typename T, typename AssignmentProcess = asn_assignment>
   11092             :       class assignment_string_range_node exprtk_final
   11093             :                                          : public binary_node     <T>
   11094             :                                          , public string_base_node<T>
   11095             :                                          , public range_interface <T>
   11096             :       {
   11097             :       public:
   11098             : 
   11099             :          typedef typename range_interface<T>::range_t range_t;
   11100             :          typedef range_t*              range_ptr;
   11101             :          typedef range_interface  <T>  irange_t;
   11102             :          typedef irange_t*             irange_ptr;
   11103             :          typedef expression_node  <T>* expression_ptr;
   11104             :          typedef stringvar_node   <T>* strvar_node_ptr;
   11105             :          typedef string_range_node<T>* str_rng_node_ptr;
   11106             :          typedef string_base_node <T>* str_base_ptr;
   11107             : 
   11108             :          using binary_node<T>::branch;
   11109             : 
   11110        4850 :          assignment_string_range_node(const operator_type& opr,
   11111             :                                       expression_ptr branch0,
   11112             :                                       expression_ptr branch1)
   11113             :          : binary_node<T>(opr, branch0, branch1)
   11114        4850 :          , initialised_(false)
   11115        4850 :          , str0_base_ptr_    (0)
   11116        4850 :          , str1_base_ptr_    (0)
   11117        4850 :          , str0_rng_node_ptr_(0)
   11118        4850 :          , str0_range_ptr_   (0)
   11119        4850 :          , str1_range_ptr_   (0)
   11120             :          {
   11121        4850 :             if (is_string_range_node(branch(0)))
   11122             :             {
   11123        4850 :                str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0));
   11124        4850 :                str0_base_ptr_     = dynamic_cast<str_base_ptr>(branch(0));
   11125        4850 :                irange_ptr range   = dynamic_cast<irange_ptr>(branch(0));
   11126             : 
   11127        4850 :                if (0 == range)
   11128           0 :                   return;
   11129             : 
   11130        4850 :                str0_range_ptr_ = &(range->range_ref());
   11131             :             }
   11132             : 
   11133        4850 :             if (is_generally_string_node(branch(1)))
   11134             :             {
   11135        4850 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   11136             : 
   11137        4850 :                if (0 == str1_base_ptr_)
   11138           0 :                   return;
   11139             : 
   11140        4850 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   11141             : 
   11142        4850 :                if (0 == range)
   11143           0 :                   return;
   11144             : 
   11145        4850 :                str1_range_ptr_ = &(range->range_ref());
   11146             :             }
   11147             : 
   11148       14550 :             initialised_ = str0_base_ptr_     &&
   11149        4850 :                            str1_base_ptr_     &&
   11150        4850 :                            str0_rng_node_ptr_ &&
   11151       14550 :                            str0_range_ptr_    &&
   11152        4850 :                            str1_range_ptr_    ;
   11153             : 
   11154        4850 :             assert(valid());
   11155           0 :          }
   11156             : 
   11157        4850 :          inline T value() const exprtk_override
   11158             :          {
   11159        4850 :             branch(0)->value();
   11160        4850 :             branch(1)->value();
   11161             : 
   11162        4850 :             std::size_t s0_r0 = 0;
   11163        4850 :             std::size_t s0_r1 = 0;
   11164             : 
   11165        4850 :             std::size_t s1_r0 = 0;
   11166        4850 :             std::size_t s1_r1 = 0;
   11167             : 
   11168        4850 :             const range_t& range0 = (*str0_range_ptr_);
   11169        4850 :             const range_t& range1 = (*str1_range_ptr_);
   11170             : 
   11171        4850 :             if (
   11172        9700 :                   range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
   11173        9700 :                   range1(s1_r0, s1_r1, str1_base_ptr_->size())
   11174             :                )
   11175             :             {
   11176        4850 :                const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0));
   11177             : 
   11178        9700 :                std::copy(
   11179        4850 :                   str1_base_ptr_->base() + s1_r0,
   11180        4850 :                   str1_base_ptr_->base() + s1_r0 + size,
   11181        4850 :                   const_cast<char_ptr>(base() + s0_r0));
   11182             :             }
   11183             : 
   11184        9700 :             return std::numeric_limits<T>::quiet_NaN();
   11185             :          }
   11186             : 
   11187           0 :          std::string str() const exprtk_override
   11188             :          {
   11189           0 :             return str0_base_ptr_->str();
   11190             :          }
   11191             : 
   11192        4850 :          char_cptr base() const exprtk_override
   11193             :          {
   11194        4850 :             return str0_base_ptr_->base();
   11195             :          }
   11196             : 
   11197           0 :          std::size_t size() const exprtk_override
   11198             :          {
   11199           0 :             return str0_base_ptr_->size();
   11200             :          }
   11201             : 
   11202           0 :          range_t& range_ref() exprtk_override
   11203             :          {
   11204           0 :             return str0_rng_node_ptr_->range_ref();
   11205             :          }
   11206             : 
   11207           0 :          const range_t& range_ref() const exprtk_override
   11208             :          {
   11209           0 :             return str0_rng_node_ptr_->range_ref();
   11210             :          }
   11211             : 
   11212       78300 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11213             :          {
   11214       78300 :             return expression_node<T>::e_strass;
   11215             :          }
   11216             : 
   11217       14550 :          inline bool valid() const exprtk_override
   11218             :          {
   11219       14550 :             return initialised_ && binary_node<T>::valid();
   11220             :          }
   11221             : 
   11222             :       private:
   11223             : 
   11224             :          bool             initialised_;
   11225             :          str_base_ptr     str0_base_ptr_;
   11226             :          str_base_ptr     str1_base_ptr_;
   11227             :          str_rng_node_ptr str0_rng_node_ptr_;
   11228             :          range_ptr        str0_range_ptr_;
   11229             :          range_ptr        str1_range_ptr_;
   11230             :       };
   11231             : 
   11232             :       template <typename T>
   11233             :       class conditional_string_node exprtk_final
   11234             :                                     : public trinary_node    <T>
   11235             :                                     , public string_base_node<T>
   11236             :                                     , public range_interface <T>
   11237             :       {
   11238             :       public:
   11239             : 
   11240             :          typedef typename range_interface<T>::range_t range_t;
   11241             :          typedef range_t*             range_ptr;
   11242             :          typedef range_interface <T>  irange_t;
   11243             :          typedef irange_t*            irange_ptr;
   11244             :          typedef expression_node <T>* expression_ptr;
   11245             :          typedef string_base_node<T>* str_base_ptr;
   11246             : 
   11247        1151 :          conditional_string_node(expression_ptr condition,
   11248             :                                  expression_ptr consequent,
   11249             :                                  expression_ptr alternative)
   11250           0 :          : trinary_node<T>(details::e_default, consequent, alternative, condition)
   11251        1151 :          , initialised_(false)
   11252        1151 :          , str0_base_ptr_ (0)
   11253        1151 :          , str1_base_ptr_ (0)
   11254        1151 :          , str0_range_ptr_(0)
   11255        1151 :          , str1_range_ptr_(0)
   11256        1151 :          , condition_  (condition  )
   11257        1151 :          , consequent_ (consequent )
   11258        1151 :          , alternative_(alternative)
   11259             :          {
   11260        1151 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   11261        1151 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   11262             : 
   11263        1151 :             range_.cache.first  = range_.n0_c.second;
   11264        1151 :             range_.cache.second = range_.n1_c.second;
   11265             : 
   11266        1151 :             if (is_generally_string_node(trinary_node<T>::branch_[0].first))
   11267             :             {
   11268        1151 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
   11269             : 
   11270        1151 :                if (0 == str0_base_ptr_)
   11271           0 :                   return;
   11272             : 
   11273        1151 :                str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
   11274             : 
   11275        1151 :                if (0 == str0_range_ptr_)
   11276           0 :                   return;
   11277             :             }
   11278             : 
   11279        1151 :             if (is_generally_string_node(trinary_node<T>::branch_[1].first))
   11280             :             {
   11281        1151 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
   11282             : 
   11283        1151 :                if (0 == str1_base_ptr_)
   11284           0 :                   return;
   11285             : 
   11286        1151 :                str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
   11287             : 
   11288        1151 :                if (0 == str1_range_ptr_)
   11289           0 :                   return;
   11290             :             }
   11291             : 
   11292        3453 :             initialised_ = str0_base_ptr_  &&
   11293        1151 :                            str1_base_ptr_  &&
   11294        3453 :                            str0_range_ptr_ &&
   11295        1151 :                            str1_range_ptr_ ;
   11296             : 
   11297        1151 :             assert(valid());
   11298           0 :          }
   11299             : 
   11300        1146 :          inline T value() const exprtk_override
   11301             :          {
   11302        1146 :             std::size_t r0 = 0;
   11303        1146 :             std::size_t r1 = 0;
   11304             : 
   11305        1146 :             if (is_true(condition_))
   11306             :             {
   11307         581 :                consequent_->value();
   11308             : 
   11309         581 :                const range_t& range = str0_range_ptr_->range_ref();
   11310             : 
   11311         581 :                if (range(r0, r1, str0_base_ptr_->size()))
   11312             :                {
   11313         581 :                   const std::size_t size = (r1 - r0);
   11314             : 
   11315         581 :                   value_.assign(str0_base_ptr_->base() + r0, size);
   11316             : 
   11317         581 :                   range_.n1_c.second  = value_.size();
   11318         581 :                   range_.cache.second = range_.n1_c.second;
   11319             : 
   11320         581 :                   return T(1);
   11321             :                }
   11322             :             }
   11323             :             else
   11324             :             {
   11325         565 :                alternative_->value();
   11326             : 
   11327         565 :                const range_t& range = str1_range_ptr_->range_ref();
   11328             : 
   11329         565 :                if (range(r0, r1, str1_base_ptr_->size()))
   11330             :                {
   11331         565 :                   const std::size_t size = (r1 - r0);
   11332             : 
   11333         565 :                   value_.assign(str1_base_ptr_->base() + r0, size);
   11334             : 
   11335         565 :                   range_.n1_c.second  = value_.size();
   11336         565 :                   range_.cache.second = range_.n1_c.second;
   11337             : 
   11338         565 :                   return T(0);
   11339             :                }
   11340             :             }
   11341             : 
   11342           0 :             return std::numeric_limits<T>::quiet_NaN();
   11343             :          }
   11344             : 
   11345        1100 :          std::string str() const exprtk_override
   11346             :          {
   11347        1100 :             return value_;
   11348             :          }
   11349             : 
   11350          46 :          char_cptr base() const exprtk_override
   11351             :          {
   11352          46 :             return &value_[0];
   11353             :          }
   11354             : 
   11355        1146 :          std::size_t size() const exprtk_override
   11356             :          {
   11357        1146 :             return value_.size();
   11358             :          }
   11359             : 
   11360        1146 :          range_t& range_ref() exprtk_override
   11361             :          {
   11362        1146 :             return range_;
   11363             :          }
   11364             : 
   11365           0 :          const range_t& range_ref() const exprtk_override
   11366             :          {
   11367           0 :             return range_;
   11368             :          }
   11369             : 
   11370       27232 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11371             :          {
   11372       27232 :             return expression_node<T>::e_strcondition;
   11373             :          }
   11374             : 
   11375        3691 :          inline bool valid() const exprtk_override
   11376             :          {
   11377             :             return
   11378        7382 :                initialised_                         &&
   11379        3691 :                condition_  && condition_  ->valid() &&
   11380        3691 :                consequent_ && consequent_ ->valid() &&
   11381        7382 :                alternative_&& alternative_->valid() ;
   11382             :          }
   11383             : 
   11384             :       private:
   11385             : 
   11386             :          bool initialised_;
   11387             :          str_base_ptr str0_base_ptr_;
   11388             :          str_base_ptr str1_base_ptr_;
   11389             :          irange_ptr   str0_range_ptr_;
   11390             :          irange_ptr   str1_range_ptr_;
   11391             :          mutable range_t     range_;
   11392             :          mutable std::string value_;
   11393             : 
   11394             :          expression_ptr condition_;
   11395             :          expression_ptr consequent_;
   11396             :          expression_ptr alternative_;
   11397             :       };
   11398             : 
   11399             :       template <typename T>
   11400             :       class cons_conditional_str_node exprtk_final
   11401             :                                       : public binary_node     <T>
   11402             :                                       , public string_base_node<T>
   11403             :                                       , public range_interface <T>
   11404             :       {
   11405             :       public:
   11406             : 
   11407             :          typedef typename range_interface<T>::range_t range_t;
   11408             :          typedef range_t*             range_ptr;
   11409             :          typedef range_interface <T>  irange_t;
   11410             :          typedef irange_t*            irange_ptr;
   11411             :          typedef expression_node <T>* expression_ptr;
   11412             :          typedef string_base_node<T>* str_base_ptr;
   11413             : 
   11414             :          using binary_node<T>::branch;
   11415             : 
   11416             :          cons_conditional_str_node(expression_ptr condition,
   11417             :                                    expression_ptr consequent)
   11418             :          : binary_node<T>(details::e_default, consequent, condition)
   11419             :          , initialised_(false)
   11420             :          , str0_base_ptr_ (0)
   11421             :          , str0_range_ptr_(0)
   11422             :          , condition_ (condition )
   11423             :          , consequent_(consequent)
   11424             :          {
   11425             :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   11426             :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   11427             : 
   11428             :             range_.cache.first  = range_.n0_c.second;
   11429             :             range_.cache.second = range_.n1_c.second;
   11430             : 
   11431             :             if (is_generally_string_node(branch(0)))
   11432             :             {
   11433             :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   11434             : 
   11435             :                if (0 == str0_base_ptr_)
   11436             :                   return;
   11437             : 
   11438             :                str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
   11439             : 
   11440             :                if (0 == str0_range_ptr_)
   11441             :                   return;
   11442             :             }
   11443             : 
   11444             :             initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
   11445             :             assert(valid());
   11446             :          }
   11447             : 
   11448             :          inline T value() const exprtk_override
   11449             :          {
   11450             :             if (is_true(condition_))
   11451             :             {
   11452             :                consequent_->value();
   11453             : 
   11454             :                const range_t& range = str0_range_ptr_->range_ref();
   11455             : 
   11456             :                std::size_t r0 = 0;
   11457             :                std::size_t r1 = 0;
   11458             : 
   11459             :                if (range(r0, r1, str0_base_ptr_->size()))
   11460             :                {
   11461             :                   const std::size_t size = (r1 - r0);
   11462             : 
   11463             :                   value_.assign(str0_base_ptr_->base() + r0, size);
   11464             : 
   11465             :                   range_.n1_c.second  = value_.size();
   11466             :                   range_.cache.second = range_.n1_c.second;
   11467             : 
   11468             :                   return T(1);
   11469             :                }
   11470             :             }
   11471             : 
   11472             :             return std::numeric_limits<T>::quiet_NaN();
   11473             :          }
   11474             : 
   11475             :          std::string str() const
   11476             :          {
   11477             :             return value_;
   11478             :          }
   11479             : 
   11480             :          char_cptr base() const
   11481             :          {
   11482             :             return &value_[0];
   11483             :          }
   11484             : 
   11485             :          std::size_t size() const
   11486             :          {
   11487             :             return value_.size();
   11488             :          }
   11489             : 
   11490             :          range_t& range_ref()
   11491             :          {
   11492             :             return range_;
   11493             :          }
   11494             : 
   11495             :          const range_t& range_ref() const
   11496             :          {
   11497             :             return range_;
   11498             :          }
   11499             : 
   11500             :          inline typename expression_node<T>::node_type type() const exprtk_override
   11501             :          {
   11502             :             return expression_node<T>::e_strccondition;
   11503             :          }
   11504             : 
   11505             :          inline bool valid() const exprtk_override
   11506             :          {
   11507             :             return
   11508             :                initialised_                         &&
   11509             :                condition_  && condition_  ->valid() &&
   11510             :                consequent_ && consequent_ ->valid() ;
   11511             :          }
   11512             : 
   11513             :       private:
   11514             : 
   11515             :          bool initialised_;
   11516             :          str_base_ptr str0_base_ptr_;
   11517             :          irange_ptr   str0_range_ptr_;
   11518             :          mutable range_t     range_;
   11519             :          mutable std::string value_;
   11520             : 
   11521             :          expression_ptr condition_;
   11522             :          expression_ptr consequent_;
   11523             :       };
   11524             : 
   11525             :       template <typename T, typename VarArgFunction>
   11526             :       class str_vararg_node exprtk_final
   11527             :                             : public expression_node <T>
   11528             :                             , public string_base_node<T>
   11529             :                             , public range_interface <T>
   11530             :       {
   11531             :       public:
   11532             : 
   11533             :          typedef typename range_interface<T>::range_t range_t;
   11534             :          typedef range_t*             range_ptr;
   11535             :          typedef range_interface <T>  irange_t;
   11536             :          typedef irange_t*            irange_ptr;
   11537             :          typedef expression_node <T>* expression_ptr;
   11538             :          typedef string_base_node<T>* str_base_ptr;
   11539             :          typedef std::pair<expression_ptr,bool> branch_t;
   11540             : 
   11541             :          template <typename Allocator,
   11542             :                    template <typename, typename> class Sequence>
   11543          85 :          explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
   11544          85 :          : initialised_(false)
   11545          85 :          , str_base_ptr_ (0)
   11546          85 :          , str_range_ptr_(0)
   11547             :          {
   11548          85 :             construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
   11549             : 
   11550          85 :             if (0 == final_node_.first)
   11551           0 :                return;
   11552          85 :             else if (!is_generally_string_node(final_node_.first))
   11553           0 :                return;
   11554             : 
   11555          85 :             str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first);
   11556             : 
   11557          85 :             if (0 == str_base_ptr_)
   11558           0 :                return;
   11559             : 
   11560          85 :             str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first);
   11561             : 
   11562          85 :             if (0 == str_range_ptr_)
   11563           0 :                return;
   11564             : 
   11565          85 :             if (arg_list.size() > 1)
   11566             :             {
   11567          85 :                const std::size_t arg_list_size = arg_list.size() - 1;
   11568             : 
   11569          85 :                arg_list_.resize(arg_list_size);
   11570             : 
   11571         245 :                for (std::size_t i = 0; i < arg_list_size; ++i)
   11572             :                {
   11573         160 :                   if (arg_list[i] && arg_list[i]->valid())
   11574             :                   {
   11575         160 :                      construct_branch_pair(arg_list_[i], arg_list[i]);
   11576             :                   }
   11577             :                   else
   11578             :                   {
   11579           0 :                      arg_list_.clear();
   11580           0 :                      return;
   11581             :                   }
   11582             :                }
   11583             : 
   11584          85 :                initialised_ = true;
   11585             :             }
   11586             : 
   11587          85 :             initialised_ &= str_base_ptr_ && str_range_ptr_;
   11588          85 :             assert(valid());
   11589           0 :          }
   11590             : 
   11591          85 :          inline T value() const exprtk_override
   11592             :          {
   11593          85 :             if (!arg_list_.empty())
   11594             :             {
   11595          85 :                VarArgFunction::process(arg_list_);
   11596             :             }
   11597             : 
   11598          85 :             final_node_.first->value();
   11599             : 
   11600          85 :             return std::numeric_limits<T>::quiet_NaN();
   11601             :          }
   11602             : 
   11603          40 :          std::string str() const exprtk_override
   11604             :          {
   11605          40 :             return str_base_ptr_->str();
   11606             :          }
   11607             : 
   11608          45 :          char_cptr base() const exprtk_override
   11609             :          {
   11610          45 :             return str_base_ptr_->base();
   11611             :          }
   11612             : 
   11613          85 :          std::size_t size() const exprtk_override
   11614             :          {
   11615          85 :             return str_base_ptr_->size();
   11616             :          }
   11617             : 
   11618          85 :          range_t& range_ref() exprtk_override
   11619             :          {
   11620          85 :             return str_range_ptr_->range_ref();
   11621             :          }
   11622             : 
   11623           0 :          const range_t& range_ref() const exprtk_override
   11624             :          {
   11625           0 :             return str_range_ptr_->range_ref();
   11626             :          }
   11627             : 
   11628        1285 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11629             :          {
   11630        1285 :             return expression_node<T>::e_stringvararg;
   11631             :          }
   11632             : 
   11633         390 :          inline bool valid() const exprtk_override
   11634             :          {
   11635             :             return
   11636         780 :                initialised_ &&
   11637         390 :                final_node_.first && final_node_.first->valid();
   11638             :          }
   11639             : 
   11640          85 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   11641             :          {
   11642          85 :             expression_node<T>::ndb_t::collect(final_node_ , node_delete_list);
   11643          85 :             expression_node<T>::ndb_t::collect(arg_list_   , node_delete_list);
   11644          85 :          }
   11645             : 
   11646         215 :          std::size_t node_depth() const exprtk_override
   11647             :          {
   11648         215 :             return std::max(
   11649         215 :                expression_node<T>::ndb_t::compute_node_depth(final_node_),
   11650         430 :                expression_node<T>::ndb_t::compute_node_depth(arg_list_  ));
   11651             :          }
   11652             : 
   11653             :       private:
   11654             : 
   11655             :          bool                  initialised_;
   11656             :          branch_t              final_node_;
   11657             :          str_base_ptr          str_base_ptr_;
   11658             :          irange_ptr            str_range_ptr_;
   11659             :          std::vector<branch_t> arg_list_;
   11660             :       };
   11661             :       #endif
   11662             : 
   11663             :       template <typename T>
   11664             :       class assert_node exprtk_final : public expression_node<T>
   11665             :       {
   11666             :       public:
   11667             : 
   11668             :          typedef expression_node<T>* expression_ptr;
   11669             :          typedef std::pair<expression_ptr,bool> branch_t;
   11670             :          typedef string_base_node<T>* str_base_ptr;
   11671             :          typedef assert_check::assert_context assert_context_t;
   11672             : 
   11673          84 :          assert_node(expression_ptr   assert_condition_node,
   11674             :                      expression_ptr   assert_message_node,
   11675             :                      assert_check_ptr assert_check,
   11676             :                      assert_context_t context)
   11677          84 :          : assert_message_str_base_(0)
   11678          84 :          , assert_check_(assert_check)
   11679          84 :          , context_(context)
   11680             :          {
   11681          84 :             construct_branch_pair(assert_condition_node_, assert_condition_node);
   11682          84 :             construct_branch_pair(assert_message_node_  , assert_message_node  );
   11683             : 
   11684             :             #ifndef exprtk_disable_string_capabilities
   11685          84 :             if (
   11686         154 :                   assert_message_node_.first &&
   11687          70 :                   details::is_generally_string_node(assert_message_node_.first)
   11688             :                )
   11689             :             {
   11690          70 :                assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first);
   11691             :             }
   11692             :             #endif
   11693             : 
   11694          84 :             assert(valid());
   11695          84 :          }
   11696             : 
   11697          84 :          inline T value() const exprtk_override
   11698             :          {
   11699          84 :             if (assert_condition_node_.first->value() != T(0))
   11700             :             {
   11701           0 :                return T(1);
   11702             :             }
   11703             : 
   11704             :             #ifndef exprtk_disable_string_capabilities
   11705          84 :             if (assert_message_node_.first)
   11706             :             {
   11707          70 :                assert_message_node_.first->value();
   11708          70 :                assert(assert_message_str_base_);
   11709          70 :                context_.message = assert_message_str_base_->str();
   11710             :             }
   11711             :             #endif
   11712             : 
   11713          84 :             assert_check_->handle_assert(context_);
   11714          84 :             return T(0);
   11715             :          }
   11716             : 
   11717        1158 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11718             :          {
   11719        1158 :             return expression_node<T>::e_assert;
   11720             :          }
   11721             : 
   11722         252 :          inline bool valid() const exprtk_override
   11723             :          {
   11724             :             return (
   11725         504 :                      assert_check_ &&
   11726         252 :                      assert_condition_node_.first &&
   11727         252 :                      assert_condition_node_.first->valid()
   11728         504 :                    ) &&
   11729             :                    (
   11730         252 :                      (0 == assert_message_node_.first) ||
   11731             :                      (
   11732         210 :                        assert_message_node_.first &&
   11733         210 :                        assert_message_str_base_   &&
   11734         210 :                        assert_message_node_.first->valid() &&
   11735         210 :                        details::is_generally_string_node(assert_message_node_.first)
   11736             :                      )
   11737         252 :                    );
   11738             :          }
   11739             : 
   11740          84 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   11741             :          {
   11742          84 :             expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list);
   11743          84 :             expression_node<T>::ndb_t::collect(assert_message_node_  , node_delete_list);
   11744          84 :          }
   11745             : 
   11746         222 :          std::size_t node_depth() const exprtk_override
   11747             :          {
   11748             :             return expression_node<T>::ndb_t::compute_node_depth
   11749         222 :                (assert_condition_node_, assert_message_node_);
   11750             :          }
   11751             : 
   11752             :       private:
   11753             : 
   11754             :          branch_t         assert_condition_node_;
   11755             :          branch_t         assert_message_node_;
   11756             :          str_base_ptr     assert_message_str_base_;
   11757             :          assert_check_ptr assert_check_;
   11758             :          mutable assert_context_t context_;
   11759             :       };
   11760             : 
   11761             :       template <typename T, std::size_t N>
   11762         640 :       inline T axn(const T a, const T x)
   11763             :       {
   11764             :          // a*x^n
   11765         640 :          return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
   11766             :       }
   11767             : 
   11768             :       template <typename T, std::size_t N>
   11769         320 :       inline T axnb(const T a, const T x, const T b)
   11770             :       {
   11771             :          // a*x^n+b
   11772         320 :          return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
   11773             :       }
   11774             : 
   11775             :       template <typename T>
   11776             :       struct sf_base
   11777             :       {
   11778             :          typedef typename details::functor_t<T>::Type Type;
   11779             :          typedef typename details::functor_t<T> functor_t;
   11780             :          typedef typename functor_t::qfunc_t quaternary_functor_t;
   11781             :          typedef typename functor_t::tfunc_t trinary_functor_t;
   11782             :          typedef typename functor_t::bfunc_t binary_functor_t;
   11783             :          typedef typename functor_t::ufunc_t unary_functor_t;
   11784             :       };
   11785             : 
   11786             :       #define define_sfop3(NN, OP0, OP1)                 \
   11787             :       template <typename T>                              \
   11788             :       struct sf##NN##_op : public sf_base<T>             \
   11789             :       {                                                  \
   11790             :          typedef typename sf_base<T>::Type const Type;   \
   11791             :          static inline T process(Type x, Type y, Type z) \
   11792             :          {                                               \
   11793             :             return (OP0);                                \
   11794             :          }                                               \
   11795             :          static inline std::string id()                  \
   11796             :          {                                               \
   11797             :             return (OP1);                                \
   11798             :          }                                               \
   11799             :       };                                                 \
   11800             : 
   11801      370734 :       define_sfop3(00,(x + y) / z       ,"(t+t)/t")
   11802      370845 :       define_sfop3(01,(x + y) * z       ,"(t+t)*t")
   11803      371235 :       define_sfop3(02,(x + y) - z       ,"(t+t)-t")
   11804      386326 :       define_sfop3(03,(x + y) + z       ,"(t+t)+t")
   11805     4999126 :       define_sfop3(04,(x - y) + z       ,"(t-t)+t")
   11806      369043 :       define_sfop3(05,(x - y) / z       ,"(t-t)/t")
   11807      371590 :       define_sfop3(06,(x - y) * z       ,"(t-t)*t")
   11808   104384042 :       define_sfop3(07,(x * y) + z       ,"(t*t)+t")
   11809      376882 :       define_sfop3(08,(x * y) - z       ,"(t*t)-t")
   11810      502355 :       define_sfop3(09,(x * y) / z       ,"(t*t)/t")
   11811     5149805 :       define_sfop3(10,(x * y) * z       ,"(t*t)*t")
   11812      382710 :       define_sfop3(11,(x / y) + z       ,"(t/t)+t")
   11813      376297 :       define_sfop3(12,(x / y) - z       ,"(t/t)-t")
   11814      326020 :       define_sfop3(13,(x / y) / z       ,"(t/t)/t")
   11815      476345 :       define_sfop3(14,(x / y) * z       ,"(t/t)*t")
   11816      361620 :       define_sfop3(15,x / (y + z)       ,"t/(t+t)")
   11817      361330 :       define_sfop3(16,x / (y - z)       ,"t/(t-t)")
   11818      527115 :       define_sfop3(17,x / (y * z)       ,"t/(t*t)")
   11819      326020 :       define_sfop3(18,x / (y / z)       ,"t/(t/t)")
   11820      366860 :       define_sfop3(19,x * (y + z)       ,"t*(t+t)")
   11821      361860 :       define_sfop3(20,x * (y - z)       ,"t*(t-t)")
   11822      399748 :       define_sfop3(21,x * (y * z)       ,"t*(t*t)")
   11823      360255 :       define_sfop3(22,x * (y / z)       ,"t*(t/t)")
   11824      396625 :       define_sfop3(23,x - (y + z)       ,"t-(t+t)")
   11825      354280 :       define_sfop3(24,x - (y - z)       ,"t-(t-t)")
   11826      375495 :       define_sfop3(25,x - (y / z)       ,"t-(t/t)")
   11827     6390073 :       define_sfop3(26,x - (y * z)       ,"t-(t*t)")
   11828      875196 :       define_sfop3(27,x + (y * z)       ,"t+(t*t)")
   11829      377460 :       define_sfop3(28,x + (y / z)       ,"t+(t/t)")
   11830      354690 :       define_sfop3(29,x + (y + z)       ,"t+(t+t)")
   11831      353620 :       define_sfop3(30,x + (y - z)       ,"t+(t-t)")
   11832          40 :       define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
   11833          40 :       define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
   11834          40 :       define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
   11835          40 :       define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
   11836          40 :       define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
   11837          40 :       define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
   11838          40 :       define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
   11839          40 :       define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
   11840          40 :       define_sfop3(39,x * numeric::log(y)   + z,"")
   11841          40 :       define_sfop3(40,x * numeric::log(y)   - z,"")
   11842          40 :       define_sfop3(41,x * numeric::log10(y) + z,"")
   11843          40 :       define_sfop3(42,x * numeric::log10(y) - z,"")
   11844          40 :       define_sfop3(43,x * numeric::sin(y) + z  ,"")
   11845          40 :       define_sfop3(44,x * numeric::sin(y) - z  ,"")
   11846          40 :       define_sfop3(45,x * numeric::cos(y) + z  ,"")
   11847          40 :       define_sfop3(46,x * numeric::cos(y) - z  ,"")
   11848          40 :       define_sfop3(47,details::is_true(x) ? y : z,"")
   11849             : 
   11850             :       #define define_sfop4(NN, OP0, OP1)                         \
   11851             :       template <typename T>                                      \
   11852             :       struct sf##NN##_op : public sf_base<T>                     \
   11853             :       {                                                          \
   11854             :          typedef typename sf_base<T>::Type const Type;           \
   11855             :          static inline T process(Type x, Type y, Type z, Type w) \
   11856             :          {                                                       \
   11857             :             return (OP0);                                        \
   11858             :          }                                                       \
   11859             :          static inline std::string id()                          \
   11860             :          {                                                       \
   11861             :             return (OP1);                                        \
   11862             :          }                                                       \
   11863             :       };                                                         \
   11864             : 
   11865      329110 :       define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
   11866      329275 :       define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
   11867      329110 :       define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
   11868      329215 :       define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
   11869      332965 :       define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
   11870      334145 :       define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
   11871      329260 :       define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
   11872      326020 :       define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
   11873      332595 :       define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
   11874      329151 :       define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
   11875      329110 :       define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
   11876      329115 :       define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
   11877      329110 :       define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
   11878      332405 :       define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
   11879      332585 :       define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
   11880      326020 :       define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
   11881      332715 :       define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
   11882      329110 :       define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
   11883      329110 :       define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
   11884      329990 :       define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
   11885      330745 :       define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
   11886      329110 :       define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
   11887      329110 :       define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
   11888      332255 :       define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
   11889      326020 :       define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
   11890      332718 :       define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
   11891      332110 :       define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
   11892      329835 :       define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
   11893      330955 :       define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
   11894      330433 :       define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
   11895      330515 :       define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
   11896      332775 :       define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
   11897      329110 :       define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
   11898      329110 :       define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
   11899      329135 :       define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
   11900      329135 :       define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
   11901             : 
   11902          40 :       define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
   11903          40 :       define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
   11904          40 :       define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
   11905          40 :       define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
   11906          40 :       define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
   11907          40 :       define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
   11908          40 :       define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
   11909          40 :       define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
   11910          75 :       define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
   11911          75 :       define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
   11912          75 :       define_sfop4(94,((x <  y) ? z : w),"")
   11913          75 :       define_sfop4(95,((x <= y) ? z : w),"")
   11914          75 :       define_sfop4(96,((x >  y) ? z : w),"")
   11915          75 :       define_sfop4(97,((x >= y) ? z : w),"")
   11916          75 :       define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
   11917          40 :       define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
   11918             : 
   11919      333970 :       define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
   11920      330765 :       define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
   11921      331695 :       define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
   11922      330735 :       define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
   11923      331845 :       define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
   11924      331245 :       define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
   11925      333510 :       define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
   11926      330415 :       define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
   11927      329070 :       define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
   11928      329050 :       define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
   11929      326705 :       define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
   11930      329050 :       define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
   11931      329270 :       define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
   11932      329710 :       define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
   11933      329370 :       define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
   11934      329570 :       define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
   11935      329230 :       define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
   11936      329050 :       define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
   11937      329050 :       define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
   11938      329050 :       define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
   11939      329050 :       define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
   11940      329050 :       define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
   11941      329050 :       define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
   11942      329050 :       define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
   11943      329050 :       define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
   11944      329050 :       define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
   11945      329485 :       define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
   11946      329050 :       define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
   11947      328625 :       define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
   11948      329050 :       define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
   11949      328620 :       define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
   11950      329050 :       define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
   11951      329480 :       define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
   11952      329215 :       define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
   11953      328900 :       define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
   11954      329060 :       define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
   11955      655035 :       define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
   11956           0 :       define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
   11957      329065 :       define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
   11958      329220 :       define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
   11959      328155 :       define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
   11960      325980 :       define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
   11961      328900 :       define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
   11962      326705 :       define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
   11963      328960 :       define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
   11964      328900 :       define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
   11965      334680 :       define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
   11966      334580 :       define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
   11967      325980 :       define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
   11968      325980 :       define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
   11969      327140 :       define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
   11970      327140 :       define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
   11971      327220 :       define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
   11972      327140 :       define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
   11973      327945 :       define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
   11974      327285 :       define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
   11975      327845 :       define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
   11976      327285 :       define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
   11977      327285 :       define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
   11978      327725 :       define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
   11979      329375 :       define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
   11980      342265 :       define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
   11981             : 
   11982             :       #undef define_sfop3
   11983             :       #undef define_sfop4
   11984             : 
   11985             :       template <typename T, typename SpecialFunction>
   11986             :       class sf3_node exprtk_final : public trinary_node<T>
   11987             :       {
   11988             :       public:
   11989             : 
   11990             :          typedef expression_node<T>* expression_ptr;
   11991             : 
   11992         720 :          sf3_node(const operator_type& opr,
   11993             :                   expression_ptr branch0,
   11994             :                   expression_ptr branch1,
   11995             :                   expression_ptr branch2)
   11996         720 :          : trinary_node<T>(opr, branch0, branch1, branch2)
   11997         720 :          {}
   11998             : 
   11999         720 :          inline T value() const exprtk_override
   12000             :          {
   12001         720 :             const T x = trinary_node<T>::branch_[0].first->value();
   12002         720 :             const T y = trinary_node<T>::branch_[1].first->value();
   12003         720 :             const T z = trinary_node<T>::branch_[2].first->value();
   12004             : 
   12005        1440 :             return SpecialFunction::process(x, y, z);
   12006             :          }
   12007             :       };
   12008             : 
   12009             :       template <typename T, typename SpecialFunction>
   12010             :       class sf4_node exprtk_final : public quaternary_node<T>
   12011             :       {
   12012             :       public:
   12013             : 
   12014             :          typedef expression_node<T>* expression_ptr;
   12015             : 
   12016         815 :          sf4_node(const operator_type& opr,
   12017             :                   expression_ptr branch0,
   12018             :                   expression_ptr branch1,
   12019             :                   expression_ptr branch2,
   12020             :                   expression_ptr branch3)
   12021         815 :          : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
   12022         815 :          {}
   12023             : 
   12024         815 :          inline T value() const exprtk_override
   12025             :          {
   12026         815 :             const T x = quaternary_node<T>::branch_[0].first->value();
   12027         815 :             const T y = quaternary_node<T>::branch_[1].first->value();
   12028         815 :             const T z = quaternary_node<T>::branch_[2].first->value();
   12029         815 :             const T w = quaternary_node<T>::branch_[3].first->value();
   12030             : 
   12031        1630 :             return SpecialFunction::process(x, y, z, w);
   12032             :          }
   12033             :       };
   12034             : 
   12035             :       template <typename T, typename SpecialFunction>
   12036             :       class sf3_var_node exprtk_final : public expression_node<T>
   12037             :       {
   12038             :       public:
   12039             : 
   12040             :          typedef expression_node<T>* expression_ptr;
   12041             : 
   12042        1200 :          sf3_var_node(const T& v0, const T& v1, const T& v2)
   12043        1200 :          : v0_(v0)
   12044        1200 :          , v1_(v1)
   12045        1200 :          , v2_(v2)
   12046        1200 :          {}
   12047             : 
   12048        1200 :          inline T value() const exprtk_override
   12049             :          {
   12050        1200 :             return SpecialFunction::process(v0_, v1_, v2_);
   12051             :          }
   12052             : 
   12053       15600 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12054             :          {
   12055       15600 :             return expression_node<T>::e_trinary;
   12056             :          }
   12057             : 
   12058             :       private:
   12059             : 
   12060             :          sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
   12061             :          sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
   12062             : 
   12063             :          const T& v0_;
   12064             :          const T& v1_;
   12065             :          const T& v2_;
   12066             :       };
   12067             : 
   12068             :       template <typename T, typename SpecialFunction>
   12069             :       class sf4_var_node exprtk_final : public expression_node<T>
   12070             :       {
   12071             :       public:
   12072             : 
   12073             :          typedef expression_node<T>* expression_ptr;
   12074             : 
   12075        1510 :          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
   12076        1510 :          : v0_(v0)
   12077        1510 :          , v1_(v1)
   12078        1510 :          , v2_(v2)
   12079        1510 :          , v3_(v3)
   12080        1510 :          {}
   12081             : 
   12082        1510 :          inline T value() const exprtk_override
   12083             :          {
   12084        1510 :             return SpecialFunction::process(v0_, v1_, v2_, v3_);
   12085             :          }
   12086             : 
   12087       19630 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12088             :          {
   12089       19630 :             return expression_node<T>::e_trinary;
   12090             :          }
   12091             : 
   12092             :       private:
   12093             : 
   12094             :          sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
   12095             :          sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
   12096             : 
   12097             :          const T& v0_;
   12098             :          const T& v1_;
   12099             :          const T& v2_;
   12100             :          const T& v3_;
   12101             :       };
   12102             : 
   12103             :       template <typename T, typename VarArgFunction>
   12104             :       class vararg_node exprtk_final : public expression_node<T>
   12105             :       {
   12106             :       public:
   12107             : 
   12108             :          typedef expression_node<T>* expression_ptr;
   12109             :          typedef std::pair<expression_ptr,bool> branch_t;
   12110             : 
   12111             :          template <typename Allocator,
   12112             :                    template <typename, typename> class Sequence>
   12113       44798 :          explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
   12114       44798 :          : initialised_(false)
   12115             :          {
   12116       44798 :             arg_list_.resize(arg_list.size());
   12117             : 
   12118      182663 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   12119             :             {
   12120      137865 :                if (arg_list[i] && arg_list[i]->valid())
   12121             :                {
   12122      137865 :                   construct_branch_pair(arg_list_[i],arg_list[i]);
   12123             :                }
   12124             :                else
   12125             :                {
   12126           0 :                   arg_list_.clear();
   12127           0 :                   return;
   12128             :                }
   12129             :             }
   12130             : 
   12131       44798 :             initialised_ = (arg_list_.size() == arg_list.size());
   12132       44798 :             assert(valid());
   12133           0 :          }
   12134             : 
   12135    10172947 :          inline T value() const exprtk_override
   12136             :          {
   12137    10172947 :             return VarArgFunction::process(arg_list_);
   12138             :          }
   12139             : 
   12140      251312 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12141             :          {
   12142      251312 :             return expression_node<T>::e_vararg;
   12143             :          }
   12144             : 
   12145      108186 :          inline bool valid() const exprtk_override
   12146             :          {
   12147      108186 :             return initialised_;
   12148             :          }
   12149             : 
   12150       44798 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   12151             :          {
   12152       44798 :             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
   12153       44798 :          }
   12154             : 
   12155       62159 :          std::size_t node_depth() const exprtk_override
   12156             :          {
   12157       62159 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
   12158             :          }
   12159             : 
   12160          54 :          std::size_t size() const
   12161             :          {
   12162          54 :             return arg_list_.size();
   12163             :          }
   12164             : 
   12165         272 :          expression_ptr operator[](const std::size_t& index) const
   12166             :          {
   12167         272 :             return arg_list_[index].first;
   12168             :          }
   12169             : 
   12170             :       private:
   12171             : 
   12172             :          std::vector<branch_t> arg_list_;
   12173             :          bool initialised_;
   12174             :       };
   12175             : 
   12176             :       template <typename T, typename VarArgFunction>
   12177             :       class vararg_varnode exprtk_final : public expression_node<T>
   12178             :       {
   12179             :       public:
   12180             : 
   12181             :          typedef expression_node<T>* expression_ptr;
   12182             : 
   12183             :          template <typename Allocator,
   12184             :                    template <typename, typename> class Sequence>
   12185        2308 :          explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
   12186        2308 :          : initialised_(false)
   12187             :          {
   12188        2308 :             arg_list_.resize(arg_list.size());
   12189             : 
   12190        7435 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   12191             :             {
   12192        5127 :                if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i]))
   12193             :                {
   12194        5127 :                   variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
   12195        5127 :                   arg_list_[i] = (&var_node_ptr->ref());
   12196             :                }
   12197             :                else
   12198             :                {
   12199           0 :                   arg_list_.clear();
   12200           0 :                   return;
   12201             :                }
   12202             :             }
   12203             : 
   12204        2308 :             initialised_ = (arg_list.size() == arg_list_.size());
   12205        2308 :             assert(valid());
   12206           0 :          }
   12207             : 
   12208        2308 :          inline T value() const exprtk_override
   12209             :          {
   12210        2308 :             return VarArgFunction::process(arg_list_);
   12211             :          }
   12212             : 
   12213       58623 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12214             :          {
   12215       58623 :             return expression_node<T>::e_vararg;
   12216             :          }
   12217             : 
   12218        8034 :          inline bool valid() const exprtk_override
   12219             :          {
   12220        8034 :             return initialised_;
   12221             :          }
   12222             : 
   12223             :       private:
   12224             : 
   12225             :          std::vector<const T*> arg_list_;
   12226             :          bool initialised_;
   12227             :       };
   12228             : 
   12229             :       template <typename T, typename VecFunction>
   12230             :       class vectorize_node exprtk_final : public expression_node<T>
   12231             :       {
   12232             :       public:
   12233             : 
   12234             :          typedef expression_node<T>* expression_ptr;
   12235             :          typedef std::pair<expression_ptr,bool> branch_t;
   12236             : 
   12237        2401 :          explicit vectorize_node(const expression_ptr v)
   12238        2401 :          : ivec_ptr_(0)
   12239             :          {
   12240        2401 :             construct_branch_pair(v_, v);
   12241             : 
   12242        2401 :             if (is_ivector_node(v_.first))
   12243             :             {
   12244        2401 :                ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
   12245             :             }
   12246        2401 :          }
   12247             : 
   12248        2615 :          inline T value() const exprtk_override
   12249             :          {
   12250        2615 :             v_.first->value();
   12251        2615 :             return VecFunction::process(ivec_ptr_);
   12252             :          }
   12253             : 
   12254       61533 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12255             :          {
   12256       61533 :             return expression_node<T>::e_vecfunc;
   12257             :          }
   12258             : 
   12259        5296 :          inline bool valid() const exprtk_override
   12260             :          {
   12261        5296 :             return ivec_ptr_ && v_.first && v_.first->valid();
   12262             :          }
   12263             : 
   12264        2401 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   12265             :          {
   12266        2401 :             expression_node<T>::ndb_t::collect(v_, node_delete_list);
   12267        2401 :          }
   12268             : 
   12269        5388 :          std::size_t node_depth() const exprtk_override
   12270             :          {
   12271        5388 :             return expression_node<T>::ndb_t::compute_node_depth(v_);
   12272             :          }
   12273             : 
   12274             :       private:
   12275             : 
   12276             :          vector_interface<T>* ivec_ptr_;
   12277             :          branch_t                    v_;
   12278             :       };
   12279             : 
   12280             :       template <typename T>
   12281             :       class assignment_node exprtk_final : public binary_node<T>
   12282             :       {
   12283             :       public:
   12284             : 
   12285             :          typedef expression_node<T>* expression_ptr;
   12286             :          using binary_node<T>::branch;
   12287             : 
   12288       46190 :          assignment_node(const operator_type& opr,
   12289             :                          expression_ptr branch0,
   12290             :                          expression_ptr branch1)
   12291             :          : binary_node<T>(opr, branch0, branch1)
   12292       46190 :          , var_node_ptr_(0)
   12293             :          {
   12294       46190 :             if (is_variable_node(branch(0)))
   12295             :             {
   12296       46190 :                var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
   12297             :             }
   12298       46190 :          }
   12299             : 
   12300    26769309 :          inline T value() const exprtk_override
   12301             :          {
   12302    26769309 :             T& result = var_node_ptr_->ref();
   12303    26769309 :                result = branch(1)->value();
   12304             : 
   12305    26769309 :             return result;
   12306             :          }
   12307             : 
   12308       98248 :          inline bool valid() const exprtk_override
   12309             :          {
   12310       98248 :             return var_node_ptr_ && binary_node<T>::valid();
   12311             :          }
   12312             : 
   12313             :       private:
   12314             : 
   12315             :          variable_node<T>* var_node_ptr_;
   12316             :       };
   12317             : 
   12318             :       template <typename T>
   12319             :       class assignment_vec_elem_node exprtk_final : public binary_node<T>
   12320             :       {
   12321             :       public:
   12322             : 
   12323             :          typedef expression_node<T>* expression_ptr;
   12324             :          using binary_node<T>::branch;
   12325             : 
   12326          83 :          assignment_vec_elem_node(const operator_type& opr,
   12327             :                                   expression_ptr branch0,
   12328             :                                   expression_ptr branch1)
   12329             :          : binary_node<T>(opr, branch0, branch1)
   12330          83 :          , vec_node_ptr_(0)
   12331             :          {
   12332          83 :             if (is_vector_elem_node(branch(0)))
   12333             :             {
   12334          83 :                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
   12335             :             }
   12336             : 
   12337          83 :             assert(valid());
   12338          83 :          }
   12339             : 
   12340    22850849 :          inline T value() const exprtk_override
   12341             :          {
   12342    22850849 :             T& result = vec_node_ptr_->ref();
   12343    22850849 :                result = branch(1)->value();
   12344             : 
   12345    22850849 :             return result;
   12346             :          }
   12347             : 
   12348         246 :          inline bool valid() const exprtk_override
   12349             :          {
   12350         246 :             return vec_node_ptr_ && binary_node<T>::valid();
   12351             :          }
   12352             : 
   12353             :       private:
   12354             : 
   12355             :          vector_elem_node<T>* vec_node_ptr_;
   12356             :       };
   12357             : 
   12358             :       template <typename T>
   12359             :       class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T>
   12360             :       {
   12361             :       public:
   12362             : 
   12363             :          typedef expression_node<T>* expression_ptr;
   12364             :          using binary_node<T>::branch;
   12365             : 
   12366          20 :          assignment_vec_elem_rtc_node(const operator_type& opr,
   12367             :                                       expression_ptr branch0,
   12368             :                                       expression_ptr branch1)
   12369             :          : binary_node<T>(opr, branch0, branch1)
   12370          20 :          , vec_node_ptr_(0)
   12371             :          {
   12372          20 :             if (is_vector_elem_rtc_node(branch(0)))
   12373             :             {
   12374          20 :                vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
   12375             :             }
   12376             : 
   12377          20 :             assert(valid());
   12378          20 :          }
   12379             : 
   12380         150 :          inline T value() const exprtk_override
   12381             :          {
   12382         150 :             T& result = vec_node_ptr_->ref();
   12383         150 :                result = branch(1)->value();
   12384             : 
   12385         150 :             return result;
   12386             :          }
   12387             : 
   12388          40 :          inline bool valid() const exprtk_override
   12389             :          {
   12390          40 :             return vec_node_ptr_ && binary_node<T>::valid();
   12391             :          }
   12392             : 
   12393             :       private:
   12394             : 
   12395             :          vector_elem_rtc_node<T>* vec_node_ptr_;
   12396             :       };
   12397             : 
   12398             :       template <typename T>
   12399             :       class assignment_rebasevec_elem_node exprtk_final : public binary_node<T>
   12400             :       {
   12401             :       public:
   12402             : 
   12403             :          typedef expression_node<T>* expression_ptr;
   12404             :          using expression_node<T>::branch;
   12405             : 
   12406           0 :          assignment_rebasevec_elem_node(const operator_type& opr,
   12407             :                                         expression_ptr branch0,
   12408             :                                         expression_ptr branch1)
   12409             :          : binary_node<T>(opr, branch0, branch1)
   12410           0 :          , rbvec_node_ptr_(0)
   12411             :          {
   12412           0 :             if (is_rebasevector_elem_node(branch(0)))
   12413             :             {
   12414           0 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
   12415             :             }
   12416             : 
   12417           0 :             assert(valid());
   12418           0 :          }
   12419             : 
   12420           0 :          inline T value() const exprtk_override
   12421             :          {
   12422           0 :             T& result = rbvec_node_ptr_->ref();
   12423           0 :                result = branch(1)->value();
   12424             : 
   12425           0 :             return result;
   12426             :          }
   12427             : 
   12428           0 :          inline bool valid() const exprtk_override
   12429             :          {
   12430           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12431             :          }
   12432             : 
   12433             :       private:
   12434             : 
   12435             :          rebasevector_elem_node<T>* rbvec_node_ptr_;
   12436             :       };
   12437             : 
   12438             :       template <typename T>
   12439             :       class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T>
   12440             :       {
   12441             :       public:
   12442             : 
   12443             :          typedef expression_node<T>* expression_ptr;
   12444             :          using expression_node<T>::branch;
   12445             : 
   12446           0 :          assignment_rebasevec_elem_rtc_node(const operator_type& opr,
   12447             :                                             expression_ptr branch0,
   12448             :                                             expression_ptr branch1)
   12449             :          : binary_node<T>(opr, branch0, branch1)
   12450           0 :          , rbvec_node_ptr_(0)
   12451             :          {
   12452           0 :             if (is_rebasevector_elem_rtc_node(branch(0)))
   12453             :             {
   12454           0 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
   12455             :             }
   12456             : 
   12457           0 :             assert(valid());
   12458           0 :          }
   12459             : 
   12460           0 :          inline T value() const exprtk_override
   12461             :          {
   12462           0 :             T& result = rbvec_node_ptr_->ref();
   12463           0 :                result = branch(1)->value();
   12464             : 
   12465           0 :             return result;
   12466             :          }
   12467             : 
   12468           0 :          inline bool valid() const exprtk_override
   12469             :          {
   12470           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12471             :          }
   12472             : 
   12473             :       private:
   12474             : 
   12475             :          rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
   12476             :       };
   12477             : 
   12478             :       template <typename T>
   12479             :       class assignment_rebasevec_celem_node exprtk_final : public binary_node<T>
   12480             :       {
   12481             :       public:
   12482             : 
   12483             :          typedef expression_node<T>* expression_ptr;
   12484             :          using binary_node<T>::branch;
   12485             : 
   12486           0 :          assignment_rebasevec_celem_node(const operator_type& opr,
   12487             :                                          expression_ptr branch0,
   12488             :                                          expression_ptr branch1)
   12489             :          : binary_node<T>(opr, branch0, branch1)
   12490           0 :          , rbvec_node_ptr_(0)
   12491             :          {
   12492           0 :             if (is_rebasevector_celem_node(branch(0)))
   12493             :             {
   12494           0 :                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
   12495             :             }
   12496             : 
   12497           0 :             assert(valid());
   12498           0 :          }
   12499             : 
   12500           0 :          inline T value() const exprtk_override
   12501             :          {
   12502           0 :             T& result = rbvec_node_ptr_->ref();
   12503           0 :                result = branch(1)->value();
   12504             : 
   12505           0 :             return result;
   12506             :          }
   12507             : 
   12508           0 :          inline bool valid() const exprtk_override
   12509             :          {
   12510           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12511             :          }
   12512             : 
   12513             :       private:
   12514             : 
   12515             :          rebasevector_celem_node<T>* rbvec_node_ptr_;
   12516             :       };
   12517             : 
   12518             :       template <typename T>
   12519             :       class assignment_vec_node exprtk_final
   12520             :                                 : public binary_node     <T>
   12521             :                                 , public vector_interface<T>
   12522             :       {
   12523             :       public:
   12524             : 
   12525             :          typedef expression_node<T>* expression_ptr;
   12526             :          typedef vector_node<T>*     vector_node_ptr;
   12527             :          typedef vec_data_store<T>   vds_t;
   12528             : 
   12529             :          using binary_node<T>::branch;
   12530             : 
   12531         204 :          assignment_vec_node(const operator_type& opr,
   12532             :                              expression_ptr branch0,
   12533             :                              expression_ptr branch1)
   12534             :          : binary_node<T>(opr, branch0, branch1)
   12535         204 :          , vec_node_ptr_(0)
   12536             :          {
   12537         204 :             if (is_vector_node(branch(0)))
   12538             :             {
   12539         204 :                vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   12540         204 :                vds()         = vec_node_ptr_->vds();
   12541             :             }
   12542             : 
   12543         204 :             assert(valid());
   12544         204 :          }
   12545             : 
   12546         204 :          inline T value() const exprtk_override
   12547             :          {
   12548         204 :             const T v = branch(1)->value();
   12549             : 
   12550         204 :             T* vec = vds().data();
   12551             : 
   12552         204 :             loop_unroll::details lud(size());
   12553         204 :             const T* upper_bound = vec + lud.upper_bound;
   12554             : 
   12555         204 :             while (vec < upper_bound)
   12556             :             {
   12557             :                #define exprtk_loop(N) \
   12558             :                vec[N] = v;            \
   12559             : 
   12560           0 :                exprtk_loop( 0) exprtk_loop( 1)
   12561           0 :                exprtk_loop( 2) exprtk_loop( 3)
   12562             :                #ifndef exprtk_disable_superscalar_unroll
   12563           0 :                exprtk_loop( 4) exprtk_loop( 5)
   12564           0 :                exprtk_loop( 6) exprtk_loop( 7)
   12565           0 :                exprtk_loop( 8) exprtk_loop( 9)
   12566           0 :                exprtk_loop(10) exprtk_loop(11)
   12567           0 :                exprtk_loop(12) exprtk_loop(13)
   12568           0 :                exprtk_loop(14) exprtk_loop(15)
   12569             :                #endif
   12570             : 
   12571           0 :                vec += lud.batch_size;
   12572             :             }
   12573             : 
   12574         204 :             switch (lud.remainder)
   12575             :             {
   12576             :                #define case_stmt(N) \
   12577             :                case N : *vec++ = v; \
   12578             :                exprtk_fallthrough   \
   12579             : 
   12580             :                #ifndef exprtk_disable_superscalar_unroll
   12581           0 :                case_stmt(15) case_stmt(14)
   12582           0 :                case_stmt(13) case_stmt(12)
   12583           0 :                case_stmt(11) case_stmt(10)
   12584         183 :                case_stmt( 9) case_stmt( 8)
   12585         189 :                case_stmt( 7) case_stmt( 6)
   12586         195 :                case_stmt( 5) case_stmt( 4)
   12587             :                #endif
   12588         201 :                case_stmt( 3) case_stmt( 2)
   12589         204 :                case 1 : *vec++ = v;
   12590             :             }
   12591             : 
   12592             :             #undef exprtk_loop
   12593             :             #undef case_stmt
   12594             : 
   12595         408 :             return vec_node_ptr_->value();
   12596             :          }
   12597             : 
   12598           0 :          vector_node_ptr vec() const exprtk_override
   12599             :          {
   12600           0 :             return vec_node_ptr_;
   12601             :          }
   12602             : 
   12603           0 :          vector_node_ptr vec() exprtk_override
   12604             :          {
   12605           0 :             return vec_node_ptr_;
   12606             :          }
   12607             : 
   12608        2244 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12609             :          {
   12610        2244 :             return expression_node<T>::e_vecvalass;
   12611             :          }
   12612             : 
   12613         612 :          inline bool valid() const exprtk_override
   12614             :          {
   12615             :             return
   12616        1224 :                vec_node_ptr_ &&
   12617        1224 :                (vds().size() <= vec_node_ptr_->vec_holder().base_size()) &&
   12618        1224 :                binary_node<T>::valid();
   12619             :          }
   12620             : 
   12621         204 :          std::size_t size() const exprtk_override
   12622             :          {
   12623         204 :             return vec_node_ptr_->vec_holder().size();
   12624             :          }
   12625             : 
   12626           0 :          std::size_t base_size() const exprtk_override
   12627             :          {
   12628           0 :             return vec_node_ptr_->vec_holder().base_size();
   12629             :          }
   12630             : 
   12631         204 :          vds_t& vds() exprtk_override
   12632             :          {
   12633         204 :             return vds_;
   12634             :          }
   12635             : 
   12636         816 :          const vds_t& vds() const exprtk_override
   12637             :          {
   12638         816 :             return vds_;
   12639             :          }
   12640             : 
   12641             :       private:
   12642             : 
   12643             :          vector_node<T>* vec_node_ptr_;
   12644             :          vds_t           vds_;
   12645             :       };
   12646             : 
   12647             :       template <typename T>
   12648             :       class assignment_vecvec_node exprtk_final
   12649             :                                    : public binary_node     <T>
   12650             :                                    , public vector_interface<T>
   12651             :       {
   12652             :       public:
   12653             : 
   12654             :          typedef expression_node<T>* expression_ptr;
   12655             :          typedef vector_node<T>*     vector_node_ptr;
   12656             :          typedef vec_data_store<T>   vds_t;
   12657             : 
   12658             :          using binary_node<T>::branch;
   12659             : 
   12660        1471 :          assignment_vecvec_node(const operator_type& opr,
   12661             :                                 expression_ptr branch0,
   12662             :                                 expression_ptr branch1)
   12663             :          : binary_node<T>(opr, branch0, branch1)
   12664        1471 :          , vec0_node_ptr_(0)
   12665        1471 :          , vec1_node_ptr_(0)
   12666        1471 :          , initialised_(false)
   12667        1471 :          , src_is_ivec_(false)
   12668             :          {
   12669        1471 :             if (is_vector_node(branch(0)))
   12670             :             {
   12671        1471 :                vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   12672        1471 :                vds()          = vec0_node_ptr_->vds();
   12673             :             }
   12674             : 
   12675        1471 :             if (is_vector_node(branch(1)))
   12676             :             {
   12677         489 :                vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
   12678         489 :                vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
   12679             :             }
   12680         982 :             else if (is_ivector_node(branch(1)))
   12681             :             {
   12682         982 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   12683             : 
   12684         982 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   12685             :                {
   12686         982 :                   vec1_node_ptr_ = vi->vec();
   12687             : 
   12688         982 :                   if (!vi->side_effect())
   12689             :                   {
   12690         822 :                      vi->vds()    = vds();
   12691         822 :                      src_is_ivec_ = true;
   12692             :                   }
   12693             :                   else
   12694         160 :                      vds_t::match_sizes(vds(),vi->vds());
   12695             :                }
   12696             :             }
   12697             : 
   12698        1471 :             initialised_ =
   12699        2942 :                vec0_node_ptr_               &&
   12700        1471 :                vec1_node_ptr_               &&
   12701        1471 :                (size() <= base_size())      &&
   12702        4413 :                (vds_.size() <= base_size()) &&
   12703        1471 :                binary_node<T>::valid();
   12704             : 
   12705        1471 :             assert(valid());
   12706        1471 :          }
   12707             : 
   12708        1471 :          inline T value() const exprtk_override
   12709             :          {
   12710        1471 :             branch(1)->value();
   12711             : 
   12712        1471 :             if (src_is_ivec_)
   12713         822 :                return vec0_node_ptr_->value();
   12714             : 
   12715         649 :             T* vec0 = vec0_node_ptr_->vds().data();
   12716         649 :             T* vec1 = vec1_node_ptr_->vds().data();
   12717             : 
   12718         649 :             loop_unroll::details lud(size());
   12719         649 :             const T* upper_bound = vec0 + lud.upper_bound;
   12720             : 
   12721         649 :             while (vec0 < upper_bound)
   12722             :             {
   12723             :                #define exprtk_loop(N) \
   12724             :                vec0[N] = vec1[N];     \
   12725             : 
   12726           0 :                exprtk_loop( 0) exprtk_loop( 1)
   12727           0 :                exprtk_loop( 2) exprtk_loop( 3)
   12728             :                #ifndef exprtk_disable_superscalar_unroll
   12729           0 :                exprtk_loop( 4) exprtk_loop( 5)
   12730           0 :                exprtk_loop( 6) exprtk_loop( 7)
   12731           0 :                exprtk_loop( 8) exprtk_loop( 9)
   12732           0 :                exprtk_loop(10) exprtk_loop(11)
   12733           0 :                exprtk_loop(12) exprtk_loop(13)
   12734           0 :                exprtk_loop(14) exprtk_loop(15)
   12735             :                #endif
   12736             : 
   12737           0 :                vec0 += lud.batch_size;
   12738           0 :                vec1 += lud.batch_size;
   12739             :             }
   12740             : 
   12741         649 :             switch (lud.remainder)
   12742             :             {
   12743             :                #define case_stmt(N,fall_through) \
   12744             :                case N : *vec0++ = *vec1++;       \
   12745             :                fall_through                      \
   12746             : 
   12747             :                #ifndef exprtk_disable_superscalar_unroll
   12748           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   12749           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   12750           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   12751           2 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   12752           8 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   12753         304 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   12754             :                #endif
   12755         564 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   12756         649 :                case_stmt( 1, (void)0;)
   12757             :             }
   12758             : 
   12759             :             #undef exprtk_loop
   12760             :             #undef case_stmt
   12761             : 
   12762         649 :             return vec0_node_ptr_->value();
   12763             :          }
   12764             : 
   12765           0 :          vector_node_ptr vec() exprtk_override
   12766             :          {
   12767           0 :             return vec0_node_ptr_;
   12768             :          }
   12769             : 
   12770           0 :          vector_node_ptr vec() const exprtk_override
   12771             :          {
   12772           0 :             return vec0_node_ptr_;
   12773             :          }
   12774             : 
   12775       16223 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12776             :          {
   12777       16223 :             return expression_node<T>::e_vecvecass;
   12778             :          }
   12779             : 
   12780        4703 :          inline bool valid() const exprtk_override
   12781             :          {
   12782        4703 :             return initialised_;
   12783             :          }
   12784             : 
   12785        2120 :          std::size_t size() const exprtk_override
   12786             :          {
   12787        2120 :             return std::min(
   12788        2120 :                vec0_node_ptr_->vec_holder().size(),
   12789        4240 :                vec1_node_ptr_->vec_holder().size());
   12790             :          }
   12791             : 
   12792        2942 :          std::size_t base_size() const exprtk_override
   12793             :          {
   12794        2942 :             return std::min(
   12795        2942 :                vec0_node_ptr_->vec_holder().base_size(),
   12796        5884 :                vec1_node_ptr_->vec_holder().base_size());
   12797             :          }
   12798             : 
   12799        2942 :          vds_t& vds() exprtk_override
   12800             :          {
   12801        2942 :             return vds_;
   12802             :          }
   12803             : 
   12804           0 :          const vds_t& vds() const exprtk_override
   12805             :          {
   12806           0 :             return vds_;
   12807             :          }
   12808             : 
   12809             :       private:
   12810             : 
   12811             :          vector_node<T>* vec0_node_ptr_;
   12812             :          vector_node<T>* vec1_node_ptr_;
   12813             :          bool            initialised_;
   12814             :          bool            src_is_ivec_;
   12815             :          vds_t           vds_;
   12816             :       };
   12817             : 
   12818             :       template <typename T, typename Operation>
   12819             :       class assignment_op_node exprtk_final : public binary_node<T>
   12820             :       {
   12821             :       public:
   12822             : 
   12823             :          typedef expression_node<T>* expression_ptr;
   12824             :          using binary_node<T>::branch;
   12825             : 
   12826        4875 :          assignment_op_node(const operator_type& opr,
   12827             :                             expression_ptr branch0,
   12828             :                             expression_ptr branch1)
   12829             :          : binary_node<T>(opr, branch0, branch1)
   12830        4875 :          , var_node_ptr_(0)
   12831             :          {
   12832        4875 :             if (is_variable_node(branch(0)))
   12833             :             {
   12834        4875 :                var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
   12835             :             }
   12836             : 
   12837        4875 :             assert(valid());
   12838        4875 :          }
   12839             : 
   12840   158668567 :          inline T value() const exprtk_override
   12841             :          {
   12842   158668567 :             T& v = var_node_ptr_->ref();
   12843   158668567 :             v = Operation::process(v,branch(1)->value());
   12844             : 
   12845   158668567 :             return v;
   12846             :          }
   12847             : 
   12848       11200 :          inline bool valid() const exprtk_override
   12849             :          {
   12850       11200 :             return var_node_ptr_ && binary_node<T>::valid();
   12851             :          }
   12852             : 
   12853             :       private:
   12854             : 
   12855             :          variable_node<T>* var_node_ptr_;
   12856             :       };
   12857             : 
   12858             :       template <typename T, typename Operation>
   12859             :       class assignment_vec_elem_op_node exprtk_final : public binary_node<T>
   12860             :       {
   12861             :       public:
   12862             : 
   12863             :          typedef expression_node<T>* expression_ptr;
   12864             :          using binary_node<T>::branch;
   12865             : 
   12866         500 :          assignment_vec_elem_op_node(const operator_type& opr,
   12867             :                                      expression_ptr branch0,
   12868             :                                      expression_ptr branch1)
   12869             :          : binary_node<T>(opr, branch0, branch1)
   12870         500 :          , vec_node_ptr_(0)
   12871             :          {
   12872         500 :             if (is_vector_elem_node(branch(0)))
   12873             :             {
   12874         500 :                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
   12875             :             }
   12876             : 
   12877         500 :             assert(valid());
   12878         500 :          }
   12879             : 
   12880        1100 :          inline T value() const exprtk_override
   12881             :          {
   12882        1100 :             T& v = vec_node_ptr_->ref();
   12883        1100 :                v = Operation::process(v,branch(1)->value());
   12884             : 
   12885        1100 :             return v;
   12886             :          }
   12887             : 
   12888        1500 :          inline bool valid() const exprtk_override
   12889             :          {
   12890        1500 :             return vec_node_ptr_ && binary_node<T>::valid();
   12891             :          }
   12892             : 
   12893             :       private:
   12894             : 
   12895             :          vector_elem_node<T>* vec_node_ptr_;
   12896             :       };
   12897             : 
   12898             :       template <typename T, typename Operation>
   12899             :       class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T>
   12900             :       {
   12901             :       public:
   12902             : 
   12903             :          typedef expression_node<T>* expression_ptr;
   12904             :          using binary_node<T>::branch;
   12905             : 
   12906          12 :          assignment_vec_elem_op_rtc_node(const operator_type& opr,
   12907             :                                          expression_ptr branch0,
   12908             :                                          expression_ptr branch1)
   12909             :          : binary_node<T>(opr, branch0, branch1)
   12910          12 :          , vec_node_ptr_(0)
   12911             :          {
   12912          12 :             if (is_vector_elem_rtc_node(branch(0)))
   12913             :             {
   12914          12 :                vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
   12915             :             }
   12916             : 
   12917          12 :             assert(valid());
   12918          12 :          }
   12919             : 
   12920          18 :          inline T value() const exprtk_override
   12921             :          {
   12922          18 :             T& v = vec_node_ptr_->ref();
   12923          18 :                v = Operation::process(v,branch(1)->value());
   12924             : 
   12925          18 :             return v;
   12926             :          }
   12927             : 
   12928          46 :          inline bool valid() const exprtk_override
   12929             :          {
   12930          46 :             return vec_node_ptr_ && binary_node<T>::valid();
   12931             :          }
   12932             : 
   12933             :       private:
   12934             : 
   12935             :          vector_elem_rtc_node<T>* vec_node_ptr_;
   12936             :       };
   12937             : 
   12938             :       template <typename T, typename Operation>
   12939             :       class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T>
   12940             :       {
   12941             :       public:
   12942             : 
   12943             :          typedef expression_node<T>* expression_ptr;
   12944             :          using binary_node<T>::branch;
   12945             : 
   12946           0 :          assignment_vec_celem_op_rtc_node(const operator_type& opr,
   12947             :                                           expression_ptr branch0,
   12948             :                                           expression_ptr branch1)
   12949             :          : binary_node<T>(opr, branch0, branch1)
   12950           0 :          , vec_node_ptr_(0)
   12951             :          {
   12952           0 :             if (is_vector_celem_rtc_node(branch(0)))
   12953             :             {
   12954           0 :                vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0));
   12955             :             }
   12956             : 
   12957           0 :             assert(valid());
   12958           0 :          }
   12959             : 
   12960           0 :          inline T value() const exprtk_override
   12961             :          {
   12962           0 :             T& v = vec_node_ptr_->ref();
   12963           0 :                v = Operation::process(v,branch(1)->value());
   12964             : 
   12965           0 :             return v;
   12966             :          }
   12967             : 
   12968           0 :          inline bool valid() const exprtk_override
   12969             :          {
   12970           0 :             return vec_node_ptr_ && binary_node<T>::valid();
   12971             :          }
   12972             : 
   12973             :       private:
   12974             : 
   12975             :          vector_celem_rtc_node<T>* vec_node_ptr_;
   12976             :       };
   12977             : 
   12978             :       template <typename T, typename Operation>
   12979             :       class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T>
   12980             :       {
   12981             :       public:
   12982             : 
   12983             :          typedef expression_node<T>* expression_ptr;
   12984             :          using binary_node<T>::branch;
   12985             : 
   12986         300 :          assignment_rebasevec_elem_op_node(const operator_type& opr,
   12987             :                                            expression_ptr branch0,
   12988             :                                            expression_ptr branch1)
   12989             :          : binary_node<T>(opr, branch0, branch1)
   12990         300 :          , rbvec_node_ptr_(0)
   12991             :          {
   12992         300 :             if (is_rebasevector_elem_node(branch(0)))
   12993             :             {
   12994         300 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
   12995             :             }
   12996             : 
   12997         300 :             assert(valid());
   12998         300 :          }
   12999             : 
   13000         300 :          inline T value() const exprtk_override
   13001             :          {
   13002         300 :             T& v = rbvec_node_ptr_->ref();
   13003         300 :                v = Operation::process(v,branch(1)->value());
   13004             : 
   13005         300 :             return v;
   13006             :          }
   13007             : 
   13008         900 :          inline bool valid() const exprtk_override
   13009             :          {
   13010         900 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   13011             :          }
   13012             : 
   13013             :       private:
   13014             : 
   13015             :          rebasevector_elem_node<T>* rbvec_node_ptr_;
   13016             :       };
   13017             : 
   13018             :       template <typename T, typename Operation>
   13019             :       class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T>
   13020             :       {
   13021             :       public:
   13022             : 
   13023             :          typedef expression_node<T>* expression_ptr;
   13024             :          using binary_node<T>::branch;
   13025             : 
   13026         300 :          assignment_rebasevec_celem_op_node(const operator_type& opr,
   13027             :                                             expression_ptr branch0,
   13028             :                                             expression_ptr branch1)
   13029             :          : binary_node<T>(opr, branch0, branch1)
   13030         300 :          , rbvec_node_ptr_(0)
   13031             :          {
   13032         300 :             if (is_rebasevector_celem_node(branch(0)))
   13033             :             {
   13034         300 :                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
   13035             :             }
   13036             : 
   13037         300 :             assert(valid());
   13038         300 :          }
   13039             : 
   13040         300 :          inline T value() const exprtk_override
   13041             :          {
   13042         300 :             T& v = rbvec_node_ptr_->ref();
   13043         300 :                v = Operation::process(v,branch(1)->value());
   13044             : 
   13045         300 :             return v;
   13046             :          }
   13047             : 
   13048         900 :          inline bool valid() const exprtk_override
   13049             :          {
   13050         900 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   13051             :          }
   13052             : 
   13053             :       private:
   13054             : 
   13055             :          rebasevector_celem_node<T>* rbvec_node_ptr_;
   13056             :       };
   13057             : 
   13058             :       template <typename T, typename Operation>
   13059             :       class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T>
   13060             :       {
   13061             :       public:
   13062             : 
   13063             :          typedef expression_node<T>* expression_ptr;
   13064             :          using binary_node<T>::branch;
   13065             : 
   13066           0 :          assignment_rebasevec_elem_op_rtc_node(const operator_type& opr,
   13067             :                                                expression_ptr branch0,
   13068             :                                                expression_ptr branch1)
   13069             :          : binary_node<T>(opr, branch0, branch1)
   13070           0 :          , rbvec_node_ptr_(0)
   13071             :          {
   13072           0 :             if (is_rebasevector_elem_rtc_node(branch(0)))
   13073             :             {
   13074           0 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
   13075             :             }
   13076             : 
   13077           0 :             assert(valid());
   13078           0 :          }
   13079             : 
   13080           0 :          inline T value() const exprtk_override
   13081             :          {
   13082           0 :             T& v = rbvec_node_ptr_->ref();
   13083           0 :                v = Operation::process(v,branch(1)->value());
   13084             : 
   13085           0 :             return v;
   13086             :          }
   13087             : 
   13088           0 :          inline bool valid() const exprtk_override
   13089             :          {
   13090           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   13091             :          }
   13092             : 
   13093             :       private:
   13094             : 
   13095             :          rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
   13096             :       };
   13097             : 
   13098             :       template <typename T, typename Operation>
   13099             :       class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T>
   13100             :       {
   13101             :       public:
   13102             : 
   13103             :          typedef expression_node<T>* expression_ptr;
   13104             :          using binary_node<T>::branch;
   13105             : 
   13106           0 :          assignment_rebasevec_celem_op_rtc_node(const operator_type& opr,
   13107             :                                                 expression_ptr branch0,
   13108             :                                                 expression_ptr branch1)
   13109             :          : binary_node<T>(opr, branch0, branch1)
   13110           0 :          , rbvec_node_ptr_(0)
   13111             :          {
   13112           0 :             if (is_rebasevector_celem_rtc_node(branch(0)))
   13113             :             {
   13114           0 :                rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0));
   13115             :             }
   13116             : 
   13117           0 :             assert(valid());
   13118           0 :          }
   13119             : 
   13120           0 :          inline T value() const exprtk_override
   13121             :          {
   13122           0 :             T& v = rbvec_node_ptr_->ref();
   13123           0 :                v = Operation::process(v,branch(1)->value());
   13124             : 
   13125           0 :             return v;
   13126             :          }
   13127             : 
   13128           0 :          inline bool valid() const exprtk_override
   13129             :          {
   13130           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   13131             :          }
   13132             : 
   13133             :       private:
   13134             : 
   13135             :          rebasevector_celem_rtc_node<T>* rbvec_node_ptr_;
   13136             :       };
   13137             : 
   13138             :       template <typename T, typename Operation>
   13139             :       class assignment_vec_op_node exprtk_final
   13140             :                                    : public binary_node     <T>
   13141             :                                    , public vector_interface<T>
   13142             :       {
   13143             :       public:
   13144             : 
   13145             :          typedef expression_node<T>* expression_ptr;
   13146             :          typedef vector_node<T>*     vector_node_ptr;
   13147             :          typedef vec_data_store<T>   vds_t;
   13148             : 
   13149             :          using binary_node<T>::branch;
   13150             : 
   13151        2492 :          assignment_vec_op_node(const operator_type& opr,
   13152             :                                 expression_ptr branch0,
   13153             :                                 expression_ptr branch1)
   13154             :          : binary_node<T>(opr, branch0, branch1)
   13155        2492 :          , vec_node_ptr_(0)
   13156             :          {
   13157        2492 :             if (is_vector_node(branch(0)))
   13158             :             {
   13159        2492 :                vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   13160        2492 :                vds()         = vec_node_ptr_->vds();
   13161             :             }
   13162             : 
   13163        2492 :             assert(valid());
   13164        2492 :          }
   13165             : 
   13166        2519 :          inline T value() const exprtk_override
   13167             :          {
   13168        2519 :             const T v = branch(1)->value();
   13169             : 
   13170        2519 :             T* vec = vds().data();
   13171             : 
   13172        2519 :             loop_unroll::details lud(size());
   13173        2519 :             const T* upper_bound = vec + lud.upper_bound;
   13174             : 
   13175        2519 :             while (vec < upper_bound)
   13176             :             {
   13177             :                #define exprtk_loop(N)       \
   13178             :                Operation::assign(vec[N],v); \
   13179             : 
   13180           0 :                exprtk_loop( 0) exprtk_loop( 1)
   13181           0 :                exprtk_loop( 2) exprtk_loop( 3)
   13182             :                #ifndef exprtk_disable_superscalar_unroll
   13183           0 :                exprtk_loop( 4) exprtk_loop( 5)
   13184           0 :                exprtk_loop( 6) exprtk_loop( 7)
   13185           0 :                exprtk_loop( 8) exprtk_loop( 9)
   13186           0 :                exprtk_loop(10) exprtk_loop(11)
   13187           0 :                exprtk_loop(12) exprtk_loop(13)
   13188           0 :                exprtk_loop(14) exprtk_loop(15)
   13189             :                #endif
   13190             : 
   13191           0 :                vec += lud.batch_size;
   13192             :             }
   13193             : 
   13194        2519 :             switch (lud.remainder)
   13195             :             {
   13196             :                #define case_stmt(N,fall_through)     \
   13197             :                case N : Operation::assign(*vec++,v); \
   13198             :                fall_through                          \
   13199             : 
   13200             :                #ifndef exprtk_disable_superscalar_unroll
   13201           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   13202           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   13203           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   13204          18 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   13205          28 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   13206         338 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   13207             :                #endif
   13208        2194 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   13209        2519 :                case_stmt( 1, (void)0;)
   13210             :             }
   13211             : 
   13212             :             #undef exprtk_loop
   13213             :             #undef case_stmt
   13214             : 
   13215        5038 :             return vec_node_ptr_->value();
   13216             :          }
   13217             : 
   13218           0 :          vector_node_ptr vec() const exprtk_override
   13219             :          {
   13220           0 :             return vec_node_ptr_;
   13221             :          }
   13222             : 
   13223        2182 :          vector_node_ptr vec() exprtk_override
   13224             :          {
   13225        2182 :             return vec_node_ptr_;
   13226             :          }
   13227             : 
   13228       41763 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13229             :          {
   13230       41763 :             return expression_node<T>::e_vecopvalass;
   13231             :          }
   13232             : 
   13233       11913 :          inline bool valid() const exprtk_override
   13234             :          {
   13235             :             return
   13236       23826 :                vec_node_ptr_           &&
   13237       23826 :                (size() <= base_size()) &&
   13238       23826 :                binary_node<T>::valid() ;
   13239             :          }
   13240             : 
   13241       14492 :          std::size_t size() const exprtk_override
   13242             :          {
   13243       14492 :             return vec_node_ptr_->vec_holder().size();
   13244             :          }
   13245             : 
   13246       11913 :          std::size_t base_size() const exprtk_override
   13247             :          {
   13248       11913 :             return vec_node_ptr_->vec_holder().base_size();
   13249             :          }
   13250             : 
   13251        3334 :          vds_t& vds() exprtk_override
   13252             :          {
   13253        3334 :             return vds_;
   13254             :          }
   13255             : 
   13256        2519 :          const vds_t& vds() const exprtk_override
   13257             :          {
   13258        2519 :             return vds_;
   13259             :          }
   13260             : 
   13261         160 :          bool side_effect() const exprtk_override
   13262             :          {
   13263         160 :             return true;
   13264             :          }
   13265             : 
   13266             :       private:
   13267             : 
   13268             :          vector_node<T>* vec_node_ptr_;
   13269             :          vds_t           vds_;
   13270             :       };
   13271             : 
   13272             :       template <typename T, typename Operation>
   13273             :       class assignment_vecvec_op_node exprtk_final
   13274             :                                       : public binary_node     <T>
   13275             :                                       , public vector_interface<T>
   13276             :       {
   13277             :       public:
   13278             : 
   13279             :          typedef expression_node<T>* expression_ptr;
   13280             :          typedef vector_node<T>*     vector_node_ptr;
   13281             :          typedef vec_data_store<T>   vds_t;
   13282             : 
   13283             :          using binary_node<T>::branch;
   13284             : 
   13285         766 :          assignment_vecvec_op_node(const operator_type& opr,
   13286             :                                    expression_ptr branch0,
   13287             :                                    expression_ptr branch1)
   13288             :          : binary_node<T>(opr, branch0, branch1)
   13289         766 :          , vec0_node_ptr_(0)
   13290         766 :          , vec1_node_ptr_(0)
   13291         766 :          , initialised_(false)
   13292             :          {
   13293         766 :             if (is_vector_node(branch(0)))
   13294             :             {
   13295         766 :                vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   13296         766 :                vds()          = vec0_node_ptr_->vds();
   13297             :             }
   13298             : 
   13299         766 :             if (is_vector_node(branch(1)))
   13300             :             {
   13301         320 :                vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
   13302         320 :                vec1_node_ptr_->vds() = vds();
   13303             :             }
   13304         446 :             else if (is_ivector_node(branch(1)))
   13305             :             {
   13306         446 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13307             : 
   13308         446 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   13309             :                {
   13310         446 :                   vec1_node_ptr_ = vi->vec();
   13311         446 :                   vec1_node_ptr_->vds() = vi->vds();
   13312             :                }
   13313             :                else
   13314           0 :                   vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
   13315             :             }
   13316             : 
   13317         766 :             initialised_ =
   13318        1532 :                vec0_node_ptr_          &&
   13319         766 :                vec1_node_ptr_          &&
   13320        2298 :                (size() <= base_size()) &&
   13321         766 :                binary_node<T>::valid();
   13322             : 
   13323         766 :             assert(valid());
   13324         766 :          }
   13325             : 
   13326         766 :          inline T value() const exprtk_override
   13327             :          {
   13328         766 :             branch(0)->value();
   13329         766 :             branch(1)->value();
   13330             : 
   13331         766 :                   T* vec0 = vec0_node_ptr_->vds().data();
   13332         766 :             const T* vec1 = vec1_node_ptr_->vds().data();
   13333             : 
   13334         766 :             loop_unroll::details lud(size());
   13335         766 :             const T* upper_bound = vec0 + lud.upper_bound;
   13336             : 
   13337         766 :             while (vec0 < upper_bound)
   13338             :             {
   13339             :                #define exprtk_loop(N)                          \
   13340             :                vec0[N] = Operation::process(vec0[N], vec1[N]); \
   13341             : 
   13342           0 :                exprtk_loop( 0) exprtk_loop( 1)
   13343           0 :                exprtk_loop( 2) exprtk_loop( 3)
   13344             :                #ifndef exprtk_disable_superscalar_unroll
   13345           0 :                exprtk_loop( 4) exprtk_loop( 5)
   13346           0 :                exprtk_loop( 6) exprtk_loop( 7)
   13347           0 :                exprtk_loop( 8) exprtk_loop( 9)
   13348           0 :                exprtk_loop(10) exprtk_loop(11)
   13349           0 :                exprtk_loop(12) exprtk_loop(13)
   13350           0 :                exprtk_loop(14) exprtk_loop(15)
   13351             :                #endif
   13352             : 
   13353           0 :                vec0 += lud.batch_size;
   13354           0 :                vec1 += lud.batch_size;
   13355             :             }
   13356             : 
   13357         766 :             int i = 0;
   13358             : 
   13359         766 :             switch (lud.remainder)
   13360             :             {
   13361             :                #define case_stmt(N,fall_through)                                 \
   13362             :                case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
   13363             :                fall_through                                                      \
   13364             : 
   13365             :                #ifndef exprtk_disable_superscalar_unroll
   13366           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   13367           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   13368           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   13369          18 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   13370          18 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   13371         108 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   13372             :                #endif
   13373         646 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   13374         766 :                case_stmt( 1, (void)0;)
   13375             :             }
   13376             : 
   13377             :             #undef exprtk_loop
   13378             :             #undef case_stmt
   13379             : 
   13380        1532 :             return vec0_node_ptr_->value();
   13381             :          }
   13382             : 
   13383           0 :          vector_node_ptr vec() const exprtk_override
   13384             :          {
   13385           0 :             return vec0_node_ptr_;
   13386             :          }
   13387             : 
   13388           0 :          vector_node_ptr vec() exprtk_override
   13389             :          {
   13390           0 :             return vec0_node_ptr_;
   13391             :          }
   13392             : 
   13393        8426 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13394             :          {
   13395        8426 :             return expression_node<T>::e_vecopvecass;
   13396             :          }
   13397             : 
   13398        2298 :          inline bool valid() const exprtk_override
   13399             :          {
   13400        2298 :             return initialised_;
   13401             :          }
   13402             : 
   13403        1532 :          std::size_t size() const exprtk_override
   13404             :          {
   13405        1532 :             return std::min(
   13406        1532 :                vec0_node_ptr_->vec_holder().size(),
   13407        3064 :                vec1_node_ptr_->vec_holder().size());
   13408             :          }
   13409             : 
   13410         766 :          std::size_t base_size() const exprtk_override
   13411             :          {
   13412         766 :             return std::min(
   13413         766 :                vec0_node_ptr_->vec_holder().base_size(),
   13414        1532 :                vec1_node_ptr_->vec_holder().base_size());
   13415             :          }
   13416             : 
   13417        1086 :          vds_t& vds() exprtk_override
   13418             :          {
   13419        1086 :             return vds_;
   13420             :          }
   13421             : 
   13422           0 :          const vds_t& vds() const exprtk_override
   13423             :          {
   13424           0 :             return vds_;
   13425             :          }
   13426             : 
   13427           0 :          bool side_effect() const exprtk_override
   13428             :          {
   13429           0 :             return true;
   13430             :          }
   13431             : 
   13432             :       private:
   13433             : 
   13434             :          vector_node<T>* vec0_node_ptr_;
   13435             :          vector_node<T>* vec1_node_ptr_;
   13436             :          bool            initialised_;
   13437             :          vds_t           vds_;
   13438             :       };
   13439             : 
   13440             :       template <typename T>
   13441             :       struct memory_context_t
   13442             :       {
   13443             :          typedef vector_node<T>*  vector_node_ptr;
   13444             :          typedef vector_holder<T> vector_holder_t;
   13445             :          typedef vector_holder_t* vector_holder_ptr;
   13446             : 
   13447       44678 :          memory_context_t()
   13448       44678 :          : temp_(0)
   13449       44678 :          , temp_vec_node_(0)
   13450       44678 :          {}
   13451             : 
   13452       22339 :          void clear()
   13453             :          {
   13454       22339 :             delete temp_vec_node_;
   13455       22339 :             delete temp_;
   13456       22339 :          }
   13457             : 
   13458             :          vector_holder_ptr temp_;
   13459             :          vector_node_ptr   temp_vec_node_;
   13460             :       };
   13461             : 
   13462             :       template <typename T>
   13463       10891 :       inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder,
   13464             :                                                      vec_data_store<T>& vds)
   13465             :       {
   13466       10891 :          memory_context_t<T> result_ctxt;
   13467       21782 :          result_ctxt.temp_  = (vec_holder.rebaseable()) ?
   13468         359 :                               new vector_holder<T>(vec_holder,vds) :
   13469       10532 :                               new vector_holder<T>(vds) ;
   13470       10891 :          result_ctxt.temp_vec_node_ = new vector_node  <T>(vds,result_ctxt.temp_);
   13471       10891 :          return result_ctxt;
   13472             :       }
   13473             : 
   13474             :       template <typename T>
   13475       11448 :       inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0,
   13476             :                                                      vector_holder<T>& vec_holder1,
   13477             :                                                      vec_data_store<T>& vds)
   13478             :       {
   13479       11448 :          memory_context_t<T> result_ctxt;
   13480             : 
   13481       11448 :          if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable())
   13482       11329 :             result_ctxt.temp_ = new vector_holder<T>(vds);
   13483         119 :          else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable())
   13484          17 :             result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds);
   13485         102 :          else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable())
   13486          27 :             result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds);
   13487             :          else
   13488             :          {
   13489         150 :             result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ?
   13490          75 :                                 new vector_holder<T>(vec_holder0, vds) :
   13491           0 :                                 new vector_holder<T>(vec_holder1, vds) ;
   13492             :          }
   13493             : 
   13494       11448 :          result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_);
   13495       11448 :          return result_ctxt;
   13496             :       }
   13497             : 
   13498             :       template <typename T, typename Operation>
   13499             :       class vec_binop_vecvec_node exprtk_final
   13500             :                                   : public binary_node     <T>
   13501             :                                   , public vector_interface<T>
   13502             :       {
   13503             :       public:
   13504             : 
   13505             :          typedef expression_node<T>* expression_ptr;
   13506             :          typedef vector_node<T>*     vector_node_ptr;
   13507             :          typedef vector_holder<T>    vector_holder_t;
   13508             :          typedef vector_holder_t*    vector_holder_ptr;
   13509             :          typedef vec_data_store<T>   vds_t;
   13510             :          typedef memory_context_t<T> memory_context;
   13511             : 
   13512             :          using binary_node<T>::branch;
   13513             : 
   13514       10555 :          vec_binop_vecvec_node(const operator_type& opr,
   13515             :                                expression_ptr branch0,
   13516             :                                expression_ptr branch1)
   13517             :          : binary_node<T>(opr, branch0, branch1)
   13518       10555 :          , vec0_node_ptr_(0)
   13519       10555 :          , vec1_node_ptr_(0)
   13520       10555 :          , initialised_(false)
   13521             :          {
   13522       10555 :             bool v0_is_ivec = false;
   13523       10555 :             bool v1_is_ivec = false;
   13524             : 
   13525       10555 :             if (is_vector_node(branch(0)))
   13526             :             {
   13527        7351 :                vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
   13528             :             }
   13529        3204 :             else if (is_ivector_node(branch(0)))
   13530             :             {
   13531        3204 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13532             : 
   13533        3204 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
   13534             :                {
   13535        3204 :                   vec0_node_ptr_ = vi->vec();
   13536        3204 :                   v0_is_ivec     = true;
   13537             :                }
   13538             :             }
   13539             : 
   13540       10555 :             if (is_vector_node(branch(1)))
   13541             :             {
   13542        7418 :                vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
   13543             :             }
   13544        3137 :             else if (is_ivector_node(branch(1)))
   13545             :             {
   13546        3137 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13547             : 
   13548        3137 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   13549             :                {
   13550        3137 :                   vec1_node_ptr_ = vi->vec();
   13551        3137 :                   v1_is_ivec     = true;
   13552             :                }
   13553             :             }
   13554             : 
   13555       10555 :             if (vec0_node_ptr_ && vec1_node_ptr_)
   13556             :             {
   13557       10555 :                vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
   13558       10555 :                vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
   13559             : 
   13560       10555 :                if (v0_is_ivec && (vec0.base_size() <= vec1.base_size()))
   13561             :                {
   13562        2880 :                   vds_ = vds_t(vec0_node_ptr_->vds());
   13563             :                }
   13564        7675 :                else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size()))
   13565             :                {
   13566         968 :                   vds_ = vds_t(vec1_node_ptr_->vds());
   13567             :                }
   13568             :                else
   13569             :                {
   13570        6707 :                   vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size()));
   13571             :                }
   13572             : 
   13573       10555 :                memory_context_ = make_memory_context(vec0, vec1, vds());
   13574             : 
   13575       10555 :                initialised_ =
   13576       21110 :                   (size() <= base_size()) &&
   13577       10555 :                   binary_node<T>::valid();
   13578             :             }
   13579             : 
   13580       10555 :             assert(valid());
   13581       10555 :          }
   13582             : 
   13583       21110 :         ~vec_binop_vecvec_node()
   13584             :          {
   13585       10555 :             memory_context_.clear();
   13586       21110 :          }
   13587             : 
   13588       10484 :          inline T value() const exprtk_override
   13589             :          {
   13590       10484 :             branch(0)->value();
   13591       10484 :             branch(1)->value();
   13592             : 
   13593       10484 :             const T* vec0 = vec0_node_ptr_->vds().data();
   13594       10484 :             const T* vec1 = vec1_node_ptr_->vds().data();
   13595       10484 :                   T* vec2 = vds().data();
   13596             : 
   13597       10484 :             loop_unroll::details lud(size());
   13598       10484 :             const T* upper_bound = vec2 + lud.upper_bound;
   13599             : 
   13600    25947984 :             while (vec2 < upper_bound)
   13601             :             {
   13602             :                #define exprtk_loop(N)                          \
   13603             :                vec2[N] = Operation::process(vec0[N], vec1[N]); \
   13604             : 
   13605    25937500 :                exprtk_loop( 0) exprtk_loop( 1)
   13606    25937500 :                exprtk_loop( 2) exprtk_loop( 3)
   13607             :                #ifndef exprtk_disable_superscalar_unroll
   13608    25937500 :                exprtk_loop( 4) exprtk_loop( 5)
   13609    25937500 :                exprtk_loop( 6) exprtk_loop( 7)
   13610    25937500 :                exprtk_loop( 8) exprtk_loop( 9)
   13611    25937500 :                exprtk_loop(10) exprtk_loop(11)
   13612    25937500 :                exprtk_loop(12) exprtk_loop(13)
   13613    25937500 :                exprtk_loop(14) exprtk_loop(15)
   13614             :                #endif
   13615             : 
   13616    25937500 :                vec0 += lud.batch_size;
   13617    25937500 :                vec1 += lud.batch_size;
   13618    25937500 :                vec2 += lud.batch_size;
   13619             :             }
   13620             : 
   13621       10484 :             int i = 0;
   13622             : 
   13623       10484 :             switch (lud.remainder)
   13624             :             {
   13625             :                #define case_stmt(N)                                              \
   13626             :                case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
   13627             :                exprtk_fallthrough                                                \
   13628             : 
   13629             :                #ifndef exprtk_disable_superscalar_unroll
   13630           0 :                case_stmt(15) case_stmt(14)
   13631           0 :                case_stmt(13) case_stmt(12)
   13632           0 :                case_stmt(11) case_stmt(10)
   13633         695 :                case_stmt( 9) case_stmt( 8)
   13634         714 :                case_stmt( 7) case_stmt( 6)
   13635        3560 :                case_stmt( 5) case_stmt( 4)
   13636             :                #endif
   13637        9199 :                case_stmt( 3) case_stmt( 2)
   13638        9934 :                case_stmt( 1)
   13639       10484 :                default: break;
   13640             :             }
   13641             : 
   13642             :             #undef exprtk_loop
   13643             :             #undef case_stmt
   13644             : 
   13645       20968 :             return (vds().data())[0];
   13646             :          }
   13647             : 
   13648           0 :          vector_node_ptr vec() const exprtk_override
   13649             :          {
   13650           0 :             return memory_context_.temp_vec_node_;
   13651             :          }
   13652             : 
   13653        5901 :          vector_node_ptr vec() exprtk_override
   13654             :          {
   13655        5901 :             return memory_context_.temp_vec_node_;
   13656             :          }
   13657             : 
   13658       89888 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13659             :          {
   13660       89888 :             return expression_node<T>::e_vecvecarith;
   13661             :          }
   13662             : 
   13663       37491 :          inline bool valid() const exprtk_override
   13664             :          {
   13665       37491 :             return initialised_;
   13666             :          }
   13667             : 
   13668       22937 :          std::size_t size() const exprtk_override
   13669             :          {
   13670       22937 :             return std::min(
   13671       22937 :                vec0_node_ptr_->vec_holder().size(),
   13672       45874 :                vec1_node_ptr_->vec_holder().size());
   13673             :          }
   13674             : 
   13675       10555 :          std::size_t base_size() const exprtk_override
   13676             :          {
   13677       10555 :             return std::min(
   13678       10555 :                vec0_node_ptr_->vec_holder().base_size(),
   13679       21110 :                vec1_node_ptr_->vec_holder().base_size());
   13680             :          }
   13681             : 
   13682       12566 :          vds_t& vds() exprtk_override
   13683             :          {
   13684       12566 :             return vds_;
   13685             :          }
   13686             : 
   13687       20968 :          const vds_t& vds() const exprtk_override
   13688             :          {
   13689       20968 :             return vds_;
   13690             :          }
   13691             : 
   13692             :       private:
   13693             : 
   13694             :          vector_node_ptr vec0_node_ptr_;
   13695             :          vector_node_ptr vec1_node_ptr_;
   13696             :          bool            initialised_;
   13697             :          vds_t           vds_;
   13698             :          memory_context  memory_context_;
   13699             :       };
   13700             : 
   13701             :       template <typename T, typename Operation>
   13702             :       class vec_binop_vecval_node exprtk_final
   13703             :                                   : public binary_node     <T>
   13704             :                                   , public vector_interface<T>
   13705             :       {
   13706             :       public:
   13707             : 
   13708             :          typedef expression_node<T>* expression_ptr;
   13709             :          typedef vector_node<T>*     vector_node_ptr;
   13710             :          typedef vector_holder<T>    vector_holder_t;
   13711             :          typedef vector_holder_t*    vector_holder_ptr;
   13712             :          typedef vec_data_store<T>   vds_t;
   13713             :          typedef memory_context_t<T> memory_context;
   13714             : 
   13715             :          using binary_node<T>::branch;
   13716             : 
   13717        3999 :          vec_binop_vecval_node(const operator_type& opr,
   13718             :                                expression_ptr branch0,
   13719             :                                expression_ptr branch1)
   13720             :          : binary_node<T>(opr, branch0, branch1)
   13721        3999 :          , vec0_node_ptr_(0)
   13722             :          {
   13723        3999 :             bool v0_is_ivec = false;
   13724             : 
   13725        3999 :             if (is_vector_node(branch(0)))
   13726             :             {
   13727        2024 :                vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
   13728             :             }
   13729        1975 :             else if (is_ivector_node(branch(0)))
   13730             :             {
   13731        1975 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13732             : 
   13733        1975 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
   13734             :                {
   13735        1975 :                   vec0_node_ptr_ = vi->vec();
   13736        1975 :                   v0_is_ivec     = true;
   13737             :                }
   13738             :             }
   13739             : 
   13740        3999 :             if (vec0_node_ptr_)
   13741             :             {
   13742        3999 :                if (v0_is_ivec)
   13743        1975 :                   vds() = vec0_node_ptr_->vds();
   13744             :                else
   13745        2024 :                   vds() = vds_t(vec0_node_ptr_->base_size());
   13746             : 
   13747        3999 :                memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
   13748             :             }
   13749             : 
   13750        3999 :             assert(valid());
   13751        3999 :          }
   13752             : 
   13753        7998 :         ~vec_binop_vecval_node()
   13754             :          {
   13755        3999 :             memory_context_.clear();
   13756        7998 :          }
   13757             : 
   13758        5075 :          inline T value() const exprtk_override
   13759             :          {
   13760        5075 :                         branch(0)->value();
   13761        5075 :             const T v = branch(1)->value();
   13762             : 
   13763        5075 :             const T* vec0 = vec0_node_ptr_->vds().data();
   13764        5075 :                   T* vec1 = vds().data();
   13765             : 
   13766        5075 :             loop_unroll::details lud(size());
   13767        5075 :             const T* upper_bound = vec0 + lud.upper_bound;
   13768             : 
   13769    26317575 :             while (vec0 < upper_bound)
   13770             :             {
   13771             :                #define exprtk_loop(N)                    \
   13772             :                vec1[N] = Operation::process(vec0[N], v); \
   13773             : 
   13774    26312500 :                exprtk_loop( 0) exprtk_loop( 1)
   13775    26312500 :                exprtk_loop( 2) exprtk_loop( 3)
   13776             :                #ifndef exprtk_disable_superscalar_unroll
   13777    26312500 :                exprtk_loop( 4) exprtk_loop( 5)
   13778    26312500 :                exprtk_loop( 6) exprtk_loop( 7)
   13779    26312500 :                exprtk_loop( 8) exprtk_loop( 9)
   13780    26312500 :                exprtk_loop(10) exprtk_loop(11)
   13781    26312500 :                exprtk_loop(12) exprtk_loop(13)
   13782    26312500 :                exprtk_loop(14) exprtk_loop(15)
   13783             :                #endif
   13784             : 
   13785    26312500 :                vec0 += lud.batch_size;
   13786    26312500 :                vec1 += lud.batch_size;
   13787             :             }
   13788             : 
   13789        5075 :             int i = 0;
   13790             : 
   13791        5075 :             switch (lud.remainder)
   13792             :             {
   13793             :                #define case_stmt(N,fall_through)                           \
   13794             :                case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
   13795             :                fall_through                                                \
   13796             : 
   13797             :                #ifndef exprtk_disable_superscalar_unroll
   13798           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   13799           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   13800           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   13801         314 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   13802         414 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   13803        3430 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   13804             :                #endif
   13805        4337 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   13806        4465 :                case_stmt( 1, (void)0;)
   13807             :             }
   13808             : 
   13809             :             #undef exprtk_loop
   13810             :             #undef case_stmt
   13811             : 
   13812       10150 :             return (vds().data())[0];
   13813             :          }
   13814             : 
   13815           0 :          vector_node_ptr vec() const exprtk_override
   13816             :          {
   13817           0 :             return memory_context_.temp_vec_node_;
   13818             :          }
   13819             : 
   13820        3794 :          vector_node_ptr vec() exprtk_override
   13821             :          {
   13822        3794 :             return memory_context_.temp_vec_node_;
   13823             :          }
   13824             : 
   13825       43790 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13826             :          {
   13827       43790 :             return expression_node<T>::e_vecvalarith;
   13828             :          }
   13829             : 
   13830       24745 :          inline bool valid() const exprtk_override
   13831             :          {
   13832             :             return
   13833       49490 :                vec0_node_ptr_          &&
   13834       49490 :                (size() <= base_size()) &&
   13835       49490 :                binary_node<T>::valid();
   13836             :          }
   13837             : 
   13838       30279 :          std::size_t size() const exprtk_override
   13839             :          {
   13840       30279 :             return vec0_node_ptr_->size();
   13841             :          }
   13842             : 
   13843       24745 :          std::size_t base_size() const exprtk_override
   13844             :          {
   13845       24745 :             return vec0_node_ptr_->vec_holder().base_size();
   13846             :          }
   13847             : 
   13848        8509 :          vds_t& vds() exprtk_override
   13849             :          {
   13850        8509 :             return vds_;
   13851             :          }
   13852             : 
   13853       10150 :          const vds_t& vds() const exprtk_override
   13854             :          {
   13855       10150 :             return vds_;
   13856             :          }
   13857             : 
   13858             :       private:
   13859             : 
   13860             :          vector_node_ptr   vec0_node_ptr_;
   13861             :          vds_t             vds_;
   13862             :          memory_context    memory_context_;
   13863             :       };
   13864             : 
   13865             :       template <typename T, typename Operation>
   13866             :       class vec_binop_valvec_node exprtk_final
   13867             :                                   : public binary_node     <T>
   13868             :                                   , public vector_interface<T>
   13869             :       {
   13870             :       public:
   13871             : 
   13872             :          typedef expression_node<T>* expression_ptr;
   13873             :          typedef vector_node<T>*     vector_node_ptr;
   13874             :          typedef vector_holder<T>    vector_holder_t;
   13875             :          typedef vector_holder_t*    vector_holder_ptr;
   13876             :          typedef vec_data_store<T>   vds_t;
   13877             :          typedef memory_context_t<T> memory_context;
   13878             : 
   13879             :          using binary_node<T>::branch;
   13880             : 
   13881        4202 :          vec_binop_valvec_node(const operator_type& opr,
   13882             :                                expression_ptr branch0,
   13883             :                                expression_ptr branch1)
   13884             :          : binary_node<T>(opr, branch0, branch1)
   13885        4202 :          , vec1_node_ptr_(0)
   13886             :          {
   13887        4202 :             bool v1_is_ivec = false;
   13888             : 
   13889        4202 :             if (is_vector_node(branch(1)))
   13890             :             {
   13891        2512 :                vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
   13892             :             }
   13893        1690 :             else if (is_ivector_node(branch(1)))
   13894             :             {
   13895        1690 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13896             : 
   13897        1690 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   13898             :                {
   13899        1690 :                   vec1_node_ptr_ = vi->vec();
   13900        1690 :                   v1_is_ivec     = true;
   13901             :                }
   13902             :             }
   13903             : 
   13904        4202 :             if (vec1_node_ptr_)
   13905             :             {
   13906        4202 :                if (v1_is_ivec)
   13907        1690 :                   vds() = vec1_node_ptr_->vds();
   13908             :                else
   13909        2512 :                   vds() = vds_t(vec1_node_ptr_->base_size());
   13910             : 
   13911        4202 :                memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds());
   13912             :             }
   13913             : 
   13914        4202 :             assert(valid());
   13915        4202 :          }
   13916             : 
   13917        8404 :         ~vec_binop_valvec_node()
   13918             :          {
   13919        4202 :             memory_context_.clear();
   13920        8404 :          }
   13921             : 
   13922        5191 :          inline T value() const exprtk_override
   13923             :          {
   13924        5191 :             const T v = branch(0)->value();
   13925        5191 :                         branch(1)->value();
   13926             : 
   13927        5191 :                   T* vec0 = vds().data();
   13928        5191 :             const T* vec1 = vec1_node_ptr_->vds().data();
   13929             : 
   13930        5191 :             loop_unroll::details lud(size());
   13931        5191 :             const T* upper_bound = vec0 + lud.upper_bound;
   13932             : 
   13933    51317691 :             while (vec0 < upper_bound)
   13934             :             {
   13935             :                #define exprtk_loop(N)                    \
   13936             :                vec0[N] = Operation::process(v, vec1[N]); \
   13937             : 
   13938    51312500 :                exprtk_loop( 0) exprtk_loop( 1)
   13939    51312500 :                exprtk_loop( 2) exprtk_loop( 3)
   13940             :                #ifndef exprtk_disable_superscalar_unroll
   13941    51312500 :                exprtk_loop( 4) exprtk_loop( 5)
   13942    51312500 :                exprtk_loop( 6) exprtk_loop( 7)
   13943    51312500 :                exprtk_loop( 8) exprtk_loop( 9)
   13944    51312500 :                exprtk_loop(10) exprtk_loop(11)
   13945    51312500 :                exprtk_loop(12) exprtk_loop(13)
   13946    51312500 :                exprtk_loop(14) exprtk_loop(15)
   13947             :                #endif
   13948             : 
   13949    51312500 :                vec0 += lud.batch_size;
   13950    51312500 :                vec1 += lud.batch_size;
   13951             :             }
   13952             : 
   13953        5191 :             int i = 0;
   13954             : 
   13955        5191 :             switch (lud.remainder)
   13956             :             {
   13957             :                #define case_stmt(N,fall_through)                           \
   13958             :                case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
   13959             :                fall_through                                                \
   13960             : 
   13961             :                #ifndef exprtk_disable_superscalar_unroll
   13962           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   13963           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   13964           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   13965         167 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   13966         195 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   13967        3074 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   13968             :                #endif
   13969        4047 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   13970        4181 :                case_stmt( 1, (void)0;)
   13971             :             }
   13972             : 
   13973             :             #undef exprtk_loop
   13974             :             #undef case_stmt
   13975             : 
   13976       10382 :             return (vds().data())[0];
   13977             :          }
   13978             : 
   13979           0 :          vector_node_ptr vec() const exprtk_override
   13980             :          {
   13981           0 :             return memory_context_.temp_vec_node_;
   13982             :          }
   13983             : 
   13984        4094 :          vector_node_ptr vec() exprtk_override
   13985             :          {
   13986        4094 :             return memory_context_.temp_vec_node_;
   13987             :          }
   13988             : 
   13989       45625 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13990             :          {
   13991       45625 :             return expression_node<T>::e_vecvalarith;
   13992             :          }
   13993             : 
   13994       25595 :          inline bool valid() const exprtk_override
   13995             :          {
   13996             :             return
   13997       51190 :                vec1_node_ptr_               &&
   13998       25595 :                (size() <= base_size())      &&
   13999       76785 :                (vds_.size() <= base_size()) &&
   14000       51190 :                binary_node<T>::valid();
   14001             :          }
   14002             : 
   14003       31487 :          std::size_t size() const exprtk_override
   14004             :          {
   14005       31487 :             return vec1_node_ptr_->vec_holder().size();
   14006             :          }
   14007             : 
   14008       51190 :          std::size_t base_size() const exprtk_override
   14009             :          {
   14010       51190 :             return vec1_node_ptr_->vec_holder().base_size();
   14011             :          }
   14012             : 
   14013        8825 :          vds_t& vds() exprtk_override
   14014             :          {
   14015        8825 :             return vds_;
   14016             :          }
   14017             : 
   14018       10382 :          const vds_t& vds() const exprtk_override
   14019             :          {
   14020       10382 :             return vds_;
   14021             :          }
   14022             : 
   14023             :       private:
   14024             : 
   14025             :          vector_node_ptr   vec1_node_ptr_;
   14026             :          vds_t             vds_;
   14027             :          memory_context    memory_context_;
   14028             :       };
   14029             : 
   14030             :       template <typename T, typename Operation>
   14031             :       class unary_vector_node exprtk_final
   14032             :                               : public unary_node      <T>
   14033             :                               , public vector_interface<T>
   14034             :       {
   14035             :       public:
   14036             : 
   14037             :          typedef expression_node<T>* expression_ptr;
   14038             :          typedef vector_node<T>*     vector_node_ptr;
   14039             :          typedef vector_holder<T>    vector_holder_t;
   14040             :          typedef vector_holder_t*    vector_holder_ptr;
   14041             :          typedef vec_data_store<T>   vds_t;
   14042             :          typedef memory_context_t<T> memory_context;
   14043             : 
   14044             :          using expression_node<T>::branch;
   14045             : 
   14046        2690 :          unary_vector_node(const operator_type& opr, expression_ptr branch0)
   14047             :          : unary_node<T>(opr, branch0)
   14048        2690 :          , vec0_node_ptr_(0)
   14049             :          {
   14050        2690 :             bool vec0_is_ivec = false;
   14051             : 
   14052        2690 :             if (is_vector_node(branch(0)))
   14053             :             {
   14054         111 :                vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
   14055             :             }
   14056        2579 :             else if (is_ivector_node(branch(0)))
   14057             :             {
   14058        2579 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   14059             : 
   14060        2579 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
   14061             :                {
   14062        2579 :                   vec0_node_ptr_ = vi->vec();
   14063        2579 :                   vec0_is_ivec   = true;
   14064             :                }
   14065             :             }
   14066             : 
   14067        2690 :             if (vec0_node_ptr_)
   14068             :             {
   14069        2690 :                if (vec0_is_ivec)
   14070        2579 :                   vds_ = vec0_node_ptr_->vds();
   14071             :                else
   14072         111 :                   vds_ = vds_t(vec0_node_ptr_->base_size());
   14073             : 
   14074        2690 :                memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
   14075             :             }
   14076             : 
   14077        2690 :             assert(valid());
   14078        2690 :          }
   14079             : 
   14080        5380 :         ~unary_vector_node()
   14081             :          {
   14082        2690 :             memory_context_.clear();
   14083        5380 :          }
   14084             : 
   14085        2785 :          inline T value() const exprtk_override
   14086             :          {
   14087        2785 :             branch()->value();
   14088             : 
   14089        2785 :             const T* vec0 = vec0_node_ptr_->vds().data();
   14090        2785 :                   T* vec1 = vds().data();
   14091             : 
   14092        2785 :             loop_unroll::details lud(size());
   14093        2785 :             const T* upper_bound = vec0 + lud.upper_bound;
   14094             : 
   14095     1377785 :             while (vec0 < upper_bound)
   14096             :             {
   14097             :                #define exprtk_loop(N)                 \
   14098             :                vec1[N] = Operation::process(vec0[N]); \
   14099             : 
   14100     1375000 :                exprtk_loop( 0) exprtk_loop( 1)
   14101     1375000 :                exprtk_loop( 2) exprtk_loop( 3)
   14102             :                #ifndef exprtk_disable_superscalar_unroll
   14103     1375000 :                exprtk_loop( 4) exprtk_loop( 5)
   14104     1375000 :                exprtk_loop( 6) exprtk_loop( 7)
   14105     1375000 :                exprtk_loop( 8) exprtk_loop( 9)
   14106     1375000 :                exprtk_loop(10) exprtk_loop(11)
   14107     1375000 :                exprtk_loop(12) exprtk_loop(13)
   14108     1375000 :                exprtk_loop(14) exprtk_loop(15)
   14109             :                #endif
   14110             : 
   14111     1375000 :                vec0 += lud.batch_size;
   14112     1375000 :                vec1 += lud.batch_size;
   14113             :             }
   14114             : 
   14115        2785 :             int i = 0;
   14116             : 
   14117        2785 :             switch (lud.remainder)
   14118             :             {
   14119             :                #define case_stmt(N)                                     \
   14120             :                case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
   14121             :                exprtk_fallthrough                                       \
   14122             : 
   14123             :                #ifndef exprtk_disable_superscalar_unroll
   14124           0 :                case_stmt(15) case_stmt(14)
   14125           0 :                case_stmt(13) case_stmt(12)
   14126           0 :                case_stmt(11) case_stmt(10)
   14127         125 :                case_stmt( 9) case_stmt( 8)
   14128         125 :                case_stmt( 7) case_stmt( 6)
   14129        2485 :                case_stmt( 5) case_stmt( 4)
   14130             :                #endif
   14131        2565 :                case_stmt( 3) case_stmt( 2)
   14132        2565 :                case_stmt( 1)
   14133        2785 :                default: break;
   14134             :             }
   14135             : 
   14136             :             #undef exprtk_loop
   14137             :             #undef case_stmt
   14138             : 
   14139        5570 :             return (vds().data())[0];
   14140             :          }
   14141             : 
   14142           0 :          vector_node_ptr vec() const exprtk_override
   14143             :          {
   14144           0 :             return memory_context_.temp_vec_node_;
   14145             :          }
   14146             : 
   14147        2690 :          vector_node_ptr vec() exprtk_override
   14148             :          {
   14149        2690 :             return memory_context_.temp_vec_node_;
   14150             :          }
   14151             : 
   14152       30387 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14153             :          {
   14154       30387 :             return expression_node<T>::e_vecunaryop;
   14155             :          }
   14156             : 
   14157       17164 :          inline bool valid() const exprtk_override
   14158             :          {
   14159       17164 :             return vec0_node_ptr_ && unary_node<T>::valid();
   14160             :          }
   14161             : 
   14162        2865 :          std::size_t size() const exprtk_override
   14163             :          {
   14164        2865 :             return vec0_node_ptr_->vec_holder().size();
   14165             :          }
   14166             : 
   14167           0 :          std::size_t base_size() const exprtk_override
   14168             :          {
   14169           0 :             return vec0_node_ptr_->vec_holder().base_size();
   14170             :          }
   14171             : 
   14172        2770 :          vds_t& vds() exprtk_override
   14173             :          {
   14174        2770 :             return vds_;
   14175             :          }
   14176             : 
   14177        5570 :          const vds_t& vds() const exprtk_override
   14178             :          {
   14179        5570 :             return vds_;
   14180             :          }
   14181             : 
   14182             :       private:
   14183             : 
   14184             :          vector_node_ptr vec0_node_ptr_;
   14185             :          vds_t           vds_;
   14186             :          memory_context  memory_context_;
   14187             :       };
   14188             : 
   14189             :       template <typename T>
   14190             :       class conditional_vector_node exprtk_final
   14191             :                                     : public expression_node <T>
   14192             :                                     , public vector_interface<T>
   14193             :       {
   14194             :       public:
   14195             : 
   14196             :          typedef expression_node <T>* expression_ptr;
   14197             :          typedef vector_interface<T>* vec_interface_ptr;
   14198             :          typedef vector_node     <T>* vector_node_ptr;
   14199             :          typedef vector_holder   <T>  vector_holder_t;
   14200             :          typedef vector_holder_t*     vector_holder_ptr;
   14201             :          typedef vec_data_store  <T>  vds_t;
   14202             :          typedef memory_context_t<T> memory_context;
   14203             :          typedef std::pair<expression_ptr,bool> branch_t;
   14204             : 
   14205         893 :          conditional_vector_node(expression_ptr condition,
   14206             :                                  expression_ptr consequent,
   14207             :                                  expression_ptr alternative)
   14208         893 :          : consequent_node_ptr_ (0)
   14209         893 :          , alternative_node_ptr_(0)
   14210         893 :          , temp_vec_node_       (0)
   14211         893 :          , temp_                (0)
   14212         893 :          , result_vec_size_     (0)
   14213         893 :          , initialised_         (false)
   14214             :          {
   14215         893 :             construct_branch_pair(condition_  , condition  );
   14216         893 :             construct_branch_pair(consequent_ , consequent );
   14217         893 :             construct_branch_pair(alternative_, alternative);
   14218             : 
   14219         893 :             if (details::is_ivector_node(consequent_.first))
   14220             :             {
   14221         893 :                vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first);
   14222             : 
   14223         893 :                if (0 != ivec_ptr)
   14224             :                {
   14225         893 :                   consequent_node_ptr_ = ivec_ptr->vec();
   14226             :                }
   14227             :             }
   14228             : 
   14229         893 :             if (details::is_ivector_node(alternative_.first))
   14230             :             {
   14231         893 :                vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first);
   14232             : 
   14233         893 :                if (0 != ivec_ptr)
   14234             :                {
   14235         893 :                   alternative_node_ptr_ = ivec_ptr->vec();
   14236             :                }
   14237             :             }
   14238             : 
   14239         893 :             if (consequent_node_ptr_ && alternative_node_ptr_)
   14240             :             {
   14241         893 :                const std::size_t vec_size =
   14242         893 :                   std::max(consequent_node_ptr_ ->vec_holder().base_size(),
   14243         893 :                            alternative_node_ptr_->vec_holder().base_size());
   14244             : 
   14245         893 :                vds_            = vds_t(vec_size);
   14246         893 :                memory_context_ = make_memory_context(
   14247         893 :                   consequent_node_ptr_ ->vec_holder(),
   14248         893 :                   alternative_node_ptr_->vec_holder(),
   14249         893 :                   vds());
   14250             : 
   14251         893 :                initialised_ = (vec_size > 0);
   14252             :             }
   14253             : 
   14254         893 :             assert(initialised_);
   14255         893 :          }
   14256             : 
   14257        1786 :         ~conditional_vector_node()
   14258             :          {
   14259         893 :             memory_context_.clear();
   14260        1786 :          }
   14261             : 
   14262         902 :          inline T value() const exprtk_override
   14263             :          {
   14264         902 :             T result = T(0);
   14265         902 :             T* source_vector = 0;
   14266         902 :             T* result_vector = vds().data();
   14267             : 
   14268         902 :             if (is_true(condition_))
   14269             :             {
   14270         462 :                result           = consequent_.first->value();
   14271         462 :                source_vector    = consequent_node_ptr_->vds().data();
   14272         462 :                result_vec_size_ = consequent_node_ptr_->size();
   14273             :             }
   14274             :             else
   14275             :             {
   14276         440 :                result           = alternative_.first->value();
   14277         440 :                source_vector    = alternative_node_ptr_->vds().data();
   14278         440 :                result_vec_size_ = alternative_node_ptr_->size();
   14279             :             }
   14280             : 
   14281        3760 :             for (std::size_t i = 0; i < result_vec_size_; ++i)
   14282             :             {
   14283        2858 :                result_vector[i] = source_vector[i];
   14284             :             }
   14285             : 
   14286         902 :             return result;
   14287             :          }
   14288             : 
   14289           0 :          vector_node_ptr vec() const exprtk_override
   14290             :          {
   14291           0 :             return memory_context_.temp_vec_node_;
   14292             :          }
   14293             : 
   14294         902 :          vector_node_ptr vec() exprtk_override
   14295             :          {
   14296         902 :             return memory_context_.temp_vec_node_;
   14297             :          }
   14298             : 
   14299       11704 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14300             :          {
   14301       11704 :             return expression_node<T>::e_vecondition;
   14302             :          }
   14303             : 
   14304        1786 :          inline bool valid() const exprtk_override
   14305             :          {
   14306             :             return
   14307        3572 :                initialised_                                      &&
   14308        1786 :                condition_  .first && condition_  .first->valid() &&
   14309        1786 :                consequent_ .first && consequent_ .first->valid() &&
   14310        5358 :                alternative_.first && alternative_.first->valid() &&
   14311        3572 :                size() <= base_size();
   14312             :          }
   14313             : 
   14314        1808 :          std::size_t size() const exprtk_override
   14315             :          {
   14316        1808 :             return result_vec_size_;
   14317             :          }
   14318             : 
   14319        1786 :          std::size_t base_size() const exprtk_override
   14320             :          {
   14321        1786 :             return std::min(
   14322        1786 :                consequent_node_ptr_ ->vec_holder().base_size(),
   14323        3572 :                alternative_node_ptr_->vec_holder().base_size());
   14324             :          }
   14325             : 
   14326         893 :          vds_t& vds() exprtk_override
   14327             :          {
   14328         893 :             return vds_;
   14329             :          }
   14330             : 
   14331         902 :          const vds_t& vds() const exprtk_override
   14332             :          {
   14333         902 :             return vds_;
   14334             :          }
   14335             : 
   14336         893 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14337             :          {
   14338         893 :             expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
   14339         893 :             expression_node<T>::ndb_t::collect(consequent_  , node_delete_list);
   14340         893 :             expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
   14341         893 :          }
   14342             : 
   14343        2279 :          std::size_t node_depth() const exprtk_override
   14344             :          {
   14345             :             return expression_node<T>::ndb_t::compute_node_depth
   14346        2279 :                (condition_, consequent_, alternative_);
   14347             :          }
   14348             : 
   14349             :       private:
   14350             : 
   14351             :          branch_t            condition_;
   14352             :          branch_t            consequent_;
   14353             :          branch_t            alternative_;
   14354             :          vector_node_ptr     consequent_node_ptr_;
   14355             :          vector_node_ptr     alternative_node_ptr_;
   14356             :          vector_node_ptr     temp_vec_node_;
   14357             :          vector_holder_ptr   temp_;
   14358             :          vds_t               vds_;
   14359             :          mutable std::size_t result_vec_size_;
   14360             :          bool                initialised_;
   14361             :          memory_context      memory_context_;
   14362             :       };
   14363             : 
   14364             :       template <typename T>
   14365             :       class scand_node exprtk_final : public binary_node<T>
   14366             :       {
   14367             :       public:
   14368             : 
   14369             :          typedef expression_node<T>* expression_ptr;
   14370             :          using binary_node<T>::branch;
   14371             : 
   14372         120 :          scand_node(const operator_type& opr,
   14373             :                     expression_ptr branch0,
   14374             :                     expression_ptr branch1)
   14375         120 :          : binary_node<T>(opr, branch0, branch1)
   14376             :          {
   14377         120 :             assert(binary_node<T>::valid());
   14378         120 :          }
   14379             : 
   14380         105 :          inline T value() const exprtk_override
   14381             :          {
   14382             :             return (
   14383         105 :                      std::not_equal_to<T>()
   14384         210 :                         (T(0),branch(0)->value()) &&
   14385           0 :                      std::not_equal_to<T>()
   14386         210 :                         (T(0),branch(1)->value())
   14387         315 :                    ) ? T(1) : T(0);
   14388             :          }
   14389             :       };
   14390             : 
   14391             :       template <typename T>
   14392             :       class scor_node exprtk_final : public binary_node<T>
   14393             :       {
   14394             :       public:
   14395             : 
   14396             :          typedef expression_node<T>* expression_ptr;
   14397             :          using binary_node<T>::branch;
   14398             : 
   14399         105 :          scor_node(const operator_type& opr,
   14400             :                    expression_ptr branch0,
   14401             :                    expression_ptr branch1)
   14402         105 :          : binary_node<T>(opr, branch0, branch1)
   14403             :          {
   14404         105 :             assert(binary_node<T>::valid());
   14405         105 :          }
   14406             : 
   14407         105 :          inline T value() const exprtk_override
   14408             :          {
   14409             :             return (
   14410         105 :                      std::not_equal_to<T>()
   14411         210 :                         (T(0),branch(0)->value()) ||
   14412           0 :                      std::not_equal_to<T>()
   14413         210 :                         (T(0),branch(1)->value())
   14414         315 :                    ) ? T(1) : T(0);
   14415             :          }
   14416             :       };
   14417             : 
   14418             :       template <typename T, typename IFunction, std::size_t N>
   14419             :       class function_N_node exprtk_final : public expression_node<T>
   14420             :       {
   14421             :       public:
   14422             : 
   14423             :          // Function of N parameters.
   14424             :          typedef expression_node<T>* expression_ptr;
   14425             :          typedef std::pair<expression_ptr,bool> branch_t;
   14426             :          typedef IFunction ifunction;
   14427             : 
   14428       60380 :          explicit function_N_node(ifunction* func)
   14429       60380 :          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
   14430       60380 :          , parameter_count_(func->param_count)
   14431       60380 :          , initialised_(false)
   14432       60380 :          {}
   14433             : 
   14434             :          template <std::size_t NumBranches>
   14435      120640 :          bool init_branches(expression_ptr (&b)[NumBranches])
   14436             :          {
   14437             :             // Needed for incompetent and broken msvc compiler versions
   14438             :             #ifdef _MSC_VER
   14439             :              #pragma warning(push)
   14440             :              #pragma warning(disable: 4127)
   14441             :             #endif
   14442             : 
   14443             :             if (N != NumBranches)
   14444             :             {
   14445             :                return false;
   14446             :             }
   14447             : 
   14448      519718 :             for (std::size_t i = 0; i < NumBranches; ++i)
   14449             :             {
   14450      399078 :                if (b[i] && b[i]->valid())
   14451      399078 :                   branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
   14452             :                else
   14453           0 :                   return false;
   14454             :             }
   14455             : 
   14456      120640 :             initialised_ = function_;
   14457      120640 :             assert(valid());
   14458      120640 :             return initialised_;
   14459             : 
   14460             :             #ifdef _MSC_VER
   14461             :              #pragma warning(pop)
   14462             :             #endif
   14463             :          }
   14464             : 
   14465             :          inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
   14466             :          {
   14467             :             return this < (&fn);
   14468             :          }
   14469             : 
   14470    45898398 :          inline T value() const exprtk_override
   14471             :          {
   14472             :             // Needed for incompetent and broken msvc compiler versions
   14473             :             #ifdef _MSC_VER
   14474             :              #pragma warning(push)
   14475             :              #pragma warning(disable: 4127)
   14476             :             #endif
   14477             : 
   14478             :             T v[N];
   14479    45898398 :             evaluate_branches<T,N>::execute(v,branch_);
   14480    91796796 :             return invoke<T,N>::execute(*function_,v);
   14481             : 
   14482             :             #ifdef _MSC_VER
   14483             :              #pragma warning(pop)
   14484             :             #endif
   14485             :          }
   14486             : 
   14487     1635343 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14488             :          {
   14489     1635343 :             return expression_node<T>::e_function;
   14490             :          }
   14491             : 
   14492     1042604 :          inline bool valid() const exprtk_override
   14493             :          {
   14494     1042604 :             return initialised_;
   14495             :          }
   14496             : 
   14497       60380 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14498             :          {
   14499       60380 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   14500       60380 :          }
   14501             : 
   14502      176077 :          std::size_t node_depth() const exprtk_override
   14503             :          {
   14504      176077 :             return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
   14505             :          }
   14506             : 
   14507             :          template <typename T_, std::size_t BranchCount>
   14508             :          struct evaluate_branches
   14509             :          {
   14510        8120 :             static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
   14511             :             {
   14512       93380 :                for (std::size_t i = 0; i < BranchCount; ++i)
   14513             :                {
   14514       85260 :                   v[i] = b[i].first->value();
   14515             :                }
   14516        8120 :             }
   14517             :          };
   14518             : 
   14519             :          template <typename T_>
   14520             :          struct evaluate_branches <T_,6>
   14521             :          {
   14522        1215 :             static inline void execute(T_ (&v)[6], const branch_t (&b)[6])
   14523             :             {
   14524        1215 :                v[0] = b[0].first->value();
   14525        1215 :                v[1] = b[1].first->value();
   14526        1215 :                v[2] = b[2].first->value();
   14527        1215 :                v[3] = b[3].first->value();
   14528        1215 :                v[4] = b[4].first->value();
   14529        1215 :                v[5] = b[5].first->value();
   14530        1215 :             }
   14531             :          };
   14532             : 
   14533             :          template <typename T_>
   14534             :          struct evaluate_branches <T_,5>
   14535             :          {
   14536        2024 :             static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
   14537             :             {
   14538        2024 :                v[0] = b[0].first->value();
   14539        2024 :                v[1] = b[1].first->value();
   14540        2024 :                v[2] = b[2].first->value();
   14541        2024 :                v[3] = b[3].first->value();
   14542        2024 :                v[4] = b[4].first->value();
   14543        2024 :             }
   14544             :          };
   14545             : 
   14546             :          template <typename T_>
   14547             :          struct evaluate_branches <T_,4>
   14548             :          {
   14549        5288 :             static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
   14550             :             {
   14551        5288 :                v[0] = b[0].first->value();
   14552        5288 :                v[1] = b[1].first->value();
   14553        5288 :                v[2] = b[2].first->value();
   14554        5288 :                v[3] = b[3].first->value();
   14555        5288 :             }
   14556             :          };
   14557             : 
   14558             :          template <typename T_>
   14559             :          struct evaluate_branches <T_,3>
   14560             :          {
   14561       13924 :             static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
   14562             :             {
   14563       13924 :                v[0] = b[0].first->value();
   14564       13924 :                v[1] = b[1].first->value();
   14565       13924 :                v[2] = b[2].first->value();
   14566       13924 :             }
   14567             :          };
   14568             : 
   14569             :          template <typename T_>
   14570             :          struct evaluate_branches <T_,2>
   14571             :          {
   14572      156842 :             static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
   14573             :             {
   14574      156842 :                v[0] = b[0].first->value();
   14575      156842 :                v[1] = b[1].first->value();
   14576      156842 :             }
   14577             :          };
   14578             : 
   14579             :          template <typename T_>
   14580             :          struct evaluate_branches <T_,1>
   14581             :          {
   14582    45710985 :             static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
   14583             :             {
   14584    45710985 :                v[0] = b[0].first->value();
   14585    45710985 :             }
   14586             :          };
   14587             : 
   14588             :          template <typename T_, std::size_t ParamCount>
   14589             :          struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
   14590             : 
   14591             :          template <typename T_>
   14592             :          struct invoke<T_,20>
   14593             :          {
   14594           0 :             static inline T_ execute(ifunction& f, T_ (&v)[20])
   14595           0 :             { 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]); }
   14596             :          };
   14597             : 
   14598             :          template <typename T_>
   14599             :          struct invoke<T_,19>
   14600             :          {
   14601           0 :             static inline T_ execute(ifunction& f, T_ (&v)[19])
   14602           0 :             { 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]); }
   14603             :          };
   14604             : 
   14605             :          template <typename T_>
   14606             :          struct invoke<T_,18>
   14607             :          {
   14608           0 :             static inline T_ execute(ifunction& f, T_ (&v)[18])
   14609           0 :             { 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]); }
   14610             :          };
   14611             : 
   14612             :          template <typename T_>
   14613             :          struct invoke<T_,17>
   14614             :          {
   14615           0 :             static inline T_ execute(ifunction& f, T_ (&v)[17])
   14616           0 :             { 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]); }
   14617             :          };
   14618             : 
   14619             :          template <typename T_>
   14620             :          struct invoke<T_,16>
   14621             :          {
   14622           0 :             static inline T_ execute(ifunction& f, T_ (&v)[16])
   14623           0 :             { 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]); }
   14624             :          };
   14625             : 
   14626             :          template <typename T_>
   14627             :          struct invoke<T_,15>
   14628             :          {
   14629           0 :             static inline T_ execute(ifunction& f, T_ (&v)[15])
   14630           0 :             { 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]); }
   14631             :          };
   14632             : 
   14633             :          template <typename T_>
   14634             :          struct invoke<T_,14>
   14635             :          {
   14636        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[14])
   14637        1015 :             { 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]); }
   14638             :          };
   14639             : 
   14640             :          template <typename T_>
   14641             :          struct invoke<T_,13>
   14642             :          {
   14643        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[13])
   14644        1015 :             { 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]); }
   14645             :          };
   14646             : 
   14647             :          template <typename T_>
   14648             :          struct invoke<T_,12>
   14649             :          {
   14650        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[12])
   14651        1015 :             { 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]); }
   14652             :          };
   14653             : 
   14654             :          template <typename T_>
   14655             :          struct invoke<T_,11>
   14656             :          {
   14657        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[11])
   14658        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); }
   14659             :          };
   14660             : 
   14661             :          template <typename T_>
   14662             :          struct invoke<T_,10>
   14663             :          {
   14664        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[10])
   14665        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); }
   14666             :          };
   14667             : 
   14668             :          template <typename T_>
   14669             :          struct invoke<T_,9>
   14670             :          {
   14671        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[9])
   14672        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); }
   14673             :          };
   14674             : 
   14675             :          template <typename T_>
   14676             :          struct invoke<T_,8>
   14677             :          {
   14678        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[8])
   14679        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); }
   14680             :          };
   14681             : 
   14682             :          template <typename T_>
   14683             :          struct invoke<T_,7>
   14684             :          {
   14685        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[7])
   14686        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); }
   14687             :          };
   14688             : 
   14689             :          template <typename T_>
   14690             :          struct invoke<T_,6>
   14691             :          {
   14692        1215 :             static inline T_ execute(ifunction& f, T_ (&v)[6])
   14693        1215 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5]); }
   14694             :          };
   14695             : 
   14696             :          template <typename T_>
   14697             :          struct invoke<T_,5>
   14698             :          {
   14699        2024 :             static inline T_ execute(ifunction& f, T_ (&v)[5])
   14700        2024 :             { return f(v[0], v[1], v[2], v[3], v[4]); }
   14701             :          };
   14702             : 
   14703             :          template <typename T_>
   14704             :          struct invoke<T_,4>
   14705             :          {
   14706        5288 :             static inline T_ execute(ifunction& f, T_ (&v)[4])
   14707        5288 :             { return f(v[0], v[1], v[2], v[3]); }
   14708             :          };
   14709             : 
   14710             :          template <typename T_>
   14711             :          struct invoke<T_,3>
   14712             :          {
   14713       13924 :             static inline T_ execute(ifunction& f, T_ (&v)[3])
   14714       13924 :             { return f(v[0], v[1], v[2]); }
   14715             :          };
   14716             : 
   14717             :          template <typename T_>
   14718             :          struct invoke<T_,2>
   14719             :          {
   14720      156842 :             static inline T_ execute(ifunction& f, T_ (&v)[2])
   14721      156842 :             { return f(v[0], v[1]); }
   14722             :          };
   14723             : 
   14724             :          template <typename T_>
   14725             :          struct invoke<T_,1>
   14726             :          {
   14727    45710985 :             static inline T_ execute(ifunction& f, T_ (&v)[1])
   14728    45710985 :             { return f(v[0]); }
   14729             :          };
   14730             : 
   14731             :       private:
   14732             : 
   14733             :          ifunction*  function_;
   14734             :          std::size_t parameter_count_;
   14735             :          branch_t    branch_[N];
   14736             :          bool        initialised_;
   14737             :       };
   14738             : 
   14739             :       template <typename T, typename IFunction>
   14740             :       class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T>
   14741             :       {
   14742             :       public:
   14743             : 
   14744             :          typedef expression_node<T>* expression_ptr;
   14745             :          typedef IFunction ifunction;
   14746             : 
   14747         231 :          explicit function_N_node(ifunction* func)
   14748         231 :          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
   14749             :          {
   14750         231 :             assert(valid());
   14751         231 :          }
   14752             : 
   14753             :          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
   14754             :          {
   14755             :             return this < (&fn);
   14756             :          }
   14757             : 
   14758       77530 :          inline T value() const exprtk_override
   14759             :          {
   14760       77530 :             return (*function_)();
   14761             :          }
   14762             : 
   14763        3981 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14764             :          {
   14765        3981 :             return expression_node<T>::e_function;
   14766             :          }
   14767             : 
   14768         501 :          inline bool valid() const exprtk_override
   14769             :          {
   14770         501 :             return function_;
   14771             :          }
   14772             : 
   14773             :       private:
   14774             : 
   14775             :          ifunction* function_;
   14776             :       };
   14777             : 
   14778             :       template <typename T, typename VarArgFunction>
   14779             :       class vararg_function_node exprtk_final : public expression_node<T>
   14780             :       {
   14781             :       public:
   14782             : 
   14783             :          typedef expression_node<T>* expression_ptr;
   14784             : 
   14785          49 :          vararg_function_node(VarArgFunction*  func,
   14786             :                               const std::vector<expression_ptr>& arg_list)
   14787          49 :          : function_(func)
   14788          49 :          , arg_list_(arg_list)
   14789             :          {
   14790          49 :             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
   14791          49 :             assert(valid());
   14792          49 :          }
   14793             : 
   14794             :          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
   14795             :          {
   14796             :             return this < (&fn);
   14797             :          }
   14798             : 
   14799          49 :          inline T value() const exprtk_override
   14800             :          {
   14801          49 :             populate_value_list();
   14802          49 :             return (*function_)(value_list_);
   14803             :          }
   14804             : 
   14805         344 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14806             :          {
   14807         344 :             return expression_node<T>::e_vafunction;
   14808             :          }
   14809             : 
   14810         131 :          inline bool valid() const exprtk_override
   14811             :          {
   14812         131 :             return function_;
   14813             :          }
   14814             : 
   14815          49 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14816             :          {
   14817         166 :             for (std::size_t i = 0; i < arg_list_.size(); ++i)
   14818             :             {
   14819         117 :                if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
   14820             :                {
   14821          69 :                   node_delete_list.push_back(&arg_list_[i]);
   14822             :                }
   14823             :             }
   14824          49 :          }
   14825             : 
   14826         144 :          std::size_t node_depth() const exprtk_override
   14827             :          {
   14828         144 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
   14829             :          }
   14830             : 
   14831             :       private:
   14832             : 
   14833          49 :          inline void populate_value_list() const
   14834             :          {
   14835         166 :             for (std::size_t i = 0; i < arg_list_.size(); ++i)
   14836             :             {
   14837         117 :                value_list_[i] = arg_list_[i]->value();
   14838             :             }
   14839          49 :          }
   14840             : 
   14841             :          VarArgFunction* function_;
   14842             :          std::vector<expression_ptr> arg_list_;
   14843             :          mutable std::vector<T> value_list_;
   14844             :       };
   14845             : 
   14846             :       template <typename T, typename GenericFunction>
   14847             :       class generic_function_node : public expression_node<T>
   14848             :       {
   14849             :       public:
   14850             : 
   14851             :          typedef type_store<T>       type_store_t;
   14852             :          typedef expression_node<T>* expression_ptr;
   14853             :          typedef variable_node<T>    variable_node_t;
   14854             :          typedef vector_node<T>      vector_node_t;
   14855             :          typedef variable_node_t*    variable_node_ptr_t;
   14856             :          typedef vector_node_t*      vector_node_ptr_t;
   14857             :          typedef range_interface<T>  range_interface_t;
   14858             :          typedef range_data_type<T>  range_data_type_t;
   14859             :          typedef typename range_interface<T>::range_t range_t;
   14860             : 
   14861             :          typedef std::pair<expression_ptr,bool> branch_t;
   14862             :          typedef vector_holder<T>* vh_t;
   14863             :          typedef vector_view<T>*   vecview_t;
   14864             : 
   14865             :          typedef std::vector<T>                 tmp_vs_t;
   14866             :          typedef std::vector<type_store_t>      typestore_list_t;
   14867             :          typedef std::vector<range_data_type_t> range_list_t;
   14868             : 
   14869        3724 :          explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
   14870             :                                         GenericFunction* func = reinterpret_cast<GenericFunction*>(0))
   14871        3724 :          : function_(func)
   14872        3724 :          , arg_list_(arg_list)
   14873        3724 :          {}
   14874             : 
   14875        3781 :          virtual ~generic_function_node()
   14876             :          {
   14877       11989 :             for (std::size_t i = 0; i < vv_list_.size(); ++i)
   14878             :             {
   14879        8265 :                vecview_t& vv = vv_list_[i];
   14880        8265 :                if (vv && typestore_list_[i].vec_data)
   14881             :                {
   14882         111 :                   vv->remove_ref(&typestore_list_[i].vec_data);
   14883         111 :                   typestore_list_[i].vec_data = 0;
   14884             :                }
   14885             :             }
   14886        7505 :          }
   14887             : 
   14888        3724 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14889             :          {
   14890        3724 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   14891        3724 :          }
   14892             : 
   14893        7609 :          std::size_t node_depth() const exprtk_override exprtk_final
   14894             :          {
   14895        7609 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   14896             :          }
   14897             : 
   14898        3724 :          virtual bool init_branches()
   14899             :          {
   14900        3724 :             expr_as_vec1_store_.resize(arg_list_.size(), T(0)               );
   14901        3724 :             typestore_list_    .resize(arg_list_.size(), type_store_t()     );
   14902        3724 :             range_list_        .resize(arg_list_.size(), range_data_type_t());
   14903        3724 :             branch_            .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false));
   14904        3724 :             vv_list_           .resize(arg_list_.size(), vecview_t(0));
   14905             : 
   14906       11989 :             for (std::size_t i = 0; i < arg_list_.size(); ++i)
   14907             :             {
   14908        8265 :                type_store_t& ts = typestore_list_[i];
   14909             : 
   14910        8265 :                if (0 == arg_list_[i])
   14911           0 :                   return false;
   14912        8265 :                else if (is_ivector_node(arg_list_[i]))
   14913             :                {
   14914        4325 :                   vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   14915             : 
   14916        4325 :                   if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
   14917           0 :                      return false;
   14918             : 
   14919        4325 :                   ts.size = vi->size();
   14920        4325 :                   ts.data = vi->vds().data();
   14921        4325 :                   ts.type = type_store_t::e_vector;
   14922             : 
   14923        4325 :                   if (
   14924        4436 :                        vi->vec()->vec_holder().rebaseable() &&
   14925         111 :                        vi->vec()->vec_holder().rebaseable_instance()
   14926             :                      )
   14927             :                   {
   14928         111 :                      vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance();
   14929         111 :                      vv_list_[i]->set_ref(&ts.vec_data);
   14930             :                   }
   14931             :                }
   14932             :                #ifndef exprtk_disable_string_capabilities
   14933        3940 :                else if (is_generally_string_node(arg_list_[i]))
   14934             :                {
   14935         254 :                   string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
   14936             : 
   14937         254 :                   if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
   14938           0 :                      return false;
   14939             : 
   14940         254 :                   ts.size = sbn->size();
   14941         254 :                   ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
   14942         254 :                   ts.type = type_store_t::e_string;
   14943             : 
   14944         254 :                   range_list_[i].data      = ts.data;
   14945         254 :                   range_list_[i].size      = ts.size;
   14946         254 :                   range_list_[i].type_size = sizeof(char);
   14947         254 :                   range_list_[i].str_node  = sbn;
   14948             : 
   14949         254 :                   range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
   14950             : 
   14951         254 :                   if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
   14952           0 :                      return false;
   14953             : 
   14954         254 :                   const range_t& rp = ri->range_ref();
   14955             : 
   14956         254 :                   if (
   14957         508 :                        rp.const_range() &&
   14958         254 :                        is_const_string_range_node(arg_list_[i])
   14959             :                      )
   14960             :                   {
   14961           0 :                      ts.size = rp.const_size();
   14962           0 :                      ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
   14963           0 :                      range_list_[i].range = reinterpret_cast<range_t*>(0);
   14964             :                   }
   14965             :                   else
   14966             :                   {
   14967         254 :                      range_list_[i].range = &(ri->range_ref());
   14968         254 :                      range_param_list_.push_back(i);
   14969             :                   }
   14970             :                }
   14971             :                #endif
   14972        3686 :                else if (is_variable_node(arg_list_[i]))
   14973             :                {
   14974         517 :                   variable_node_ptr_t var = variable_node_ptr_t(0);
   14975             : 
   14976         517 :                   if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
   14977           0 :                      return false;
   14978             : 
   14979         517 :                   ts.size = 1;
   14980         517 :                   ts.data = &var->ref();
   14981         517 :                   ts.type = type_store_t::e_scalar;
   14982             :                }
   14983             :                else
   14984             :                {
   14985        3169 :                   ts.size = 1;
   14986        3169 :                   ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
   14987        3169 :                   ts.type = type_store_t::e_scalar;
   14988             :                }
   14989             : 
   14990        8265 :                branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
   14991             :             }
   14992             : 
   14993        3724 :             return true;
   14994             :          }
   14995             : 
   14996             :          inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
   14997             :          {
   14998             :             return this < (&fn);
   14999             :          }
   15000             : 
   15001         120 :          inline T value() const exprtk_override
   15002             :          {
   15003         120 :             if (populate_value_list())
   15004             :             {
   15005             :                typedef typename GenericFunction::parameter_list_t parameter_list_t;
   15006             : 
   15007         120 :                return (*function_)(parameter_list_t(typestore_list_));
   15008             :             }
   15009             : 
   15010           0 :             return std::numeric_limits<T>::quiet_NaN();
   15011             :          }
   15012             : 
   15013         337 :          inline typename expression_node<T>::node_type type() const exprtk_override
   15014             :          {
   15015         337 :             return expression_node<T>::e_genfunction;
   15016             :          }
   15017             : 
   15018       12169 :          inline bool valid() const exprtk_override
   15019             :          {
   15020       12169 :             return function_;
   15021             :          }
   15022             : 
   15023             :       protected:
   15024             : 
   15025        5088 :          inline virtual bool populate_value_list() const
   15026             :          {
   15027       16159 :             for (std::size_t i = 0; i < branch_.size(); ++i)
   15028             :             {
   15029       11071 :                expr_as_vec1_store_[i] = branch_[i].first->value();
   15030             :             }
   15031             : 
   15032        5088 :             if (!range_param_list_.empty())
   15033             :             {
   15034         158 :                assert(range_param_list_.size() <= branch_.size());
   15035             : 
   15036         408 :                for (std::size_t i = 0; i < range_param_list_.size(); ++i)
   15037             :                {
   15038         250 :                   const std::size_t  index = range_param_list_[i];
   15039         250 :                   range_data_type_t& rdt   = range_list_[index];
   15040             : 
   15041         250 :                   const range_t& rp = (*rdt.range);
   15042         250 :                   std::size_t r0    = 0;
   15043         250 :                   std::size_t r1    = 0;
   15044             : 
   15045         250 :                   const std::size_t data_size =
   15046             :                   #ifndef exprtk_disable_string_capabilities
   15047         250 :                      rdt.str_node ? rdt.str_node->size() : rdt.size;
   15048             :                   #else
   15049             :                      rdt.size;
   15050             :                   #endif
   15051             : 
   15052         250 :                   if (!rp(r0, r1, data_size))
   15053             :                   {
   15054           0 :                      return false;
   15055             :                   }
   15056             : 
   15057         250 :                   type_store_t& ts = typestore_list_[index];
   15058             : 
   15059         250 :                   ts.size = rp.cache_size();
   15060             :                   #ifndef exprtk_disable_string_capabilities
   15061         250 :                   if (ts.type == type_store_t::e_string)
   15062         250 :                      ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
   15063             :                   else
   15064             :                   #endif
   15065           0 :                      ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
   15066             :                }
   15067             :             }
   15068             : 
   15069        5088 :             return true;
   15070             :          }
   15071             : 
   15072             :          GenericFunction* function_;
   15073             :          mutable typestore_list_t typestore_list_;
   15074             : 
   15075             :       private:
   15076             : 
   15077             :          std::vector<expression_ptr> arg_list_;
   15078             :          std::vector<branch_t>       branch_;
   15079             :          std::vector<vecview_t>      vv_list_;
   15080             :          mutable tmp_vs_t            expr_as_vec1_store_;
   15081             :          mutable range_list_t        range_list_;
   15082             :          std::vector<std::size_t>    range_param_list_;
   15083             :       };
   15084             : 
   15085             :       #ifndef exprtk_disable_string_capabilities
   15086             :       template <typename T, typename StringFunction>
   15087             :       class string_function_node : public generic_function_node<T,StringFunction>
   15088             :                                  , public string_base_node<T>
   15089             :                                  , public range_interface <T>
   15090             :       {
   15091             :       public:
   15092             : 
   15093             :          typedef generic_function_node<T,StringFunction> gen_function_t;
   15094             :          typedef typename range_interface<T>::range_t range_t;
   15095             : 
   15096          72 :          string_function_node(StringFunction* func,
   15097             :                               const std::vector<typename gen_function_t::expression_ptr>& arg_list)
   15098          72 :          : gen_function_t(arg_list,func)
   15099             :          {
   15100          72 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   15101          72 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   15102          72 :             range_.cache.first  = range_.n0_c.second;
   15103          72 :             range_.cache.second = range_.n1_c.second;
   15104          72 :             assert(valid());
   15105          72 :          }
   15106             : 
   15107             :          inline bool operator <(const string_function_node<T,StringFunction>& fn) const
   15108             :          {
   15109             :             return this < (&fn);
   15110             :          }
   15111             : 
   15112           0 :          inline T value() const exprtk_override
   15113             :          {
   15114           0 :             if (gen_function_t::populate_value_list())
   15115             :             {
   15116             :                typedef typename StringFunction::parameter_list_t parameter_list_t;
   15117             : 
   15118             :                const T result =
   15119           0 :                   (*gen_function_t::function_)
   15120           0 :                   (
   15121           0 :                      ret_string_,
   15122           0 :                      parameter_list_t(gen_function_t::typestore_list_)
   15123             :                   );
   15124             : 
   15125           0 :                range_.n1_c.second  = ret_string_.size();
   15126           0 :                range_.cache.second = range_.n1_c.second;
   15127             : 
   15128           0 :                return result;
   15129             :             }
   15130             : 
   15131           0 :             return std::numeric_limits<T>::quiet_NaN();
   15132             :          }
   15133             : 
   15134           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
   15135             :          {
   15136           0 :             return expression_node<T>::e_strfunction;
   15137             :          }
   15138             : 
   15139         414 :          inline bool valid() const exprtk_override
   15140             :          {
   15141         414 :             return gen_function_t::function_;
   15142             :          }
   15143             : 
   15144           6 :          std::string str() const exprtk_override
   15145             :          {
   15146           6 :             return ret_string_;
   15147             :          }
   15148             : 
   15149          66 :          char_cptr base() const exprtk_override
   15150             :          {
   15151          66 :            return &ret_string_[0];
   15152             :          }
   15153             : 
   15154          72 :          std::size_t size() const exprtk_override
   15155             :          {
   15156          72 :             return ret_string_.size();
   15157             :          }
   15158             : 
   15159          72 :          range_t& range_ref() exprtk_override
   15160             :          {
   15161          72 :             return range_;
   15162             :          }
   15163             : 
   15164           0 :          const range_t& range_ref() const exprtk_override
   15165             :          {
   15166           0 :             return range_;
   15167             :          }
   15168             : 
   15169             :       protected:
   15170             : 
   15171             :          mutable range_t     range_;
   15172             :          mutable std::string ret_string_;
   15173             :       };
   15174             :       #endif
   15175             : 
   15176             :       template <typename T, typename GenericFunction>
   15177             :       class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
   15178             :       {
   15179             :       public:
   15180             : 
   15181             :          typedef generic_function_node<T,GenericFunction> gen_function_t;
   15182             :          typedef typename gen_function_t::range_t         range_t;
   15183             : 
   15184        3479 :          multimode_genfunction_node(GenericFunction* func,
   15185             :                                     const std::size_t& param_seq_index,
   15186             :                                     const std::vector<typename gen_function_t::expression_ptr>& arg_list)
   15187             :          : gen_function_t(arg_list,func)
   15188        3479 :          , param_seq_index_(param_seq_index)
   15189        3479 :          {}
   15190             : 
   15191        4865 :          inline T value() const exprtk_override
   15192             :          {
   15193        4865 :             assert(gen_function_t::valid());
   15194             : 
   15195        4865 :             if (gen_function_t::populate_value_list())
   15196             :             {
   15197             :                typedef typename GenericFunction::parameter_list_t parameter_list_t;
   15198             : 
   15199             :                return
   15200        4865 :                   (*gen_function_t::function_)
   15201        4865 :                   (
   15202        4865 :                      param_seq_index_,
   15203        4865 :                      parameter_list_t(gen_function_t::typestore_list_)
   15204        4865 :                   );
   15205             :             }
   15206             : 
   15207           0 :             return std::numeric_limits<T>::quiet_NaN();
   15208             :          }
   15209             : 
   15210       50666 :          inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
   15211             :          {
   15212       50666 :             return expression_node<T>::e_genfunction;
   15213             :          }
   15214             : 
   15215             :       private:
   15216             : 
   15217             :          std::size_t param_seq_index_;
   15218             :       };
   15219             : 
   15220             :       #ifndef exprtk_disable_string_capabilities
   15221             :       template <typename T, typename StringFunction>
   15222             :       class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction>
   15223             :       {
   15224             :       public:
   15225             : 
   15226             :          typedef string_function_node<T,StringFunction> str_function_t;
   15227             :          typedef typename str_function_t::range_t range_t;
   15228             : 
   15229          72 :          multimode_strfunction_node(StringFunction* func,
   15230             :                                     const std::size_t& param_seq_index,
   15231             :                                     const std::vector<typename str_function_t::expression_ptr>& arg_list)
   15232             :          : str_function_t(func,arg_list)
   15233          72 :          , param_seq_index_(param_seq_index)
   15234          72 :          {}
   15235             : 
   15236          72 :          inline T value() const exprtk_override
   15237             :          {
   15238          72 :             if (str_function_t::populate_value_list())
   15239             :             {
   15240             :                typedef typename StringFunction::parameter_list_t parameter_list_t;
   15241             : 
   15242             :                const T result =
   15243          72 :                   (*str_function_t::function_)
   15244         216 :                   (
   15245          72 :                      param_seq_index_,
   15246          72 :                      str_function_t::ret_string_,
   15247          72 :                      parameter_list_t(str_function_t::typestore_list_)
   15248             :                   );
   15249             : 
   15250          72 :                str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size();
   15251          72 :                str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
   15252             : 
   15253          72 :                return result;
   15254             :             }
   15255             : 
   15256           0 :             return std::numeric_limits<T>::quiet_NaN();
   15257             :          }
   15258             : 
   15259         984 :          inline typename expression_node<T>::node_type type() const exprtk_override
   15260             :          {
   15261         984 :             return expression_node<T>::e_strfunction;
   15262             :          }
   15263             : 
   15264             :       private:
   15265             : 
   15266             :          const std::size_t param_seq_index_;
   15267             :       };
   15268             :       #endif
   15269             : 
   15270             :       class return_exception {};
   15271             : 
   15272             :       template <typename T>
   15273             :       class null_igenfunc
   15274             :       {
   15275             :       public:
   15276             : 
   15277             :          virtual ~null_igenfunc()
   15278             :          {}
   15279             : 
   15280             :          typedef type_store<T> generic_type;
   15281             :          typedef typename generic_type::parameter_list parameter_list_t;
   15282             : 
   15283             :          inline virtual T operator() (parameter_list_t)
   15284             :          {
   15285             :             return std::numeric_limits<T>::quiet_NaN();
   15286             :          }
   15287             :       };
   15288             : 
   15289             :       #ifndef exprtk_disable_return_statement
   15290             :       template <typename T>
   15291             :       class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> >
   15292             :       {
   15293             :       public:
   15294             : 
   15295             :          typedef results_context<T>   results_context_t;
   15296             :          typedef null_igenfunc<T>     igeneric_function_t;
   15297             :          typedef igeneric_function_t* igeneric_function_ptr;
   15298             :          typedef generic_function_node<T,igeneric_function_t> gen_function_t;
   15299             : 
   15300         116 :          return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
   15301             :                      results_context_t& rc)
   15302             :          : gen_function_t  (arg_list)
   15303         116 :          , results_context_(&rc)
   15304         116 :          {}
   15305             : 
   15306          31 :          inline T value() const exprtk_override
   15307             :          {
   15308          31 :             if (
   15309          62 :                  (0 != results_context_) &&
   15310          31 :                  gen_function_t::populate_value_list()
   15311             :                )
   15312             :             {
   15313             :                typedef typename type_store<T>::parameter_list parameter_list_t;
   15314             : 
   15315          31 :                results_context_->
   15316          31 :                   assign(parameter_list_t(gen_function_t::typestore_list_));
   15317             : 
   15318          31 :                throw return_exception();
   15319             :             }
   15320             : 
   15321           0 :             return std::numeric_limits<T>::quiet_NaN();
   15322             :          }
   15323             : 
   15324         542 :          inline typename expression_node<T>::node_type type() const exprtk_override
   15325             :          {
   15326         542 :             return expression_node<T>::e_return;
   15327             :          }
   15328             : 
   15329         162 :          inline bool valid() const exprtk_override
   15330             :          {
   15331         162 :             return results_context_;
   15332             :          }
   15333             : 
   15334             :       private:
   15335             : 
   15336             :          results_context_t* results_context_;
   15337             :       };
   15338             : 
   15339             :       template <typename T>
   15340             :       class return_envelope_node exprtk_final : public expression_node<T>
   15341             :       {
   15342             :       public:
   15343             : 
   15344             :          typedef expression_node<T>* expression_ptr;
   15345             :          typedef results_context<T>  results_context_t;
   15346             :          typedef std::pair<expression_ptr,bool> branch_t;
   15347             : 
   15348         111 :          return_envelope_node(expression_ptr body, results_context_t& rc)
   15349         111 :          : results_context_(&rc  )
   15350         111 :          , return_invoked_ (false)
   15351             :          {
   15352         111 :             construct_branch_pair(body_, body);
   15353         111 :             assert(valid());
   15354         111 :          }
   15355             : 
   15356         111 :          inline T value() const exprtk_override
   15357             :          {
   15358             :             try
   15359             :             {
   15360         111 :                return_invoked_ = false;
   15361         111 :                results_context_->clear();
   15362             : 
   15363         111 :                return body_.first->value();
   15364             :             }
   15365          31 :             catch(const return_exception&)
   15366             :             {
   15367          31 :                return_invoked_ = true;
   15368             : 
   15369          31 :                return std::numeric_limits<T>::quiet_NaN();
   15370             :             }
   15371             :          }
   15372             : 
   15373         222 :          inline typename expression_node<T>::node_type type() const exprtk_override
   15374             :          {
   15375         222 :             return expression_node<T>::e_retenv;
   15376             :          }
   15377             : 
   15378         111 :          inline bool valid() const exprtk_override
   15379             :          {
   15380         111 :             return results_context_ && body_.first;
   15381             :          }
   15382             : 
   15383         111 :          inline bool* retinvk_ptr()
   15384             :          {
   15385         111 :             return &return_invoked_;
   15386             :          }
   15387             : 
   15388         111 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   15389             :          {
   15390         111 :             expression_node<T>::ndb_t::collect(body_, node_delete_list);
   15391         111 :          }
   15392             : 
   15393         111 :          std::size_t node_depth() const exprtk_override
   15394             :          {
   15395         111 :             return expression_node<T>::ndb_t::compute_node_depth(body_);
   15396             :          }
   15397             : 
   15398             :       private:
   15399             : 
   15400             :          results_context_t* results_context_;
   15401             :          mutable bool        return_invoked_;
   15402             :          branch_t                      body_;
   15403             :       };
   15404             :       #endif
   15405             : 
   15406             :       #define exprtk_define_unary_op(OpName)                    \
   15407             :       template <typename T>                                     \
   15408             :       struct OpName##_op                                        \
   15409             :       {                                                         \
   15410             :          typedef typename functor_t<T>::Type Type;              \
   15411             :          typedef typename expression_node<T>::node_type node_t; \
   15412             :                                                                 \
   15413             :          static inline T process(Type v)                        \
   15414             :          {                                                      \
   15415             :             return numeric:: OpName (v);                        \
   15416             :          }                                                      \
   15417             :                                                                 \
   15418             :          static inline node_t type()                            \
   15419             :          {                                                      \
   15420             :             return expression_node<T>::e_##OpName;              \
   15421             :          }                                                      \
   15422             :                                                                 \
   15423             :          static inline details::operator_type operation()       \
   15424             :          {                                                      \
   15425             :             return details::e_##OpName;                         \
   15426             :          }                                                      \
   15427             :       };                                                        \
   15428             : 
   15429    22116398 :       exprtk_define_unary_op(abs  )
   15430        1560 :       exprtk_define_unary_op(acos )
   15431        1740 :       exprtk_define_unary_op(acosh)
   15432        1740 :       exprtk_define_unary_op(asin )
   15433        1800 :       exprtk_define_unary_op(asinh)
   15434        1870 :       exprtk_define_unary_op(atan )
   15435           0 :       exprtk_define_unary_op(atanh)
   15436        1440 :       exprtk_define_unary_op(ceil )
   15437    40031237 :       exprtk_define_unary_op(cos  )
   15438        1740 :       exprtk_define_unary_op(cosh )
   15439        1876 :       exprtk_define_unary_op(cot  )
   15440        1630 :       exprtk_define_unary_op(csc  )
   15441        1440 :       exprtk_define_unary_op(d2g  )
   15442        1800 :       exprtk_define_unary_op(d2r  )
   15443    30001450 :       exprtk_define_unary_op(erf  )
   15444    30001570 :       exprtk_define_unary_op(erfc )
   15445        1800 :       exprtk_define_unary_op(exp  )
   15446        1560 :       exprtk_define_unary_op(expm1)
   15447        1440 :       exprtk_define_unary_op(floor)
   15448        2604 :       exprtk_define_unary_op(frac )
   15449        1560 :       exprtk_define_unary_op(g2d  )
   15450        3070 :       exprtk_define_unary_op(log  )
   15451        3190 :       exprtk_define_unary_op(log10)
   15452           0 :       exprtk_define_unary_op(log2 )
   15453        1440 :       exprtk_define_unary_op(log1p)
   15454           0 :       exprtk_define_unary_op(ncdf )
   15455      146526 :       exprtk_define_unary_op(neg  )
   15456         112 :       exprtk_define_unary_op(notl )
   15457           0 :       exprtk_define_unary_op(pos  )
   15458        1740 :       exprtk_define_unary_op(r2d  )
   15459        1800 :       exprtk_define_unary_op(round)
   15460        1510 :       exprtk_define_unary_op(sec  )
   15461        4098 :       exprtk_define_unary_op(sgn  )
   15462   144368184 :       exprtk_define_unary_op(sin  )
   15463          70 :       exprtk_define_unary_op(sinc )
   15464        1560 :       exprtk_define_unary_op(sinh )
   15465     6003291 :       exprtk_define_unary_op(sqrt )
   15466      290899 :       exprtk_define_unary_op(tan  )
   15467        1740 :       exprtk_define_unary_op(tanh )
   15468         940 :       exprtk_define_unary_op(trunc)
   15469             :       #undef exprtk_define_unary_op
   15470             : 
   15471             :       template <typename T>
   15472             :       struct opr_base
   15473             :       {
   15474             :          typedef typename details::functor_t<T>::Type    Type;
   15475             :          typedef typename details::functor_t<T>::RefType RefType;
   15476             :          typedef typename details::functor_t<T> functor_t;
   15477             :          typedef typename functor_t::qfunc_t    quaternary_functor_t;
   15478             :          typedef typename functor_t::tfunc_t    trinary_functor_t;
   15479             :          typedef typename functor_t::bfunc_t    binary_functor_t;
   15480             :          typedef typename functor_t::ufunc_t    unary_functor_t;
   15481             :       };
   15482             : 
   15483             :       template <typename T>
   15484             :       struct add_op : public opr_base<T>
   15485             :       {
   15486             :          typedef typename opr_base<T>::Type    Type;
   15487             :          typedef typename opr_base<T>::RefType RefType;
   15488             : 
   15489   278746690 :          static inline T process(Type t1, Type t2) { return t1 + t2; }
   15490             :          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
   15491        5568 :          static inline void assign(RefType t1, Type t2) { t1 += t2; }
   15492     1770063 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
   15493      119142 :          static inline details::operator_type operation() { return details::e_add; }
   15494             :       };
   15495             : 
   15496             :       template <typename T>
   15497             :       struct mul_op : public opr_base<T>
   15498             :       {
   15499             :          typedef typename opr_base<T>::Type    Type;
   15500             :          typedef typename opr_base<T>::RefType RefType;
   15501             : 
   15502   900469021 :          static inline T process(Type t1, Type t2) { return t1 * t2; }
   15503             :          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
   15504         240 :          static inline void assign(RefType t1, Type t2) { t1 *= t2; }
   15505     3975181 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
   15506      214083 :          static inline details::operator_type operation() { return details::e_mul; }
   15507             :       };
   15508             : 
   15509             :       template <typename T>
   15510             :       struct sub_op : public opr_base<T>
   15511             :       {
   15512             :          typedef typename opr_base<T>::Type    Type;
   15513             :          typedef typename opr_base<T>::RefType RefType;
   15514             : 
   15515   445983141 :          static inline T process(Type t1, Type t2) { return t1 - t2; }
   15516             :          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
   15517        1004 :          static inline void assign(RefType t1, Type t2) { t1 -= t2; }
   15518     1593439 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
   15519      116791 :          static inline details::operator_type operation() { return details::e_sub; }
   15520             :       };
   15521             : 
   15522             :       template <typename T>
   15523             :       struct div_op : public opr_base<T>
   15524             :       {
   15525             :          typedef typename opr_base<T>::Type    Type;
   15526             :          typedef typename opr_base<T>::RefType RefType;
   15527             : 
   15528   400187315 :          static inline T process(Type t1, Type t2) { return t1 / t2; }
   15529             :          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
   15530         240 :          static inline void assign(RefType t1, Type t2) { t1 /= t2; }
   15531     3041094 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
   15532      185468 :          static inline details::operator_type operation() { return details::e_div; }
   15533             :       };
   15534             : 
   15535             :       template <typename T>
   15536             :       struct mod_op : public opr_base<T>
   15537             :       {
   15538             :          typedef typename opr_base<T>::Type    Type;
   15539             :          typedef typename opr_base<T>::RefType RefType;
   15540             : 
   15541      118403 :          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
   15542           0 :          static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
   15543         118 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
   15544          21 :          static inline details::operator_type operation() { return details::e_mod; }
   15545             :       };
   15546             : 
   15547             :       template <typename T>
   15548             :       struct pow_op : public opr_base<T>
   15549             :       {
   15550             :          typedef typename opr_base<T>::Type    Type;
   15551             :          typedef typename opr_base<T>::RefType RefType;
   15552             : 
   15553        1380 :          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
   15554             :          static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
   15555        3714 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
   15556         446 :          static inline details::operator_type operation() { return details::e_pow; }
   15557             :       };
   15558             : 
   15559             :       template <typename T>
   15560             :       struct lt_op : public opr_base<T>
   15561             :       {
   15562             :          typedef typename opr_base<T>::Type Type;
   15563             : 
   15564    43491690 :          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
   15565         656 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
   15566       16518 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
   15567         121 :          static inline details::operator_type operation() { return details::e_lt; }
   15568             :       };
   15569             : 
   15570             :       template <typename T>
   15571             :       struct lte_op : public opr_base<T>
   15572             :       {
   15573             :          typedef typename opr_base<T>::Type Type;
   15574             : 
   15575    60009490 :          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
   15576         155 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
   15577       13274 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
   15578           0 :          static inline details::operator_type operation() { return details::e_lte; }
   15579             :       };
   15580             : 
   15581             :       template <typename T>
   15582             :       struct gt_op : public opr_base<T>
   15583             :       {
   15584             :          typedef typename opr_base<T>::Type Type;
   15585             : 
   15586       39115 :          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
   15587         655 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
   15588       18478 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
   15589         151 :          static inline details::operator_type operation() { return details::e_gt; }
   15590             :       };
   15591             : 
   15592             :       template <typename T>
   15593             :       struct gte_op : public opr_base<T>
   15594             :       {
   15595             :          typedef typename opr_base<T>::Type Type;
   15596             : 
   15597         675 :          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
   15598         155 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
   15599        1480 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
   15600           0 :          static inline details::operator_type operation() { return details::e_gte; }
   15601             :       };
   15602             : 
   15603             :       template <typename T>
   15604             :       struct eq_op : public opr_base<T>
   15605             :       {
   15606             :          typedef typename opr_base<T>::Type Type;
   15607    94985622 :          static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
   15608       25921 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
   15609      267750 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
   15610        6007 :          static inline details::operator_type operation() { return details::e_eq; }
   15611             :       };
   15612             : 
   15613             :       template <typename T>
   15614             :       struct equal_op : public opr_base<T>
   15615             :       {
   15616             :          typedef typename opr_base<T>::Type Type;
   15617             : 
   15618         360 :          static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
   15619             :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
   15620             :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
   15621             :          static inline details::operator_type operation() { return details::e_equal; }
   15622             :       };
   15623             : 
   15624             :       template <typename T>
   15625             :       struct ne_op : public opr_base<T>
   15626             :       {
   15627             :          typedef typename opr_base<T>::Type Type;
   15628             : 
   15629        1817 :          static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
   15630        2450 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
   15631       14060 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
   15632         120 :          static inline details::operator_type operation() { return details::e_ne; }
   15633             :       };
   15634             : 
   15635             :       template <typename T>
   15636             :       struct and_op : public opr_base<T>
   15637             :       {
   15638             :          typedef typename opr_base<T>::Type Type;
   15639             : 
   15640        9894 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
   15641         570 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
   15642           0 :          static inline details::operator_type operation() { return details::e_and; }
   15643             :       };
   15644             : 
   15645             :       template <typename T>
   15646             :       struct nand_op : public opr_base<T>
   15647             :       {
   15648             :          typedef typename opr_base<T>::Type Type;
   15649             : 
   15650           4 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
   15651          68 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
   15652           0 :          static inline details::operator_type operation() { return details::e_nand; }
   15653             :       };
   15654             : 
   15655             :       template <typename T>
   15656             :       struct or_op : public opr_base<T>
   15657             :       {
   15658             :          typedef typename opr_base<T>::Type Type;
   15659             : 
   15660    11406052 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
   15661         570 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
   15662           0 :          static inline details::operator_type operation() { return details::e_or; }
   15663             :       };
   15664             : 
   15665             :       template <typename T>
   15666             :       struct nor_op : public opr_base<T>
   15667             :       {
   15668             :          typedef typename opr_base<T>::Type Type;
   15669             : 
   15670           4 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
   15671          68 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
   15672           0 :          static inline details::operator_type operation() { return details::e_nor; }
   15673             :       };
   15674             : 
   15675             :       template <typename T>
   15676             :       struct xor_op : public opr_base<T>
   15677             :       {
   15678             :          typedef typename opr_base<T>::Type Type;
   15679             : 
   15680          25 :          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
   15681           0 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
   15682           0 :          static inline details::operator_type operation() { return details::e_xor; }
   15683             :       };
   15684             : 
   15685             :       template <typename T>
   15686             :       struct xnor_op : public opr_base<T>
   15687             :       {
   15688             :          typedef typename opr_base<T>::Type Type;
   15689             : 
   15690           0 :          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
   15691           0 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
   15692           0 :          static inline details::operator_type operation() { return details::e_xnor; }
   15693             :       };
   15694             : 
   15695             :       template <typename T>
   15696             :       struct in_op : public opr_base<T>
   15697             :       {
   15698             :          typedef typename opr_base<T>::Type Type;
   15699             : 
   15700             :          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
   15701         760 :          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
   15702        9300 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
   15703           0 :          static inline details::operator_type operation() { return details::e_in; }
   15704             :       };
   15705             : 
   15706             :       template <typename T>
   15707             :       struct like_op : public opr_base<T>
   15708             :       {
   15709             :          typedef typename opr_base<T>::Type Type;
   15710             : 
   15711             :          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
   15712        3070 :          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
   15713       18550 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
   15714           0 :          static inline details::operator_type operation() { return details::e_like; }
   15715             :       };
   15716             : 
   15717             :       template <typename T>
   15718             :       struct ilike_op : public opr_base<T>
   15719             :       {
   15720             :          typedef typename opr_base<T>::Type Type;
   15721             : 
   15722             :          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
   15723        3245 :          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
   15724       18550 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
   15725           0 :          static inline details::operator_type operation() { return details::e_ilike; }
   15726             :       };
   15727             : 
   15728             :       template <typename T>
   15729             :       struct inrange_op : public opr_base<T>
   15730             :       {
   15731             :          typedef typename opr_base<T>::Type Type;
   15732             : 
   15733             :          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
   15734         300 :          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
   15735             :          {
   15736         300 :             return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
   15737             :          }
   15738        1500 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
   15739           0 :          static inline details::operator_type operation() { return details::e_inrange; }
   15740             :       };
   15741             : 
   15742             :       template <typename T>
   15743             :       inline T value(details::expression_node<T>* n)
   15744             :       {
   15745             :          return n->value();
   15746             :       }
   15747             : 
   15748             :       template <typename T>
   15749    31848709 :       inline T value(std::pair<details::expression_node<T>*,bool> n)
   15750             :       {
   15751    31848709 :          return n.first->value();
   15752             :       }
   15753             : 
   15754             :       template <typename T>
   15755        5111 :       inline T value(const T* t)
   15756             :       {
   15757        5111 :          return (*t);
   15758             :       }
   15759             : 
   15760             :       template <typename T>
   15761             :       inline T value(const T& t)
   15762             :       {
   15763             :          return t;
   15764             :       }
   15765             : 
   15766             :       template <typename T>
   15767             :       struct vararg_add_op exprtk_final : public opr_base<T>
   15768             :       {
   15769             :          typedef typename opr_base<T>::Type Type;
   15770             : 
   15771             :          template <typename Type,
   15772             :                    typename Allocator,
   15773             :                    template <typename, typename> class Sequence>
   15774         191 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15775             :          {
   15776         191 :             switch (arg_list.size())
   15777             :             {
   15778           0 :                case 0  : return T(0);
   15779           0 :                case 1  : return process_1(arg_list);
   15780          30 :                case 2  : return process_2(arg_list);
   15781          30 :                case 3  : return process_3(arg_list);
   15782          30 :                case 4  : return process_4(arg_list);
   15783          30 :                case 5  : return process_5(arg_list);
   15784          71 :                default :
   15785             :                          {
   15786          71 :                             T result = T(0);
   15787             : 
   15788         569 :                             for (std::size_t i = 0; i < arg_list.size(); ++i)
   15789             :                             {
   15790         498 :                                result += value(arg_list[i]);
   15791             :                             }
   15792             : 
   15793          71 :                             return result;
   15794             :                          }
   15795             :             }
   15796             :          }
   15797             : 
   15798             :          template <typename Sequence>
   15799           0 :          static inline T process_1(const Sequence& arg_list)
   15800             :          {
   15801           0 :             return value(arg_list[0]);
   15802             :          }
   15803             : 
   15804             :          template <typename Sequence>
   15805          30 :          static inline T process_2(const Sequence& arg_list)
   15806             :          {
   15807          30 :             return value(arg_list[0]) + value(arg_list[1]);
   15808             :          }
   15809             : 
   15810             :          template <typename Sequence>
   15811          30 :          static inline T process_3(const Sequence& arg_list)
   15812             :          {
   15813          30 :             return value(arg_list[0]) + value(arg_list[1]) +
   15814          30 :                    value(arg_list[2]) ;
   15815             :          }
   15816             : 
   15817             :          template <typename Sequence>
   15818          30 :          static inline T process_4(const Sequence& arg_list)
   15819             :          {
   15820          30 :             return value(arg_list[0]) + value(arg_list[1]) +
   15821          30 :                    value(arg_list[2]) + value(arg_list[3]) ;
   15822             :          }
   15823             : 
   15824             :          template <typename Sequence>
   15825          30 :          static inline T process_5(const Sequence& arg_list)
   15826             :          {
   15827          30 :             return value(arg_list[0]) + value(arg_list[1]) +
   15828          30 :                    value(arg_list[2]) + value(arg_list[3]) +
   15829          30 :                    value(arg_list[4]) ;
   15830             :          }
   15831             :       };
   15832             : 
   15833             :       template <typename T>
   15834             :       struct vararg_mul_op exprtk_final : public opr_base<T>
   15835             :       {
   15836             :          typedef typename opr_base<T>::Type Type;
   15837             : 
   15838             :          template <typename Type,
   15839             :                    typename Allocator,
   15840             :                    template <typename, typename> class Sequence>
   15841         164 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15842             :          {
   15843         164 :             switch (arg_list.size())
   15844             :             {
   15845           0 :                case 0  : return T(0);
   15846           0 :                case 1  : return process_1(arg_list);
   15847          30 :                case 2  : return process_2(arg_list);
   15848          30 :                case 3  : return process_3(arg_list);
   15849          30 :                case 4  : return process_4(arg_list);
   15850          30 :                case 5  : return process_5(arg_list);
   15851          44 :                default :
   15852             :                          {
   15853          44 :                             T result = T(value(arg_list[0]));
   15854             : 
   15855         304 :                             for (std::size_t i = 1; i < arg_list.size(); ++i)
   15856             :                             {
   15857         260 :                                result *= value(arg_list[i]);
   15858             :                             }
   15859             : 
   15860          44 :                             return result;
   15861             :                          }
   15862             :             }
   15863             :          }
   15864             : 
   15865             :          template <typename Sequence>
   15866           0 :          static inline T process_1(const Sequence& arg_list)
   15867             :          {
   15868           0 :             return value(arg_list[0]);
   15869             :          }
   15870             : 
   15871             :          template <typename Sequence>
   15872          30 :          static inline T process_2(const Sequence& arg_list)
   15873             :          {
   15874          30 :             return value(arg_list[0]) * value(arg_list[1]);
   15875             :          }
   15876             : 
   15877             :          template <typename Sequence>
   15878          30 :          static inline T process_3(const Sequence& arg_list)
   15879             :          {
   15880          30 :             return value(arg_list[0]) * value(arg_list[1]) *
   15881          30 :                    value(arg_list[2]) ;
   15882             :          }
   15883             : 
   15884             :          template <typename Sequence>
   15885          30 :          static inline T process_4(const Sequence& arg_list)
   15886             :          {
   15887          30 :             return value(arg_list[0]) * value(arg_list[1]) *
   15888          30 :                    value(arg_list[2]) * value(arg_list[3]) ;
   15889             :          }
   15890             : 
   15891             :          template <typename Sequence>
   15892          30 :          static inline T process_5(const Sequence& arg_list)
   15893             :          {
   15894          30 :             return value(arg_list[0]) * value(arg_list[1]) *
   15895          30 :                    value(arg_list[2]) * value(arg_list[3]) *
   15896          30 :                    value(arg_list[4]) ;
   15897             :          }
   15898             :       };
   15899             : 
   15900             :       template <typename T>
   15901             :       struct vararg_avg_op exprtk_final : public opr_base<T>
   15902             :       {
   15903             :          typedef typename opr_base<T>::Type Type;
   15904             : 
   15905             :          template <typename Type,
   15906             :                    typename Allocator,
   15907             :                    template <typename, typename> class Sequence>
   15908         247 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15909             :          {
   15910         247 :             switch (arg_list.size())
   15911             :             {
   15912           0 :                case 0  : return T(0);
   15913           0 :                case 1  : return process_1(arg_list);
   15914          55 :                case 2  : return process_2(arg_list);
   15915          55 :                case 3  : return process_3(arg_list);
   15916          55 :                case 4  : return process_4(arg_list);
   15917          55 :                case 5  : return process_5(arg_list);
   15918          27 :                default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size());
   15919             :             }
   15920             :          }
   15921             : 
   15922             :          template <typename Sequence>
   15923           0 :          static inline T process_1(const Sequence& arg_list)
   15924             :          {
   15925           0 :             return value(arg_list[0]);
   15926             :          }
   15927             : 
   15928             :          template <typename Sequence>
   15929          55 :          static inline T process_2(const Sequence& arg_list)
   15930             :          {
   15931          55 :             return (value(arg_list[0]) + value(arg_list[1])) / T(2);
   15932             :          }
   15933             : 
   15934             :          template <typename Sequence>
   15935          55 :          static inline T process_3(const Sequence& arg_list)
   15936             :          {
   15937          55 :             return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
   15938             :          }
   15939             : 
   15940             :          template <typename Sequence>
   15941          55 :          static inline T process_4(const Sequence& arg_list)
   15942             :          {
   15943          55 :             return (value(arg_list[0]) + value(arg_list[1]) +
   15944          55 :                     value(arg_list[2]) + value(arg_list[3])) / T(4);
   15945             :          }
   15946             : 
   15947             :          template <typename Sequence>
   15948          55 :          static inline T process_5(const Sequence& arg_list)
   15949             :          {
   15950          55 :             return (value(arg_list[0]) + value(arg_list[1]) +
   15951          55 :                     value(arg_list[2]) + value(arg_list[3]) +
   15952          55 :                     value(arg_list[4])) / T(5);
   15953             :          }
   15954             :       };
   15955             : 
   15956             :       template <typename T>
   15957             :       struct vararg_min_op exprtk_final : public opr_base<T>
   15958             :       {
   15959             :          typedef typename opr_base<T>::Type Type;
   15960             : 
   15961             :          template <typename Type,
   15962             :                    typename Allocator,
   15963             :                    template <typename, typename> class Sequence>
   15964        4924 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15965             :          {
   15966        4924 :             switch (arg_list.size())
   15967             :             {
   15968           0 :                case 0  : return T(0);
   15969           0 :                case 1  : return process_1(arg_list);
   15970        4690 :                case 2  : return process_2(arg_list);
   15971          82 :                case 3  : return process_3(arg_list);
   15972          55 :                case 4  : return process_4(arg_list);
   15973          56 :                case 5  : return process_5(arg_list);
   15974          41 :                default :
   15975             :                          {
   15976          41 :                             T result = T(value(arg_list[0]));
   15977             : 
   15978         278 :                             for (std::size_t i = 1; i < arg_list.size(); ++i)
   15979             :                             {
   15980         237 :                                const T v = value(arg_list[i]);
   15981             : 
   15982         237 :                                if (v < result)
   15983           1 :                                   result = v;
   15984             :                             }
   15985             : 
   15986          41 :                             return result;
   15987             :                          }
   15988             :             }
   15989             :          }
   15990             : 
   15991             :          template <typename Sequence>
   15992           0 :          static inline T process_1(const Sequence& arg_list)
   15993             :          {
   15994           0 :             return value(arg_list[0]);
   15995             :          }
   15996             : 
   15997             :          template <typename Sequence>
   15998        4690 :          static inline T process_2(const Sequence& arg_list)
   15999             :          {
   16000        4690 :             return std::min<T>(value(arg_list[0]),value(arg_list[1]));
   16001             :          }
   16002             : 
   16003             :          template <typename Sequence>
   16004          82 :          static inline T process_3(const Sequence& arg_list)
   16005             :          {
   16006          82 :             return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
   16007             :          }
   16008             : 
   16009             :          template <typename Sequence>
   16010          55 :          static inline T process_4(const Sequence& arg_list)
   16011             :          {
   16012          55 :             return std::min<T>(
   16013          55 :                         std::min<T>(value(arg_list[0]), value(arg_list[1])),
   16014         110 :                         std::min<T>(value(arg_list[2]), value(arg_list[3])));
   16015             :          }
   16016             : 
   16017             :          template <typename Sequence>
   16018          56 :          static inline T process_5(const Sequence& arg_list)
   16019             :          {
   16020          56 :             return std::min<T>(
   16021          56 :                    std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
   16022          56 :                                std::min<T>(value(arg_list[2]), value(arg_list[3]))),
   16023         112 :                                value(arg_list[4]));
   16024             :          }
   16025             :       };
   16026             : 
   16027             :       template <typename T>
   16028             :       struct vararg_max_op exprtk_final : public opr_base<T>
   16029             :       {
   16030             :          typedef typename opr_base<T>::Type Type;
   16031             : 
   16032             :          template <typename Type,
   16033             :                    typename Allocator,
   16034             :                    template <typename, typename> class Sequence>
   16035         307 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   16036             :          {
   16037         307 :             switch (arg_list.size())
   16038             :             {
   16039           0 :                case 0  : return T(0);
   16040           0 :                case 1  : return process_1(arg_list);
   16041         100 :                case 2  : return process_2(arg_list);
   16042          55 :                case 3  : return process_3(arg_list);
   16043          55 :                case 4  : return process_4(arg_list);
   16044          56 :                case 5  : return process_5(arg_list);
   16045          41 :                default :
   16046             :                          {
   16047          41 :                             T result = T(value(arg_list[0]));
   16048             : 
   16049         278 :                             for (std::size_t i = 1; i < arg_list.size(); ++i)
   16050             :                             {
   16051         237 :                                const T v = value(arg_list[i]);
   16052             : 
   16053         237 :                                if (v > result)
   16054         237 :                                   result = v;
   16055             :                             }
   16056             : 
   16057          41 :                             return result;
   16058             :                          }
   16059             :             }
   16060             :          }
   16061             : 
   16062             :          template <typename Sequence>
   16063           0 :          static inline T process_1(const Sequence& arg_list)
   16064             :          {
   16065           0 :             return value(arg_list[0]);
   16066             :          }
   16067             : 
   16068             :          template <typename Sequence>
   16069         100 :          static inline T process_2(const Sequence& arg_list)
   16070             :          {
   16071         100 :             return std::max<T>(value(arg_list[0]),value(arg_list[1]));
   16072             :          }
   16073             : 
   16074             :          template <typename Sequence>
   16075          55 :          static inline T process_3(const Sequence& arg_list)
   16076             :          {
   16077          55 :             return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
   16078             :          }
   16079             : 
   16080             :          template <typename Sequence>
   16081          55 :          static inline T process_4(const Sequence& arg_list)
   16082             :          {
   16083          55 :             return std::max<T>(
   16084          55 :                         std::max<T>(value(arg_list[0]), value(arg_list[1])),
   16085         110 :                         std::max<T>(value(arg_list[2]), value(arg_list[3])));
   16086             :          }
   16087             : 
   16088             :          template <typename Sequence>
   16089          56 :          static inline T process_5(const Sequence& arg_list)
   16090             :          {
   16091          56 :             return std::max<T>(
   16092          56 :                    std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
   16093          56 :                                std::max<T>(value(arg_list[2]), value(arg_list[3]))),
   16094         112 :                                value(arg_list[4]));
   16095             :          }
   16096             :       };
   16097             : 
   16098             :       template <typename T>
   16099             :       struct vararg_mand_op exprtk_final : public opr_base<T>
   16100             :       {
   16101             :          typedef typename opr_base<T>::Type Type;
   16102             : 
   16103             :          template <typename Type,
   16104             :                    typename Allocator,
   16105             :                    template <typename, typename> class Sequence>
   16106         256 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   16107             :          {
   16108         256 :             switch (arg_list.size())
   16109             :             {
   16110           0 :                case 1  : return process_1(arg_list);
   16111         249 :                case 2  : return process_2(arg_list);
   16112           2 :                case 3  : return process_3(arg_list);
   16113           2 :                case 4  : return process_4(arg_list);
   16114           2 :                case 5  : return process_5(arg_list);
   16115           1 :                default :
   16116             :                          {
   16117           6 :                             for (std::size_t i = 0; i < arg_list.size(); ++i)
   16118             :                             {
   16119           6 :                                if (std::equal_to<T>()(T(0), value(arg_list[i])))
   16120           1 :                                   return T(0);
   16121             :                             }
   16122             : 
   16123           0 :                             return T(1);
   16124             :                          }
   16125             :             }
   16126             :          }
   16127             : 
   16128             :          template <typename Sequence>
   16129           0 :          static inline T process_1(const Sequence& arg_list)
   16130             :          {
   16131           0 :             return std::not_equal_to<T>()
   16132           0 :                       (T(0), value(arg_list[0])) ? T(1) : T(0);
   16133             :          }
   16134             : 
   16135             :          template <typename Sequence>
   16136         249 :          static inline T process_2(const Sequence& arg_list)
   16137             :          {
   16138             :             return (
   16139         374 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   16140         374 :                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
   16141         614 :                    ) ? T(1) : T(0);
   16142             :          }
   16143             : 
   16144             :          template <typename Sequence>
   16145           2 :          static inline T process_3(const Sequence& arg_list)
   16146             :          {
   16147             :             return (
   16148           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   16149           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
   16150           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
   16151           4 :                    ) ? T(1) : T(0);
   16152             :          }
   16153             : 
   16154             :          template <typename Sequence>
   16155           2 :          static inline T process_4(const Sequence& arg_list)
   16156             :          {
   16157             :             return (
   16158           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   16159           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
   16160           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
   16161           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
   16162           4 :                    ) ? T(1) : T(0);
   16163             :          }
   16164             : 
   16165             :          template <typename Sequence>
   16166           2 :          static inline T process_5(const Sequence& arg_list)
   16167             :          {
   16168             :             return (
   16169           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   16170           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
   16171           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
   16172           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
   16173           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
   16174           4 :                    ) ? T(1) : T(0);
   16175             :          }
   16176             :       };
   16177             : 
   16178             :       template <typename T>
   16179             :       struct vararg_mor_op exprtk_final : public opr_base<T>
   16180             :       {
   16181             :          typedef typename opr_base<T>::Type Type;
   16182             : 
   16183             :          template <typename Type,
   16184             :                    typename Allocator,
   16185             :                    template <typename, typename> class Sequence>
   16186         257 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   16187             :          {
   16188         257 :             switch (arg_list.size())
   16189             :             {
   16190           0 :                case 1  : return process_1(arg_list);
   16191         250 :                case 2  : return process_2(arg_list);
   16192           3 :                case 3  : return process_3(arg_list);
   16193           1 :                case 4  : return process_4(arg_list);
   16194           1 :                case 5  : return process_5(arg_list);
   16195           2 :                default :
   16196             :                          {
   16197          15 :                             for (std::size_t i = 0; i < arg_list.size(); ++i)
   16198             :                             {
   16199          14 :                                if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
   16200           1 :                                   return T(1);
   16201             :                             }
   16202             : 
   16203           1 :                             return T(0);
   16204             :                          }
   16205             :             }
   16206             :          }
   16207             : 
   16208             :          template <typename Sequence>
   16209           0 :          static inline T process_1(const Sequence& arg_list)
   16210             :          {
   16211           0 :             return std::not_equal_to<T>()
   16212           0 :                       (T(0), value(arg_list[0])) ? T(1) : T(0);
   16213             :          }
   16214             : 
   16215             :          template <typename Sequence>
   16216         250 :          static inline T process_2(const Sequence& arg_list)
   16217             :          {
   16218             :             return (
   16219         375 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   16220         375 :                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
   16221         615 :                    ) ? T(1) : T(0);
   16222             :          }
   16223             : 
   16224             :          template <typename Sequence>
   16225           3 :          static inline T process_3(const Sequence& arg_list)
   16226             :          {
   16227             :             return (
   16228           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   16229           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
   16230           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
   16231           4 :                    ) ? T(1) : T(0);
   16232             :          }
   16233             : 
   16234             :          template <typename Sequence>
   16235           1 :          static inline T process_4(const Sequence& arg_list)
   16236             :          {
   16237             :             return (
   16238           1 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   16239           0 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
   16240           0 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
   16241           1 :                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
   16242           1 :                    ) ? T(1) : T(0);
   16243             :          }
   16244             : 
   16245             :          template <typename Sequence>
   16246           1 :          static inline T process_5(const Sequence& arg_list)
   16247             :          {
   16248             :             return (
   16249           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   16250           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
   16251           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
   16252           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
   16253           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
   16254           2 :                    ) ? T(1) : T(0);
   16255             :          }
   16256             :       };
   16257             : 
   16258             :       template <typename T>
   16259             :       struct vararg_multi_op exprtk_final : public opr_base<T>
   16260             :       {
   16261             :          typedef typename opr_base<T>::Type Type;
   16262             : 
   16263             :          template <typename Type,
   16264             :                    typename Allocator,
   16265             :                    template <typename, typename> class Sequence>
   16266    10169021 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   16267             :          {
   16268    10169021 :             switch (arg_list.size())
   16269             :             {
   16270           0 :                case 0  : return std::numeric_limits<T>::quiet_NaN();
   16271          40 :                case 1  : return process_1(arg_list);
   16272     4656458 :                case 2  : return process_2(arg_list);
   16273       16177 :                case 3  : return process_3(arg_list);
   16274     5005264 :                case 4  : return process_4(arg_list);
   16275      490504 :                case 5  : return process_5(arg_list);
   16276         258 :                case 6  : return process_6(arg_list);
   16277          15 :                case 7  : return process_7(arg_list);
   16278         204 :                case 8  : return process_8(arg_list);
   16279         101 :                default :
   16280             :                         {
   16281         909 :                            for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
   16282             :                            {
   16283         808 :                               value(arg_list[i]);
   16284             :                            }
   16285         101 :                            return value(arg_list.back());
   16286             :                         }
   16287             :             }
   16288             :          }
   16289             : 
   16290             :          template <typename Sequence>
   16291          40 :          static inline T process_1(const Sequence& arg_list)
   16292             :          {
   16293          40 :             return value(arg_list[0]);
   16294             :          }
   16295             : 
   16296             :          template <typename Sequence>
   16297     4656458 :          static inline T process_2(const Sequence& arg_list)
   16298             :          {
   16299     4656458 :                    value(arg_list[0]);
   16300     4656408 :             return value(arg_list[1]);
   16301             :          }
   16302             : 
   16303             :          template <typename Sequence>
   16304       16177 :          static inline T process_3(const Sequence& arg_list)
   16305             :          {
   16306       16177 :                    value(arg_list[0]);
   16307       16127 :                    value(arg_list[1]);
   16308       16077 :             return value(arg_list[2]);
   16309             :          }
   16310             : 
   16311             :          template <typename Sequence>
   16312     5005264 :          static inline T process_4(const Sequence& arg_list)
   16313             :          {
   16314     5005264 :                    value(arg_list[0]);
   16315     5005264 :                    value(arg_list[1]);
   16316     5005264 :                    value(arg_list[2]);
   16317     5005264 :             return value(arg_list[3]);
   16318             :          }
   16319             : 
   16320             :          template <typename Sequence>
   16321      490504 :          static inline T process_5(const Sequence& arg_list)
   16322             :          {
   16323      490504 :                    value(arg_list[0]);
   16324      490504 :                    value(arg_list[1]);
   16325      490504 :                    value(arg_list[2]);
   16326      490504 :                    value(arg_list[3]);
   16327      490504 :             return value(arg_list[4]);
   16328             :          }
   16329             : 
   16330             :          template <typename Sequence>
   16331         258 :          static inline T process_6(const Sequence& arg_list)
   16332             :          {
   16333         258 :                    value(arg_list[0]);
   16334         258 :                    value(arg_list[1]);
   16335         258 :                    value(arg_list[2]);
   16336         258 :                    value(arg_list[3]);
   16337         258 :                    value(arg_list[4]);
   16338         258 :             return value(arg_list[5]);
   16339             :          }
   16340             : 
   16341             :          template <typename Sequence>
   16342          15 :          static inline T process_7(const Sequence& arg_list)
   16343             :          {
   16344          15 :                    value(arg_list[0]);
   16345          15 :                    value(arg_list[1]);
   16346          15 :                    value(arg_list[2]);
   16347          15 :                    value(arg_list[3]);
   16348          15 :                    value(arg_list[4]);
   16349          15 :                    value(arg_list[5]);
   16350          15 :             return value(arg_list[6]);
   16351             :          }
   16352             : 
   16353             :          template <typename Sequence>
   16354         204 :          static inline T process_8(const Sequence& arg_list)
   16355             :          {
   16356         204 :                    value(arg_list[0]);
   16357         204 :                    value(arg_list[1]);
   16358         204 :                    value(arg_list[2]);
   16359         204 :                    value(arg_list[3]);
   16360         204 :                    value(arg_list[4]);
   16361         204 :                    value(arg_list[5]);
   16362         204 :                    value(arg_list[6]);
   16363         204 :             return value(arg_list[7]);
   16364             :          }
   16365             :       };
   16366             : 
   16367             :       template <typename T>
   16368             :       struct vec_add_op
   16369             :       {
   16370             :          typedef vector_interface<T>* ivector_ptr;
   16371             : 
   16372        2365 :          static inline T process(const ivector_ptr v)
   16373             :          {
   16374        2365 :             const T* vec = v->vec()->vds().data();
   16375        2365 :             const std::size_t vec_size = v->size();
   16376             : 
   16377        2365 :             loop_unroll::details lud(vec_size);
   16378             : 
   16379        2365 :             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
   16380             :             {
   16381        1705 :                T result = T(0);
   16382        1705 :                int i    = 0;
   16383             : 
   16384        1705 :                switch (vec_size)
   16385             :                {
   16386             :                   #define case_stmt(N,fall_through) \
   16387             :                   case N : result += vec[i++];      \
   16388             :                   fall_through                      \
   16389             : 
   16390             :                   #ifndef exprtk_disable_superscalar_unroll
   16391          20 :                   case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
   16392          20 :                   case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
   16393          20 :                   case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
   16394          23 :                   case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
   16395         313 :                   case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
   16396         772 :                   case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
   16397             : 
   16398             :                   #endif
   16399        1617 :                   case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
   16400        1705 :                   case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
   16401             :                }
   16402             : 
   16403             :                #undef case_stmt
   16404             : 
   16405        1705 :                return result;
   16406             :             }
   16407             : 
   16408         660 :             T r[] = {
   16409             :                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
   16410             :                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
   16411             :                     };
   16412             : 
   16413         660 :             const T* upper_bound = vec + lud.upper_bound;
   16414             : 
   16415    26375720 :             while (vec < upper_bound)
   16416             :             {
   16417             :                #define exprtk_loop(N) \
   16418             :                r[N] += vec[N];        \
   16419             : 
   16420    26375060 :                exprtk_loop( 0) exprtk_loop( 1)
   16421    26375060 :                exprtk_loop( 2) exprtk_loop( 3)
   16422             :                #ifndef exprtk_disable_superscalar_unroll
   16423    26375060 :                exprtk_loop( 4) exprtk_loop( 5)
   16424    26375060 :                exprtk_loop( 6) exprtk_loop( 7)
   16425    26375060 :                exprtk_loop( 8) exprtk_loop( 9)
   16426    26375060 :                exprtk_loop(10) exprtk_loop(11)
   16427    26375060 :                exprtk_loop(12) exprtk_loop(13)
   16428    26375060 :                exprtk_loop(14) exprtk_loop(15)
   16429             :                #endif
   16430             : 
   16431    26375060 :                vec += lud.batch_size;
   16432             :             }
   16433             : 
   16434         660 :             int i = 0;
   16435             : 
   16436         660 :             switch (lud.remainder)
   16437             :             {
   16438             :                #define case_stmt(N,fall_through) \
   16439             :                case N : r[0] += vec[i++];        \
   16440             :                fall_through                      \
   16441             : 
   16442             :                #ifndef exprtk_disable_superscalar_unroll
   16443           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   16444          10 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   16445          10 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   16446          10 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   16447          10 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   16448          10 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   16449             :                #endif
   16450          10 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   16451          30 :                case_stmt( 1, (void)0;)
   16452             :             }
   16453             : 
   16454             :             #undef exprtk_loop
   16455             :             #undef case_stmt
   16456             : 
   16457         660 :             return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
   16458             :                    #ifndef exprtk_disable_superscalar_unroll
   16459         660 :                  + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
   16460         660 :                  + (r[ 8] + r[ 9] + r[10] + r[11])
   16461         660 :                  + (r[12] + r[13] + r[14] + r[15])
   16462             :                    #endif
   16463             :                    ;
   16464             :          }
   16465             :       };
   16466             : 
   16467             :       template <typename T>
   16468             :       struct vec_mul_op
   16469             :       {
   16470             :          typedef vector_interface<T>* ivector_ptr;
   16471             : 
   16472          60 :          static inline T process(const ivector_ptr v)
   16473             :          {
   16474          60 :             const T* vec = v->vec()->vds().data();
   16475          60 :             const std::size_t vec_size = v->vec()->size();
   16476             : 
   16477          60 :             loop_unroll::details lud(vec_size);
   16478             : 
   16479          60 :             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
   16480             :             {
   16481          20 :                T result = T(1);
   16482          20 :                int i    = 0;
   16483             : 
   16484          20 :                switch (vec_size)
   16485             :                {
   16486             :                   #define case_stmt(N,fall_through) \
   16487             :                   case N : result *= vec[i++];      \
   16488             :                   fall_through                      \
   16489             : 
   16490             :                   #ifndef exprtk_disable_superscalar_unroll
   16491          20 :                   case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
   16492          20 :                   case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
   16493          20 :                   case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
   16494          20 :                   case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
   16495          20 :                   case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
   16496          20 :                   case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
   16497             :                   #endif
   16498          20 :                   case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
   16499          20 :                   case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
   16500             :                }
   16501             : 
   16502             :                #undef case_stmt
   16503             : 
   16504          20 :                return result;
   16505             :             }
   16506             : 
   16507          40 :             T r[] = {
   16508             :                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
   16509             :                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
   16510             :                     };
   16511             : 
   16512          40 :             const T* upper_bound = vec + lud.upper_bound;
   16513             : 
   16514         100 :             while (vec < upper_bound)
   16515             :             {
   16516             :                #define exprtk_loop(N) \
   16517             :                r[N] *= vec[N];        \
   16518             : 
   16519          60 :                exprtk_loop( 0) exprtk_loop( 1)
   16520          60 :                exprtk_loop( 2) exprtk_loop( 3)
   16521             :                #ifndef exprtk_disable_superscalar_unroll
   16522          60 :                exprtk_loop( 4) exprtk_loop( 5)
   16523          60 :                exprtk_loop( 6) exprtk_loop( 7)
   16524          60 :                exprtk_loop( 8) exprtk_loop( 9)
   16525          60 :                exprtk_loop(10) exprtk_loop(11)
   16526          60 :                exprtk_loop(12) exprtk_loop(13)
   16527          60 :                exprtk_loop(14) exprtk_loop(15)
   16528             :                #endif
   16529             : 
   16530          60 :                vec += lud.batch_size;
   16531             :             }
   16532             : 
   16533          40 :             int i = 0;
   16534             : 
   16535          40 :             switch (lud.remainder)
   16536             :             {
   16537             :                #define case_stmt(N,fall_through) \
   16538             :                case N : r[0] *= vec[i++];        \
   16539             :                fall_through                      \
   16540             : 
   16541             :                #ifndef exprtk_disable_superscalar_unroll
   16542           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   16543          10 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   16544          10 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   16545          10 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   16546          10 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   16547          10 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   16548             :                #endif
   16549          10 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   16550          30 :                case_stmt( 1, (void)0;)
   16551             :             }
   16552             : 
   16553             :             #undef exprtk_loop
   16554             :             #undef case_stmt
   16555             : 
   16556          40 :             return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
   16557             :                    #ifndef exprtk_disable_superscalar_unroll
   16558          40 :                  * (r[ 4] * r[ 5] * r[ 6] * r[ 7])
   16559          40 :                  * (r[ 8] * r[ 9] * r[10] * r[11])
   16560          40 :                  * (r[12] * r[13] * r[14] * r[15])
   16561             :                    #endif
   16562             :                    ;
   16563             :          }
   16564             :       };
   16565             : 
   16566             :       template <typename T>
   16567             :       struct vec_avg_op
   16568             :       {
   16569             :          typedef vector_interface<T>* ivector_ptr;
   16570             : 
   16571          90 :          static inline T process(const ivector_ptr v)
   16572             :          {
   16573          90 :             const T vec_size = T(v->vec()->size());
   16574          90 :             return vec_add_op<T>::process(v) / vec_size;
   16575             :          }
   16576             :       };
   16577             : 
   16578             :       template <typename T>
   16579             :       struct vec_min_op
   16580             :       {
   16581             :          typedef vector_interface<T>* ivector_ptr;
   16582             : 
   16583         100 :          static inline T process(const ivector_ptr v)
   16584             :          {
   16585         100 :             const T* vec = v->vec()->vds().data();
   16586         100 :             const std::size_t vec_size = v->vec()->size();
   16587             : 
   16588         100 :             T result = vec[0];
   16589             : 
   16590         449 :             for (std::size_t i = 1; i < vec_size; ++i)
   16591             :             {
   16592         349 :                const T v_i = vec[i];
   16593             : 
   16594         349 :                if (v_i < result)
   16595          20 :                   result = v_i;
   16596             :             }
   16597             : 
   16598         100 :             return result;
   16599             :          }
   16600             :       };
   16601             : 
   16602             :       template <typename T>
   16603             :       struct vec_max_op
   16604             :       {
   16605             :          typedef vector_interface<T>* ivector_ptr;
   16606             : 
   16607          90 :          static inline T process(const ivector_ptr v)
   16608             :          {
   16609          90 :             const T* vec = v->vec()->vds().data();
   16610          90 :             const std::size_t vec_size = v->vec()->size();
   16611             : 
   16612          90 :             T result = vec[0];
   16613             : 
   16614         434 :             for (std::size_t i = 1; i < vec_size; ++i)
   16615             :             {
   16616         344 :                const T v_i = vec[i];
   16617             : 
   16618         344 :                if (v_i > result)
   16619         304 :                   result = v_i;
   16620             :             }
   16621             : 
   16622          90 :             return result;
   16623             :          }
   16624             :       };
   16625             : 
   16626             :       template <typename T>
   16627             :       class vov_base_node : public expression_node<T>
   16628             :       {
   16629             :       public:
   16630             : 
   16631      265747 :          virtual ~vov_base_node()
   16632      265747 :          {}
   16633             : 
   16634           0 :          inline virtual operator_type operation() const
   16635             :          {
   16636           0 :             return details::e_default;
   16637             :          }
   16638             : 
   16639             :          virtual const T& v0() const = 0;
   16640             : 
   16641             :          virtual const T& v1() const = 0;
   16642             :       };
   16643             : 
   16644             :       template <typename T>
   16645             :       class cov_base_node : public expression_node<T>
   16646             :       {
   16647             :       public:
   16648             : 
   16649      243926 :          virtual ~cov_base_node()
   16650      243926 :          {}
   16651             : 
   16652           0 :          inline virtual operator_type operation() const
   16653             :          {
   16654           0 :             return details::e_default;
   16655             :          }
   16656             : 
   16657             :          virtual const T c() const = 0;
   16658             : 
   16659             :          virtual const T& v() const = 0;
   16660             :       };
   16661             : 
   16662             :       template <typename T>
   16663             :       class voc_base_node : public expression_node<T>
   16664             :       {
   16665             :       public:
   16666             : 
   16667      288796 :          virtual ~voc_base_node()
   16668      288796 :          {}
   16669             : 
   16670           0 :          inline virtual operator_type operation() const
   16671             :          {
   16672           0 :             return details::e_default;
   16673             :          }
   16674             : 
   16675             :          virtual const T c() const = 0;
   16676             : 
   16677             :          virtual const T& v() const = 0;
   16678             :       };
   16679             : 
   16680             :       template <typename T>
   16681             :       class vob_base_node : public expression_node<T>
   16682             :       {
   16683             :       public:
   16684             : 
   16685       33759 :          virtual ~vob_base_node()
   16686       33759 :          {}
   16687             : 
   16688             :          virtual const T& v() const = 0;
   16689             :       };
   16690             : 
   16691             :       template <typename T>
   16692             :       class bov_base_node : public expression_node<T>
   16693             :       {
   16694             :       public:
   16695             : 
   16696      352771 :          virtual ~bov_base_node()
   16697      352771 :          {}
   16698             : 
   16699             :          virtual const T& v() const = 0;
   16700             :       };
   16701             : 
   16702             :       template <typename T>
   16703             :       class cob_base_node : public expression_node<T>
   16704             :       {
   16705             :       public:
   16706             : 
   16707       89268 :          virtual ~cob_base_node()
   16708       89268 :          {}
   16709             : 
   16710           0 :          inline virtual operator_type operation() const
   16711             :          {
   16712           0 :             return details::e_default;
   16713             :          }
   16714             : 
   16715             :          virtual const T c() const = 0;
   16716             : 
   16717             :          virtual void set_c(const T) = 0;
   16718             : 
   16719             :          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
   16720             :       };
   16721             : 
   16722             :       template <typename T>
   16723             :       class boc_base_node : public expression_node<T>
   16724             :       {
   16725             :       public:
   16726             : 
   16727      144576 :          virtual ~boc_base_node()
   16728      144576 :          {}
   16729             : 
   16730           0 :          inline virtual operator_type operation() const
   16731             :          {
   16732           0 :             return details::e_default;
   16733             :          }
   16734             : 
   16735             :          virtual const T c() const = 0;
   16736             : 
   16737             :          virtual void set_c(const T) = 0;
   16738             : 
   16739             :          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
   16740             :       };
   16741             : 
   16742             :       template <typename T>
   16743             :       class uv_base_node : public expression_node<T>
   16744             :       {
   16745             :       public:
   16746             : 
   16747        8332 :          virtual ~uv_base_node()
   16748        8332 :          {}
   16749             : 
   16750           0 :          inline virtual operator_type operation() const
   16751             :          {
   16752           0 :             return details::e_default;
   16753             :          }
   16754             : 
   16755             :          virtual const T& v() const = 0;
   16756             :       };
   16757             : 
   16758             :       template <typename T>
   16759             :       class sos_base_node : public expression_node<T>
   16760             :       {
   16761             :       public:
   16762             : 
   16763       30647 :          virtual ~sos_base_node()
   16764       30647 :          {}
   16765             : 
   16766           0 :          inline virtual operator_type operation() const
   16767             :          {
   16768           0 :             return details::e_default;
   16769             :          }
   16770             :       };
   16771             : 
   16772             :       template <typename T>
   16773             :       class sosos_base_node : public expression_node<T>
   16774             :       {
   16775             :       public:
   16776             : 
   16777         300 :          virtual ~sosos_base_node()
   16778         300 :          {}
   16779             : 
   16780           0 :          inline virtual operator_type operation() const
   16781             :          {
   16782           0 :             return details::e_default;
   16783             :          }
   16784             :       };
   16785             : 
   16786             :       template <typename T>
   16787             :       class T0oT1oT2_base_node : public expression_node<T>
   16788             :       {
   16789             :       public:
   16790             : 
   16791      377040 :          virtual ~T0oT1oT2_base_node()
   16792      377040 :          {}
   16793             : 
   16794             :          virtual std::string type_id() const = 0;
   16795             :       };
   16796             : 
   16797             :       template <typename T>
   16798             :       class T0oT1oT2oT3_base_node : public expression_node<T>
   16799             :       {
   16800             :       public:
   16801             : 
   16802      104801 :          virtual ~T0oT1oT2oT3_base_node()
   16803      104801 :          {}
   16804             : 
   16805             :          virtual std::string type_id() const = 0;
   16806             :       };
   16807             : 
   16808             :       template <typename T, typename Operation>
   16809             :       class unary_variable_node exprtk_final : public uv_base_node<T>
   16810             :       {
   16811             :       public:
   16812             : 
   16813             :          typedef expression_node<T>* expression_ptr;
   16814             :          typedef Operation operation_t;
   16815             : 
   16816        8332 :          explicit unary_variable_node(const T& var)
   16817        8332 :          : v_(var)
   16818        8332 :          {}
   16819             : 
   16820    60006359 :          inline T value() const exprtk_override
   16821             :          {
   16822    60006359 :             return Operation::process(v_);
   16823             :          }
   16824             : 
   16825      205316 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16826             :          {
   16827      205316 :             return Operation::type();
   16828             :          }
   16829             : 
   16830        2346 :          inline operator_type operation() const exprtk_override
   16831             :          {
   16832        2346 :             return Operation::operation();
   16833             :          }
   16834             : 
   16835        2360 :          inline const T& v() const exprtk_override
   16836             :          {
   16837        2360 :             return v_;
   16838             :          }
   16839             : 
   16840             :       private:
   16841             : 
   16842             :          unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete;
   16843             :          unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete;
   16844             : 
   16845             :          const T& v_;
   16846             :       };
   16847             : 
   16848             :       template <typename T>
   16849             :       class uvouv_node exprtk_final : public expression_node<T>
   16850             :       {
   16851             :       public:
   16852             : 
   16853             :          // UOpr1(v0) Op UOpr2(v1)
   16854             :          typedef typename details::functor_t<T> functor_t;
   16855             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16856             :          typedef typename functor_t::ufunc_t    ufunc_t;
   16857             :          typedef expression_node<T>*            expression_ptr;
   16858             : 
   16859         620 :          explicit uvouv_node(const T& var0,const T& var1,
   16860             :                              ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
   16861         620 :          : v0_(var0)
   16862         620 :          , v1_(var1)
   16863         620 :          , u0_(uf0 )
   16864         620 :          , u1_(uf1 )
   16865         620 :          , f_ (bf  )
   16866         620 :          {}
   16867             : 
   16868         140 :          inline T value() const exprtk_override
   16869             :          {
   16870         140 :             return f_(u0_(v0_),u1_(v1_));
   16871             :          }
   16872             : 
   16873       20990 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16874             :          {
   16875       20990 :             return expression_node<T>::e_uvouv;
   16876             :          }
   16877             : 
   16878             :          inline const T& v0()
   16879             :          {
   16880             :             return v0_;
   16881             :          }
   16882             : 
   16883             :          inline const T& v1()
   16884             :          {
   16885             :             return v1_;
   16886             :          }
   16887             : 
   16888             :          inline ufunc_t u0()
   16889             :          {
   16890             :             return u0_;
   16891             :          }
   16892             : 
   16893             :          inline ufunc_t u1()
   16894             :          {
   16895             :             return u1_;
   16896             :          }
   16897             : 
   16898             :          inline ufunc_t f()
   16899             :          {
   16900             :             return f_;
   16901             :          }
   16902             : 
   16903             :       private:
   16904             : 
   16905             :          uvouv_node(const uvouv_node<T>&) exprtk_delete;
   16906             :          uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete;
   16907             : 
   16908             :          const T& v0_;
   16909             :          const T& v1_;
   16910             :          const ufunc_t u0_;
   16911             :          const ufunc_t u1_;
   16912             :          const bfunc_t f_;
   16913             :       };
   16914             : 
   16915             :       template <typename T, typename Operation>
   16916             :       class unary_branch_node exprtk_final : public expression_node<T>
   16917             :       {
   16918             :       public:
   16919             : 
   16920             :          typedef Operation                      operation_t;
   16921             :          typedef expression_node<T>*            expression_ptr;
   16922             :          typedef std::pair<expression_ptr,bool> branch_t;
   16923             : 
   16924       59953 :          explicit unary_branch_node(expression_ptr branch)
   16925       59953 :          {
   16926       59953 :             construct_branch_pair(branch_, branch);
   16927       59953 :          }
   16928             : 
   16929   190043663 :          inline T value() const exprtk_override
   16930             :          {
   16931   190043663 :             return Operation::process(branch_.first->value());
   16932             :          }
   16933             : 
   16934      737421 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16935             :          {
   16936      737421 :             return Operation::type();
   16937             :          }
   16938             : 
   16939      133488 :          inline bool valid() const exprtk_override
   16940             :          {
   16941      133488 :             return branch_.first && branch_.first->valid();
   16942             :          }
   16943             : 
   16944             :          inline operator_type operation()
   16945             :          {
   16946             :             return Operation::operation();
   16947             :          }
   16948             : 
   16949        1460 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   16950             :          {
   16951        1460 :             return branch_.first;
   16952             :          }
   16953             : 
   16954        1460 :          inline void release()
   16955             :          {
   16956        1460 :             branch_.second = false;
   16957        1460 :          }
   16958             : 
   16959       59953 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   16960             :          {
   16961       59953 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   16962       59953 :          }
   16963             : 
   16964      113909 :          std::size_t node_depth() const exprtk_override
   16965             :          {
   16966      113909 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   16967             :          }
   16968             : 
   16969             :       private:
   16970             : 
   16971             :          unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete;
   16972             :          unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete;
   16973             : 
   16974             :          branch_t branch_;
   16975             :       };
   16976             : 
   16977             :       template <typename T> struct is_const                { enum {result = 0}; };
   16978             :       template <typename T> struct is_const <const T>      { enum {result = 1}; };
   16979             :       template <typename T> struct is_const_ref            { enum {result = 0}; };
   16980             :       template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
   16981             :       template <typename T> struct is_ref                  { enum {result = 0}; };
   16982             :       template <typename T> struct is_ref<T&>              { enum {result = 1}; };
   16983             :       template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
   16984             : 
   16985             :       template <std::size_t State>
   16986         140 :       struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
   16987             : 
   16988             :       template <>
   16989          72 :       struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
   16990             : 
   16991             :       #define exprtk_crtype(Type)                          \
   16992             :       param_to_str<is_const_ref< Type >::result>::result() \
   16993             : 
   16994             :       template <typename T>
   16995             :       struct T0oT1oT2process
   16996             :       {
   16997             :          typedef typename details::functor_t<T> functor_t;
   16998             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16999             : 
   17000             :          struct mode0
   17001             :          {
   17002     5069329 :             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
   17003             :             {
   17004             :                // (T0 o0 T1) o1 T2
   17005     5069329 :                return bf1(bf0(t0,t1),t2);
   17006             :             }
   17007             : 
   17008             :             template <typename T0, typename T1, typename T2>
   17009      652080 :             static inline std::string id()
   17010             :             {
   17011      652080 :                static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
   17012             :                                                        exprtk_crtype(T1) + ")o(" +
   17013             :                                                        exprtk_crtype(T2) + ")"   ;
   17014      652080 :                return result;
   17015             :             }
   17016             :          };
   17017             : 
   17018             :          struct mode1
   17019             :          {
   17020       53400 :             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
   17021             :             {
   17022             :                // T0 o0 (T1 o1 T2)
   17023       53400 :                return bf0(t0,bf1(t1,t2));
   17024             :             }
   17025             : 
   17026             :             template <typename T0, typename T1, typename T2>
   17027      651993 :             static inline std::string id()
   17028             :             {
   17029      651993 :                static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
   17030             :                                                        exprtk_crtype(T1) + "o"   +
   17031             :                                                        exprtk_crtype(T2) + ")"   ;
   17032      651993 :                return result;
   17033             :             }
   17034             :          };
   17035             :       };
   17036             : 
   17037             :       template <typename T>
   17038             :       struct T0oT1oT20T3process
   17039             :       {
   17040             :          typedef typename details::functor_t<T> functor_t;
   17041             :          typedef typename functor_t::bfunc_t    bfunc_t;
   17042             : 
   17043             :          struct mode0
   17044             :          {
   17045    11413258 :             static inline T process(const T& t0, const T& t1,
   17046             :                                     const T& t2, const T& t3,
   17047             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   17048             :             {
   17049             :                // (T0 o0 T1) o1 (T2 o2 T3)
   17050    11413258 :                return bf1(bf0(t0,t1),bf2(t2,t3));
   17051             :             }
   17052             : 
   17053             :             template <typename T0, typename T1, typename T2, typename T3>
   17054      982190 :             static inline std::string id()
   17055             :             {
   17056      982190 :                static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
   17057             :                                                        exprtk_crtype(T1) + ")o" +
   17058             :                                                  "(" + exprtk_crtype(T2) + "o"  +
   17059             :                                                        exprtk_crtype(T3) + ")"  ;
   17060      982190 :                return result;
   17061             :             }
   17062             :          };
   17063             : 
   17064             :          struct mode1
   17065             :          {
   17066           0 :             static inline T process(const T& t0, const T& t1,
   17067             :                                     const T& t2, const T& t3,
   17068             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   17069             :             {
   17070             :                // (T0 o0 (T1 o1 (T2 o2 T3))
   17071           0 :                return bf0(t0,bf1(t1,bf2(t2,t3)));
   17072             :             }
   17073             :             template <typename T0, typename T1, typename T2, typename T3>
   17074      977940 :             static inline std::string id()
   17075             :             {
   17076      977940 :                static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
   17077             :                                                        exprtk_crtype(T1) +  ")o("  +
   17078             :                                                        exprtk_crtype(T2) +  "o"    +
   17079             :                                                        exprtk_crtype(T3) +  "))"   ;
   17080      977940 :                return result;
   17081             :             }
   17082             :          };
   17083             : 
   17084             :          struct mode2
   17085             :          {
   17086           0 :             static inline T process(const T& t0, const T& t1,
   17087             :                                     const T& t2, const T& t3,
   17088             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   17089             :             {
   17090             :                // (T0 o0 ((T1 o1 T2) o2 T3)
   17091           0 :                return bf0(t0,bf2(bf1(t1,t2),t3));
   17092             :             }
   17093             : 
   17094             :             template <typename T0, typename T1, typename T2, typename T3>
   17095      869280 :             static inline std::string id()
   17096             :             {
   17097      869280 :                static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
   17098             :                                                        exprtk_crtype(T1) + "o"    +
   17099             :                                                        exprtk_crtype(T2) + ")o("  +
   17100             :                                                        exprtk_crtype(T3) + "))"   ;
   17101      869280 :                return result;
   17102             :             }
   17103             :          };
   17104             : 
   17105             :          struct mode3
   17106             :          {
   17107           0 :             static inline T process(const T& t0, const T& t1,
   17108             :                                     const T& t2, const T& t3,
   17109             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   17110             :             {
   17111             :                // (((T0 o0 T1) o1 T2) o2 T3)
   17112           0 :                return bf2(bf1(bf0(t0,t1),t2),t3);
   17113             :             }
   17114             : 
   17115             :             template <typename T0, typename T1, typename T2, typename T3>
   17116      977940 :             static inline std::string id()
   17117             :             {
   17118      977940 :                static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
   17119             :                                                         exprtk_crtype(T1) + ")o("  +
   17120             :                                                         exprtk_crtype(T2) + "))o(" +
   17121             :                                                         exprtk_crtype(T3) + ")";
   17122      977940 :                return result;
   17123             :             }
   17124             :          };
   17125             : 
   17126             :          struct mode4
   17127             :          {
   17128           0 :             static inline T process(const T& t0, const T& t1,
   17129             :                                     const T& t2, const T& t3,
   17130             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   17131             :             {
   17132             :                // ((T0 o0 (T1 o1 T2)) o2 T3
   17133           0 :                return bf2(bf0(t0,bf1(t1,t2)),t3);
   17134             :             }
   17135             : 
   17136             :             template <typename T0, typename T1, typename T2, typename T3>
   17137      869280 :             static inline std::string id()
   17138             :             {
   17139      869280 :                static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
   17140             :                                                         exprtk_crtype(T1) + "o"    +
   17141             :                                                         exprtk_crtype(T2) + "))o(" +
   17142             :                                                         exprtk_crtype(T3) + ")"    ;
   17143      869280 :                return result;
   17144             :             }
   17145             :          };
   17146             :       };
   17147             : 
   17148             :       #undef exprtk_crtype
   17149             : 
   17150             :       template <typename T, typename T0, typename T1>
   17151             :       struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
   17152             :       template <typename T, typename T0, typename T1>
   17153             :       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
   17154             : 
   17155             :       #define synthesis_node_type_define(T0_, T1_, v_)                                                          \
   17156             :       template <typename T, typename T0, typename T1>                                                           \
   17157             :       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
   17158             :       template <typename T, typename T0, typename T1>                                                           \
   17159             :       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
   17160             : 
   17161             :       synthesis_node_type_define(const T0&, const T1&,  e_vov)
   17162             :       synthesis_node_type_define(const T0&, const T1 ,  e_voc)
   17163             :       synthesis_node_type_define(const T0 , const T1&,  e_cov)
   17164             :       synthesis_node_type_define(      T0&,       T1&, e_none)
   17165             :       synthesis_node_type_define(const T0 , const T1 , e_none)
   17166             :       synthesis_node_type_define(      T0&, const T1 , e_none)
   17167             :       synthesis_node_type_define(const T0 ,       T1&, e_none)
   17168             :       synthesis_node_type_define(const T0&,       T1&, e_none)
   17169             :       synthesis_node_type_define(      T0&, const T1&, e_none)
   17170             :       #undef synthesis_node_type_define
   17171             : 
   17172             :       template <typename T, typename T0, typename T1, typename T2>
   17173             :       struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
   17174             :       template <typename T, typename T0, typename T1, typename T2>
   17175             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
   17176             : 
   17177             :       #define synthesis_node_type_define(T0_, T1_, T2_, v_)                                                            \
   17178             :       template <typename T, typename T0, typename T1, typename T2>                                                     \
   17179             :       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
   17180             :       template <typename T, typename T0, typename T1, typename T2>                                                     \
   17181             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
   17182             : 
   17183             :       synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
   17184             :       synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
   17185             :       synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
   17186             :       synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
   17187             :       synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
   17188             :       synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
   17189             :       synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
   17190             :       synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
   17191             :       synthesis_node_type_define(      T0&,       T1&,       T2&, e_none )
   17192             :       #undef synthesis_node_type_define
   17193             : 
   17194             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   17195             :       struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
   17196             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   17197             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
   17198             : 
   17199             :       #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_)                                                              \
   17200             :       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
   17201             :       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
   17202             :       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
   17203             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
   17204             : 
   17205             :       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
   17206             :       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
   17207             :       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
   17208             :       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
   17209             :       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
   17210             :       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
   17211             :       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
   17212             :       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
   17213             :       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
   17214             :       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none   )
   17215             :       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none   )
   17216             :       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none   )
   17217             :       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none   )
   17218             :       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none   )
   17219             :       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none   )
   17220             :       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none   )
   17221             :       #undef synthesis_node_type_define
   17222             : 
   17223             :       template <typename T, typename T0, typename T1>
   17224             :       class T0oT1 exprtk_final : public expression_node<T>
   17225             :       {
   17226             :       public:
   17227             : 
   17228             :          typedef typename details::functor_t<T> functor_t;
   17229             :          typedef typename functor_t::bfunc_t    bfunc_t;
   17230             :          typedef T value_type;
   17231             :          typedef T0oT1<T,T0,T1> node_type;
   17232             : 
   17233             :          T0oT1(T0 p0, T1 p1, const bfunc_t p2)
   17234             :          : t0_(p0)
   17235             :          , t1_(p1)
   17236             :          , f_ (p2)
   17237             :          {}
   17238             : 
   17239             :          inline typename expression_node<T>::node_type type() const exprtk_override
   17240             :          {
   17241             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
   17242             :             return result;
   17243             :          }
   17244             : 
   17245             :          inline operator_type operation() const exprtk_override
   17246             :          {
   17247             :             return e_default;
   17248             :          }
   17249             : 
   17250             :          inline T value() const exprtk_override
   17251             :          {
   17252             :             return f_(t0_,t1_);
   17253             :          }
   17254             : 
   17255             :          inline T0 t0() const
   17256             :          {
   17257             :             return t0_;
   17258             :          }
   17259             : 
   17260             :          inline T1 t1() const
   17261             :          {
   17262             :             return t1_;
   17263             :          }
   17264             : 
   17265             :          inline bfunc_t f() const
   17266             :          {
   17267             :             return f_;
   17268             :          }
   17269             : 
   17270             :          template <typename Allocator>
   17271             :          static inline expression_node<T>* allocate(Allocator& allocator,
   17272             :                                                     T0 p0, T1 p1,
   17273             :                                                     bfunc_t p2)
   17274             :          {
   17275             :             return allocator
   17276             :                      .template allocate_type<node_type, T0, T1, bfunc_t&>
   17277             :                         (p0, p1, p2);
   17278             :          }
   17279             : 
   17280             :       private:
   17281             : 
   17282             :          T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete;
   17283             :          T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); }
   17284             : 
   17285             :          T0 t0_;
   17286             :          T1 t1_;
   17287             :          const bfunc_t f_;
   17288             :       };
   17289             : 
   17290             :       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
   17291             :       class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T>
   17292             :       {
   17293             :       public:
   17294             : 
   17295             :          typedef typename details::functor_t<T> functor_t;
   17296             :          typedef typename functor_t::bfunc_t    bfunc_t;
   17297             :          typedef T value_type;
   17298             :          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
   17299             :          typedef ProcessMode process_mode_t;
   17300             : 
   17301        5960 :          T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
   17302        5960 :          : t0_(p0)
   17303        5960 :          , t1_(p1)
   17304        5960 :          , t2_(p2)
   17305        5960 :          , f0_(p3)
   17306        5960 :          , f1_(p4)
   17307        5960 :          {}
   17308             : 
   17309       38380 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17310             :          {
   17311             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
   17312       38380 :             return result;
   17313             :          }
   17314             : 
   17315             :          inline operator_type operation()
   17316             :          {
   17317             :             return e_default;
   17318             :          }
   17319             : 
   17320     5122729 :          inline T value() const exprtk_override
   17321             :          {
   17322     5122729 :             return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
   17323             :          }
   17324             : 
   17325           0 :          inline T0 t0() const
   17326             :          {
   17327           0 :             return t0_;
   17328             :          }
   17329             : 
   17330           0 :          inline T1 t1() const
   17331             :          {
   17332           0 :             return t1_;
   17333             :          }
   17334             : 
   17335           0 :          inline T2 t2() const
   17336             :          {
   17337           0 :             return t2_;
   17338             :          }
   17339             : 
   17340           0 :          bfunc_t f0() const
   17341             :          {
   17342           0 :             return f0_;
   17343             :          }
   17344             : 
   17345           0 :          bfunc_t f1() const
   17346             :          {
   17347           0 :             return f1_;
   17348             :          }
   17349             : 
   17350         153 :          std::string type_id() const exprtk_override
   17351             :          {
   17352         153 :             return id();
   17353             :          }
   17354             : 
   17355     1304073 :          static inline std::string id()
   17356             :          {
   17357     1304073 :             return process_mode_t::template id<T0,T1,T2>();
   17358             :          }
   17359             : 
   17360             :          template <typename Allocator>
   17361        5960 :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
   17362             :          {
   17363             :             return allocator
   17364             :                       .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
   17365        5960 :                          (p0, p1, p2, p3, p4);
   17366             :          }
   17367             : 
   17368             :       private:
   17369             : 
   17370             :          T0oT1oT2(const node_type&) exprtk_delete;
   17371             :          node_type& operator=(const node_type&) exprtk_delete;
   17372             : 
   17373             :          T0 t0_;
   17374             :          T1 t1_;
   17375             :          T2 t2_;
   17376             :          const bfunc_t f0_;
   17377             :          const bfunc_t f1_;
   17378             :       };
   17379             : 
   17380             :       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
   17381             :       class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T>
   17382             :       {
   17383             :       public:
   17384             : 
   17385             :          typedef typename details::functor_t<T> functor_t;
   17386             :          typedef typename functor_t::bfunc_t    bfunc_t;
   17387             :          typedef T value_type;
   17388             :          typedef T0_ T0;
   17389             :          typedef T1_ T1;
   17390             :          typedef T2_ T2;
   17391             :          typedef T3_ T3;
   17392             :          typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
   17393             :          typedef ProcessMode process_mode_t;
   17394             : 
   17395        6917 :          T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
   17396        6917 :          : t0_(p0)
   17397        6917 :          , t1_(p1)
   17398        6917 :          , t2_(p2)
   17399        6917 :          , t3_(p3)
   17400        6917 :          , f0_(p4)
   17401        6917 :          , f1_(p5)
   17402        6917 :          , f2_(p6)
   17403        6917 :          {}
   17404             : 
   17405    11413258 :          inline T value() const exprtk_override
   17406             :          {
   17407    11413258 :             return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
   17408             :          }
   17409             : 
   17410             :          inline T0 t0() const
   17411             :          {
   17412             :             return t0_;
   17413             :          }
   17414             : 
   17415             :          inline T1 t1() const
   17416             :          {
   17417             :             return t1_;
   17418             :          }
   17419             : 
   17420             :          inline T2 t2() const
   17421             :          {
   17422             :             return t2_;
   17423             :          }
   17424             : 
   17425             :          inline T3 t3() const
   17426             :          {
   17427             :             return t3_;
   17428             :          }
   17429             : 
   17430             :          inline bfunc_t f0() const
   17431             :          {
   17432             :             return f0_;
   17433             :          }
   17434             : 
   17435             :          inline bfunc_t f1() const
   17436             :          {
   17437             :             return f1_;
   17438             :          }
   17439             : 
   17440             :          inline bfunc_t f2() const
   17441             :          {
   17442             :             return f2_;
   17443             :          }
   17444             : 
   17445        4250 :          inline std::string type_id() const exprtk_override
   17446             :          {
   17447        4250 :             return id();
   17448             :          }
   17449             : 
   17450     4676630 :          static inline std::string id()
   17451             :          {
   17452     4676630 :             return process_mode_t::template id<T0, T1, T2, T3>();
   17453             :          }
   17454             : 
   17455             :          template <typename Allocator>
   17456        6917 :          static inline expression_node<T>* allocate(Allocator& allocator,
   17457             :                                                     T0 p0, T1 p1, T2 p2, T3 p3,
   17458             :                                                     bfunc_t p4, bfunc_t p5, bfunc_t p6)
   17459             :          {
   17460             :             return allocator
   17461             :                       .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
   17462        6917 :                          (p0, p1, p2, p3, p4, p5, p6);
   17463             :          }
   17464             : 
   17465             :       private:
   17466             : 
   17467             :          T0oT1oT2oT3(const node_type&) exprtk_delete;
   17468             :          node_type& operator=(const node_type&) exprtk_delete;
   17469             : 
   17470             :          T0 t0_;
   17471             :          T1 t1_;
   17472             :          T2 t2_;
   17473             :          T3 t3_;
   17474             :          const bfunc_t f0_;
   17475             :          const bfunc_t f1_;
   17476             :          const bfunc_t f2_;
   17477             :       };
   17478             : 
   17479             :       template <typename T, typename T0, typename T1, typename T2>
   17480             :       class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T>
   17481             :       {
   17482             :       public:
   17483             : 
   17484             :          typedef typename details::functor_t<T> functor_t;
   17485             :          typedef typename functor_t::tfunc_t    tfunc_t;
   17486             :          typedef T value_type;
   17487             :          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
   17488             : 
   17489             :          T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
   17490             :          : t0_(p0)
   17491             :          , t1_(p1)
   17492             :          , t2_(p2)
   17493             :          , f_ (p3)
   17494             :          {}
   17495             : 
   17496             :          inline typename expression_node<T>::node_type type() const exprtk_override
   17497             :          {
   17498             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
   17499             :             return result;
   17500             :          }
   17501             : 
   17502             :          inline operator_type operation() const exprtk_override
   17503             :          {
   17504             :             return e_default;
   17505             :          }
   17506             : 
   17507             :          inline T value() const exprtk_override
   17508             :          {
   17509             :             return f_(t0_, t1_, t2_);
   17510             :          }
   17511             : 
   17512             :          inline T0 t0() const
   17513             :          {
   17514             :             return t0_;
   17515             :          }
   17516             : 
   17517             :          inline T1 t1() const
   17518             :          {
   17519             :             return t1_;
   17520             :          }
   17521             : 
   17522             :          inline T2 t2() const
   17523             :          {
   17524             :             return t2_;
   17525             :          }
   17526             : 
   17527             :          tfunc_t f() const
   17528             :          {
   17529             :             return f_;
   17530             :          }
   17531             : 
   17532             :          std::string type_id() const
   17533             :          {
   17534             :             return id();
   17535             :          }
   17536             : 
   17537             :          static inline std::string id()
   17538             :          {
   17539             :             return "sf3";
   17540             :          }
   17541             : 
   17542             :          template <typename Allocator>
   17543             :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
   17544             :          {
   17545             :             return allocator
   17546             :                      .template allocate_type<node_type, T0, T1, T2, tfunc_t>
   17547             :                         (p0, p1, p2, p3);
   17548             :          }
   17549             : 
   17550             :       private:
   17551             : 
   17552             :          T0oT1oT2_sf3(const node_type&) exprtk_delete;
   17553             :          node_type& operator=(const node_type&) exprtk_delete;
   17554             : 
   17555             :          T0 t0_;
   17556             :          T1 t1_;
   17557             :          T2 t2_;
   17558             :          const tfunc_t f_;
   17559             :       };
   17560             : 
   17561             :       template <typename T, typename T0, typename T1, typename T2>
   17562             :       class sf3ext_type_node : public T0oT1oT2_base_node<T>
   17563             :       {
   17564             :       public:
   17565             : 
   17566      371080 :          virtual ~sf3ext_type_node()
   17567      371080 :          {}
   17568             : 
   17569             :          virtual T0 t0() const = 0;
   17570             : 
   17571             :          virtual T1 t1() const = 0;
   17572             : 
   17573             :          virtual T2 t2() const = 0;
   17574             :       };
   17575             : 
   17576             :       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
   17577             :       class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2>
   17578             :       {
   17579             :       public:
   17580             : 
   17581             :          typedef T value_type;
   17582             :          typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type;
   17583             : 
   17584      371080 :          T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
   17585      371080 :          : t0_(p0)
   17586      371080 :          , t1_(p1)
   17587      371080 :          , t2_(p2)
   17588      371080 :          {}
   17589             : 
   17590    12070008 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17591             :          {
   17592             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
   17593    12070008 :             return result;
   17594             :          }
   17595             : 
   17596             :          inline operator_type operation()
   17597             :          {
   17598             :             return e_default;
   17599             :          }
   17600             : 
   17601   120067133 :          inline T value() const exprtk_override
   17602             :          {
   17603   120067133 :             return SF3Operation::process(t0_, t1_, t2_);
   17604             :          }
   17605             : 
   17606      181199 :          T0 t0() const exprtk_override
   17607             :          {
   17608      181199 :             return t0_;
   17609             :          }
   17610             : 
   17611      181199 :          T1 t1() const exprtk_override
   17612             :          {
   17613      181199 :             return t1_;
   17614             :          }
   17615             : 
   17616      181199 :          T2 t2() const exprtk_override
   17617             :          {
   17618      181199 :             return t2_;
   17619             :          }
   17620             : 
   17621      527283 :          std::string type_id() const exprtk_override
   17622             :          {
   17623      527283 :             return id();
   17624             :          }
   17625             : 
   17626      527283 :          static inline std::string id()
   17627             :          {
   17628      527283 :             return SF3Operation::id();
   17629             :          }
   17630             : 
   17631             :          template <typename Allocator>
   17632      371080 :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
   17633             :          {
   17634             :             return allocator
   17635             :                      .template allocate_type<node_type, T0, T1, T2>
   17636      371080 :                         (p0, p1, p2);
   17637             :          }
   17638             : 
   17639             :       private:
   17640             : 
   17641             :          T0oT1oT2_sf3ext(const node_type&) exprtk_delete;
   17642             :          node_type& operator=(const node_type&) exprtk_delete;
   17643             : 
   17644             :          T0 t0_;
   17645             :          T1 t1_;
   17646             :          T2 t2_;
   17647             :       };
   17648             : 
   17649             :       template <typename T>
   17650      839039 :       inline bool is_sf3ext_node(const expression_node<T>* n)
   17651             :       {
   17652      839039 :          switch (n->type())
   17653             :          {
   17654       99912 :             case expression_node<T>::e_vovov : return true;
   17655       82671 :             case expression_node<T>::e_vovoc : return true;
   17656       80666 :             case expression_node<T>::e_vocov : return true;
   17657       84620 :             case expression_node<T>::e_covov : return true;
   17658       14530 :             case expression_node<T>::e_covoc : return true;
   17659      476640 :             default                          : return false;
   17660             :          }
   17661             :       }
   17662             : 
   17663             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   17664             :       class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T>
   17665             :       {
   17666             :       public:
   17667             : 
   17668             :          typedef typename details::functor_t<T> functor_t;
   17669             :          typedef typename functor_t::qfunc_t    qfunc_t;
   17670             :          typedef T value_type;
   17671             :          typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type;
   17672             : 
   17673             :          T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
   17674             :          : t0_(p0)
   17675             :          , t1_(p1)
   17676             :          , t2_(p2)
   17677             :          , t3_(p3)
   17678             :          , f_ (p4)
   17679             :          {}
   17680             : 
   17681             :          inline typename expression_node<T>::node_type type() const exprtk_override
   17682             :          {
   17683             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
   17684             :             return result;
   17685             :          }
   17686             : 
   17687             :          inline operator_type operation() const exprtk_override
   17688             :          {
   17689             :             return e_default;
   17690             :          }
   17691             : 
   17692             :          inline T value() const exprtk_override
   17693             :          {
   17694             :             return f_(t0_, t1_, t2_, t3_);
   17695             :          }
   17696             : 
   17697             :          inline T0 t0() const
   17698             :          {
   17699             :             return t0_;
   17700             :          }
   17701             : 
   17702             :          inline T1 t1() const
   17703             :          {
   17704             :             return t1_;
   17705             :          }
   17706             : 
   17707             :          inline T2 t2() const
   17708             :          {
   17709             :             return t2_;
   17710             :          }
   17711             : 
   17712             :          inline T3 t3() const
   17713             :          {
   17714             :             return t3_;
   17715             :          }
   17716             : 
   17717             :          qfunc_t f() const
   17718             :          {
   17719             :             return f_;
   17720             :          }
   17721             : 
   17722             :          std::string type_id() const
   17723             :          {
   17724             :             return id();
   17725             :          }
   17726             : 
   17727             :          static inline std::string id()
   17728             :          {
   17729             :             return "sf4";
   17730             :          }
   17731             : 
   17732             :          template <typename Allocator>
   17733             :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
   17734             :          {
   17735             :             return allocator
   17736             :                      .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
   17737             :                         (p0, p1, p2, p3, p4);
   17738             :          }
   17739             : 
   17740             :       private:
   17741             : 
   17742             :          T0oT1oT2oT3_sf4(const node_type&) exprtk_delete;
   17743             :          node_type& operator=(const node_type&) exprtk_delete;
   17744             : 
   17745             :          T0 t0_;
   17746             :          T1 t1_;
   17747             :          T2 t2_;
   17748             :          T3 t3_;
   17749             :          const qfunc_t f_;
   17750             :       };
   17751             : 
   17752             :       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
   17753             :       class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T>
   17754             :       {
   17755             :       public:
   17756             : 
   17757             :          typedef T value_type;
   17758             :          typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type;
   17759             : 
   17760       97884 :          T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
   17761       97884 :          : t0_(p0)
   17762       97884 :          , t1_(p1)
   17763       97884 :          , t2_(p2)
   17764       97884 :          , t3_(p3)
   17765       97884 :          {}
   17766             : 
   17767     3280533 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17768             :          {
   17769             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
   17770     3280533 :             return result;
   17771             :          }
   17772             : 
   17773       97271 :          inline T value() const exprtk_override
   17774             :          {
   17775       97271 :             return SF4Operation::process(t0_, t1_, t2_, t3_);
   17776             :          }
   17777             : 
   17778             :          inline T0 t0() const
   17779             :          {
   17780             :             return t0_;
   17781             :          }
   17782             : 
   17783             :          inline T1 t1() const
   17784             :          {
   17785             :             return t1_;
   17786             :          }
   17787             : 
   17788             :          inline T2 t2() const
   17789             :          {
   17790             :             return t2_;
   17791             :          }
   17792             : 
   17793             :          inline T3 t3() const
   17794             :          {
   17795             :             return t3_;
   17796             :          }
   17797             : 
   17798       84472 :          std::string type_id() const exprtk_override
   17799             :          {
   17800       84472 :             return id();
   17801             :          }
   17802             : 
   17803       84472 :          static inline std::string id()
   17804             :          {
   17805       84472 :             return SF4Operation::id();
   17806             :          }
   17807             : 
   17808             :          template <typename Allocator>
   17809       97884 :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
   17810             :          {
   17811             :             return allocator
   17812             :                      .template allocate_type<node_type, T0, T1, T2, T3>
   17813       97884 :                         (p0, p1, p2, p3);
   17814             :          }
   17815             : 
   17816             :       private:
   17817             : 
   17818             :          T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete;
   17819             :          node_type& operator=(const node_type&) exprtk_delete;
   17820             : 
   17821             :          T0 t0_;
   17822             :          T1 t1_;
   17823             :          T2 t2_;
   17824             :          T3 t3_;
   17825             :       };
   17826             : 
   17827             :       template <typename T>
   17828           0 :       inline bool is_sf4ext_node(const expression_node<T>* n)
   17829             :       {
   17830           0 :          switch (n->type())
   17831             :          {
   17832           0 :             case expression_node<T>::e_vovovov : return true;
   17833           0 :             case expression_node<T>::e_vovovoc : return true;
   17834           0 :             case expression_node<T>::e_vovocov : return true;
   17835           0 :             case expression_node<T>::e_vocovov : return true;
   17836           0 :             case expression_node<T>::e_covovov : return true;
   17837           0 :             case expression_node<T>::e_covocov : return true;
   17838           0 :             case expression_node<T>::e_vocovoc : return true;
   17839           0 :             case expression_node<T>::e_covovoc : return true;
   17840           0 :             case expression_node<T>::e_vococov : return true;
   17841           0 :             default                            : return false;
   17842             :          }
   17843             :       }
   17844             : 
   17845             :       template <typename T, typename T0, typename T1>
   17846             :       struct T0oT1_define
   17847             :       {
   17848             :          typedef details::T0oT1<T, T0, T1> type0;
   17849             :       };
   17850             : 
   17851             :       template <typename T, typename T0, typename T1, typename T2>
   17852             :       struct T0oT1oT2_define
   17853             :       {
   17854             :          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
   17855             :          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
   17856             :          typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
   17857             :          typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
   17858             :       };
   17859             : 
   17860             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   17861             :       struct T0oT1oT2oT3_define
   17862             :       {
   17863             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
   17864             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
   17865             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
   17866             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
   17867             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
   17868             :          typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
   17869             :       };
   17870             : 
   17871             :       template <typename T, typename Operation>
   17872             :       class vov_node exprtk_final : public vov_base_node<T>
   17873             :       {
   17874             :       public:
   17875             : 
   17876             :          typedef expression_node<T>* expression_ptr;
   17877             :          typedef Operation operation_t;
   17878             : 
   17879             :          // variable op variable node
   17880      265747 :          explicit vov_node(const T& var0, const T& var1)
   17881      265747 :          : v0_(var0)
   17882      265747 :          , v1_(var1)
   17883      265747 :          {}
   17884             : 
   17885    10561674 :          inline T value() const exprtk_override
   17886             :          {
   17887    10561674 :             return Operation::process(v0_,v1_);
   17888             :          }
   17889             : 
   17890     5332602 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17891             :          {
   17892     5332602 :             return Operation::type();
   17893             :          }
   17894             : 
   17895      217869 :          inline operator_type operation() const exprtk_override
   17896             :          {
   17897      217869 :             return Operation::operation();
   17898             :          }
   17899             : 
   17900      217869 :          inline const T& v0() const exprtk_override
   17901             :          {
   17902      217869 :             return v0_;
   17903             :          }
   17904             : 
   17905      217869 :          inline const T& v1() const exprtk_override
   17906             :          {
   17907      217869 :             return v1_;
   17908             :          }
   17909             : 
   17910             :       protected:
   17911             : 
   17912             :          const T& v0_;
   17913             :          const T& v1_;
   17914             : 
   17915             :       private:
   17916             : 
   17917             :          vov_node(const vov_node<T,Operation>&) exprtk_delete;
   17918             :          vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete;
   17919             :       };
   17920             : 
   17921             :       template <typename T, typename Operation>
   17922             :       class cov_node exprtk_final : public cov_base_node<T>
   17923             :       {
   17924             :       public:
   17925             : 
   17926             :          typedef expression_node<T>* expression_ptr;
   17927             :          typedef Operation operation_t;
   17928             : 
   17929             :          // constant op variable node
   17930      243926 :          explicit cov_node(const T& const_var, const T& var)
   17931      243926 :          : c_(const_var)
   17932      243926 :          , v_(var)
   17933      243926 :          {}
   17934             : 
   17935    40059009 :          inline T value() const exprtk_override
   17936             :          {
   17937    40059009 :             return Operation::process(c_,v_);
   17938             :          }
   17939             : 
   17940     5131284 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17941             :          {
   17942     5131284 :             return Operation::type();
   17943             :          }
   17944             : 
   17945      184595 :          inline operator_type operation() const exprtk_override
   17946             :          {
   17947      184595 :             return Operation::operation();
   17948             :          }
   17949             : 
   17950      184595 :          inline const T c() const exprtk_override
   17951             :          {
   17952      184595 :             return c_;
   17953             :          }
   17954             : 
   17955      184595 :          inline const T& v() const exprtk_override
   17956             :          {
   17957      184595 :             return v_;
   17958             :          }
   17959             : 
   17960             :       protected:
   17961             : 
   17962             :          const T  c_;
   17963             :          const T& v_;
   17964             : 
   17965             :       private:
   17966             : 
   17967             :          cov_node(const cov_node<T,Operation>&) exprtk_delete;
   17968             :          cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete;
   17969             :       };
   17970             : 
   17971             :       template <typename T, typename Operation>
   17972             :       class voc_node exprtk_final : public voc_base_node<T>
   17973             :       {
   17974             :       public:
   17975             : 
   17976             :          typedef expression_node<T>* expression_ptr;
   17977             :          typedef Operation operation_t;
   17978             : 
   17979             :          // variable op constant node
   17980      288796 :          explicit voc_node(const T& var, const T& const_var)
   17981      288796 :          : v_(var)
   17982      288796 :          , c_(const_var)
   17983      288796 :          {}
   17984             : 
   17985   245875857 :          inline T value() const exprtk_override
   17986             :          {
   17987   245875857 :             return Operation::process(v_,c_);
   17988             :          }
   17989             : 
   17990      161215 :          inline operator_type operation() const exprtk_override
   17991             :          {
   17992      161215 :             return Operation::operation();
   17993             :          }
   17994             : 
   17995      161215 :          inline const T c() const exprtk_override
   17996             :          {
   17997      161215 :             return c_;
   17998             :          }
   17999             : 
   18000      161215 :          inline const T& v() const exprtk_override
   18001             :          {
   18002      161215 :             return v_;
   18003             :          }
   18004             : 
   18005             :       protected:
   18006             : 
   18007             :          const T& v_;
   18008             :          const T  c_;
   18009             : 
   18010             :       private:
   18011             : 
   18012             :          voc_node(const voc_node<T,Operation>&) exprtk_delete;
   18013             :          voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete;
   18014             :       };
   18015             : 
   18016             :       template <typename T, typename Operation>
   18017             :       class vob_node exprtk_final : public vob_base_node<T>
   18018             :       {
   18019             :       public:
   18020             : 
   18021             :          typedef expression_node<T>* expression_ptr;
   18022             :          typedef std::pair<expression_ptr,bool> branch_t;
   18023             :          typedef Operation operation_t;
   18024             : 
   18025             :          // variable op binary node
   18026       33759 :          explicit vob_node(const T& var, const expression_ptr branch)
   18027       33759 :          : v_(var)
   18028             :          {
   18029       33759 :             construct_branch_pair(branch_, branch);
   18030       33759 :             assert(valid());
   18031       33759 :          }
   18032             : 
   18033       26104 :          inline T value() const exprtk_override
   18034             :          {
   18035       26104 :             return Operation::process(v_,branch_.first->value());
   18036             :          }
   18037             : 
   18038           0 :          inline const T& v() const exprtk_override
   18039             :          {
   18040           0 :             return v_;
   18041             :          }
   18042             : 
   18043      150568 :          inline bool valid() const exprtk_override
   18044             :          {
   18045      150568 :             return branch_.first && branch_.first->valid();
   18046             :          }
   18047             : 
   18048           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   18049             :          {
   18050           0 :             return branch_.first;
   18051             :          }
   18052             : 
   18053       33759 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18054             :          {
   18055       33759 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18056       33759 :          }
   18057             : 
   18058      135806 :          std::size_t node_depth() const exprtk_override
   18059             :          {
   18060      135806 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18061             :          }
   18062             : 
   18063             :       private:
   18064             : 
   18065             :          vob_node(const vob_node<T,Operation>&) exprtk_delete;
   18066             :          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete;
   18067             : 
   18068             :          const T& v_;
   18069             :          branch_t branch_;
   18070             :       };
   18071             : 
   18072             :       template <typename T, typename Operation>
   18073             :       class bov_node exprtk_final : public bov_base_node<T>
   18074             :       {
   18075             :       public:
   18076             : 
   18077             :          typedef expression_node<T>* expression_ptr;
   18078             :          typedef std::pair<expression_ptr,bool> branch_t;
   18079             :          typedef Operation operation_t;
   18080             : 
   18081             :          // binary node op variable node
   18082      352771 :          explicit bov_node(const expression_ptr branch, const T& var)
   18083      352771 :          : v_(var)
   18084             :          {
   18085      352771 :             construct_branch_pair(branch_, branch);
   18086      352771 :             assert(valid());
   18087      352771 :          }
   18088             : 
   18089     5042963 :          inline T value() const exprtk_override
   18090             :          {
   18091     5042963 :             return Operation::process(branch_.first->value(),v_);
   18092             :          }
   18093             : 
   18094           0 :          inline const T& v() const exprtk_override
   18095             :          {
   18096           0 :             return v_;
   18097             :          }
   18098             : 
   18099    16169031 :          inline bool valid() const exprtk_override
   18100             :          {
   18101    16169031 :             return branch_.first && branch_.first->valid();
   18102             :          }
   18103             : 
   18104           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   18105             :          {
   18106           0 :             return branch_.first;
   18107             :          }
   18108             : 
   18109      352771 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18110             :          {
   18111      352771 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18112      352771 :          }
   18113             : 
   18114      894013 :          std::size_t node_depth() const exprtk_override
   18115             :          {
   18116      894013 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18117             :          }
   18118             : 
   18119             :       private:
   18120             : 
   18121             :          bov_node(const bov_node<T,Operation>&) exprtk_delete;
   18122             :          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete;
   18123             : 
   18124             :          const T& v_;
   18125             :          branch_t branch_;
   18126             :       };
   18127             : 
   18128             :       template <typename T, typename Operation>
   18129             :       class cob_node exprtk_final : public cob_base_node<T>
   18130             :       {
   18131             :       public:
   18132             : 
   18133             :          typedef expression_node<T>* expression_ptr;
   18134             :          typedef std::pair<expression_ptr,bool> branch_t;
   18135             :          typedef Operation operation_t;
   18136             : 
   18137             :          // constant op variable node
   18138       89268 :          explicit cob_node(const T const_var, const expression_ptr branch)
   18139       89268 :          : c_(const_var)
   18140             :          {
   18141       89268 :             construct_branch_pair(branch_, branch);
   18142       89268 :             assert(valid());
   18143       89268 :          }
   18144             : 
   18145    10225863 :          inline T value() const exprtk_override
   18146             :          {
   18147    10225863 :             return Operation::process(c_,branch_.first->value());
   18148             :          }
   18149             : 
   18150       21065 :          inline operator_type operation() const exprtk_override
   18151             :          {
   18152       21065 :             return Operation::operation();
   18153             :          }
   18154             : 
   18155        5920 :          inline const T c() const exprtk_override
   18156             :          {
   18157        5920 :             return c_;
   18158             :          }
   18159             : 
   18160        4985 :          inline void set_c(const T new_c) exprtk_override
   18161             :          {
   18162        4985 :             (*const_cast<T*>(&c_)) = new_c;
   18163        4985 :          }
   18164             : 
   18165      656096 :          inline bool valid() const exprtk_override
   18166             :          {
   18167      656096 :             return branch_.first && branch_.first->valid();
   18168             :          }
   18169             : 
   18170           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   18171             :          {
   18172           0 :             return branch_.first;
   18173             :          }
   18174             : 
   18175         935 :          inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
   18176             :          {
   18177         935 :             branch_.second = false;
   18178         935 :             return branch_.first;
   18179             :          }
   18180             : 
   18181       89268 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18182             :          {
   18183       89268 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18184       89268 :          }
   18185             : 
   18186      296884 :          std::size_t node_depth() const exprtk_override
   18187             :          {
   18188      296884 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18189             :          }
   18190             : 
   18191             :       private:
   18192             : 
   18193             :          cob_node(const cob_node<T,Operation>&) exprtk_delete;
   18194             :          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete;
   18195             : 
   18196             :          const T  c_;
   18197             :          branch_t branch_;
   18198             :       };
   18199             : 
   18200             :       template <typename T, typename Operation>
   18201             :       class boc_node exprtk_final : public boc_base_node<T>
   18202             :       {
   18203             :       public:
   18204             : 
   18205             :          typedef expression_node<T>* expression_ptr;
   18206             :          typedef std::pair<expression_ptr,bool> branch_t;
   18207             :          typedef Operation operation_t;
   18208             : 
   18209             :          // binary node op constant node
   18210      144576 :          explicit boc_node(const expression_ptr branch, const T const_var)
   18211      144576 :          : c_(const_var)
   18212             :          {
   18213      144576 :             construct_branch_pair(branch_, branch);
   18214      144576 :             assert(valid());
   18215      144576 :          }
   18216             : 
   18217      130440 :          inline T value() const exprtk_override
   18218             :          {
   18219      130440 :             return Operation::process(branch_.first->value(),c_);
   18220             :          }
   18221             : 
   18222       57606 :          inline operator_type operation() const exprtk_override
   18223             :          {
   18224       57606 :             return Operation::operation();
   18225             :          }
   18226             : 
   18227       21382 :          inline const T c() const exprtk_override
   18228             :          {
   18229       21382 :             return c_;
   18230             :          }
   18231             : 
   18232       18723 :          inline void set_c(const T new_c) exprtk_override
   18233             :          {
   18234       18723 :             (*const_cast<T*>(&c_)) = new_c;
   18235       18723 :          }
   18236             : 
   18237      634348 :          inline bool valid() const exprtk_override
   18238             :          {
   18239      634348 :             return branch_.first && branch_.first->valid();
   18240             :          }
   18241             : 
   18242           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   18243             :          {
   18244           0 :             return branch_.first;
   18245             :          }
   18246             : 
   18247        2659 :          inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
   18248             :          {
   18249        2659 :             branch_.second = false;
   18250        2659 :             return branch_.first;
   18251             :          }
   18252             : 
   18253      144576 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18254             :          {
   18255      144576 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18256      144576 :          }
   18257             : 
   18258      456534 :          std::size_t node_depth() const exprtk_override
   18259             :          {
   18260      456534 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18261             :          }
   18262             : 
   18263             :       private:
   18264             : 
   18265             :          boc_node(const boc_node<T,Operation>&) exprtk_delete;
   18266             :          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete;
   18267             : 
   18268             :          const T  c_;
   18269             :          branch_t branch_;
   18270             :       };
   18271             : 
   18272             :       #ifndef exprtk_disable_string_capabilities
   18273             :       template <typename T, typename SType0, typename SType1, typename Operation>
   18274             :       class sos_node exprtk_final : public sos_base_node<T>
   18275             :       {
   18276             :       public:
   18277             : 
   18278             :          typedef expression_node<T>* expression_ptr;
   18279             :          typedef Operation operation_t;
   18280             : 
   18281             :          // string op string node
   18282       20042 :          explicit sos_node(SType0 p0, SType1 p1)
   18283       20042 :          : s0_(p0)
   18284       20042 :          , s1_(p1)
   18285       20042 :          {}
   18286             : 
   18287       20041 :          inline T value() const exprtk_override
   18288             :          {
   18289       20041 :             return Operation::process(s0_,s1_);
   18290             :          }
   18291             : 
   18292      221104 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18293             :          {
   18294      221104 :             return Operation::type();
   18295             :          }
   18296             : 
   18297           0 :          inline operator_type operation() const exprtk_override
   18298             :          {
   18299           0 :             return Operation::operation();
   18300             :          }
   18301             : 
   18302             :          inline std::string& s0()
   18303             :          {
   18304             :             return s0_;
   18305             :          }
   18306             : 
   18307             :          inline std::string& s1()
   18308             :          {
   18309             :             return s1_;
   18310             :          }
   18311             : 
   18312             :       protected:
   18313             : 
   18314             :          SType0 s0_;
   18315             :          SType1 s1_;
   18316             : 
   18317             :       private:
   18318             : 
   18319             :          sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
   18320             :          sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
   18321             :       };
   18322             : 
   18323             :       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
   18324             :       class str_xrox_node exprtk_final : public sos_base_node<T>
   18325             :       {
   18326             :       public:
   18327             : 
   18328             :          typedef expression_node<T>* expression_ptr;
   18329             :          typedef Operation operation_t;
   18330             :          typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type;
   18331             : 
   18332             :          // string-range op string node
   18333        3690 :          explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
   18334        3690 :          : s0_ (p0 )
   18335        3690 :          , s1_ (p1 )
   18336        3690 :          , rp0_(rp0)
   18337        3690 :          {}
   18338             : 
   18339        7380 :         ~str_xrox_node()
   18340             :          {
   18341        3690 :             rp0_.free();
   18342        7380 :          }
   18343             : 
   18344        3690 :          inline T value() const exprtk_override
   18345             :          {
   18346        3690 :             std::size_t r0 = 0;
   18347        3690 :             std::size_t r1 = 0;
   18348             : 
   18349        3690 :             if (rp0_(r0, r1, s0_.size()))
   18350        3690 :                return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
   18351             :             else
   18352           0 :                return T(0);
   18353             :          }
   18354             : 
   18355       18450 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18356             :          {
   18357       18450 :             return Operation::type();
   18358             :          }
   18359             : 
   18360           0 :          inline operator_type operation() const exprtk_override
   18361             :          {
   18362           0 :             return Operation::operation();
   18363             :          }
   18364             : 
   18365             :          inline std::string& s0()
   18366             :          {
   18367             :             return s0_;
   18368             :          }
   18369             : 
   18370             :          inline std::string& s1()
   18371             :          {
   18372             :             return s1_;
   18373             :          }
   18374             : 
   18375             :       protected:
   18376             : 
   18377             :          SType0    s0_;
   18378             :          SType1    s1_;
   18379             :          RangePack rp0_;
   18380             : 
   18381             :       private:
   18382             : 
   18383             :          str_xrox_node(const node_type&) exprtk_delete;
   18384             :          node_type& operator=(const node_type&) exprtk_delete;
   18385             :       };
   18386             : 
   18387             :       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
   18388             :       class str_xoxr_node exprtk_final : public sos_base_node<T>
   18389             :       {
   18390             :       public:
   18391             : 
   18392             :          typedef expression_node<T>* expression_ptr;
   18393             :          typedef Operation operation_t;
   18394             :          typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type;
   18395             : 
   18396             :          // string op string range node
   18397        3560 :          explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
   18398        3560 :          : s0_ (p0 )
   18399        3560 :          , s1_ (p1 )
   18400        3560 :          , rp1_(rp1)
   18401        3560 :          {}
   18402             : 
   18403        7120 :         ~str_xoxr_node()
   18404             :          {
   18405        3560 :             rp1_.free();
   18406        7120 :          }
   18407             : 
   18408        3560 :          inline T value() const exprtk_override
   18409             :          {
   18410        3560 :             std::size_t r0 = 0;
   18411        3560 :             std::size_t r1 = 0;
   18412             : 
   18413        3560 :             if (rp1_(r0, r1, s1_.size()))
   18414             :             {
   18415             :                return Operation::process
   18416        3560 :                       (
   18417        3560 :                          s0_,
   18418        3560 :                          s1_.substr(r0, (r1 - r0) + 1)
   18419        3560 :                       );
   18420             :             }
   18421             :             else
   18422           0 :                return T(0);
   18423             :          }
   18424             : 
   18425       17800 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18426             :          {
   18427       17800 :             return Operation::type();
   18428             :          }
   18429             : 
   18430           0 :          inline operator_type operation() const exprtk_override
   18431             :          {
   18432           0 :             return Operation::operation();
   18433             :          }
   18434             : 
   18435             :          inline std::string& s0()
   18436             :          {
   18437             :             return s0_;
   18438             :          }
   18439             : 
   18440             :          inline std::string& s1()
   18441             :          {
   18442             :             return s1_;
   18443             :          }
   18444             : 
   18445             :       protected:
   18446             : 
   18447             :          SType0    s0_;
   18448             :          SType1    s1_;
   18449             :          RangePack rp1_;
   18450             : 
   18451             :       private:
   18452             : 
   18453             :          str_xoxr_node(const node_type&) exprtk_delete;
   18454             :          node_type& operator=(const node_type&) exprtk_delete;
   18455             :       };
   18456             : 
   18457             :       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
   18458             :       class str_xroxr_node exprtk_final : public sos_base_node<T>
   18459             :       {
   18460             :       public:
   18461             : 
   18462             :          typedef expression_node<T>* expression_ptr;
   18463             :          typedef Operation operation_t;
   18464             :          typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type;
   18465             : 
   18466             :          // string-range op string-range node
   18467        3355 :          explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
   18468        3355 :          : s0_ (p0 )
   18469        3355 :          , s1_ (p1 )
   18470        3355 :          , rp0_(rp0)
   18471        3355 :          , rp1_(rp1)
   18472        3355 :          {}
   18473             : 
   18474        6710 :         ~str_xroxr_node()
   18475             :          {
   18476        3355 :             rp0_.free();
   18477        3355 :             rp1_.free();
   18478       10065 :          }
   18479             : 
   18480        3355 :          inline T value() const exprtk_override
   18481             :          {
   18482        3355 :             std::size_t r0_0 = 0;
   18483        3355 :             std::size_t r0_1 = 0;
   18484        3355 :             std::size_t r1_0 = 0;
   18485        3355 :             std::size_t r1_1 = 0;
   18486             : 
   18487        3355 :             if (
   18488        6710 :                  rp0_(r0_0, r1_0, s0_.size()) &&
   18489        6710 :                  rp1_(r0_1, r1_1, s1_.size())
   18490             :                )
   18491             :             {
   18492             :                return Operation::process
   18493        6710 :                       (
   18494        3355 :                          s0_.substr(r0_0, (r1_0 - r0_0) + 1),
   18495        3355 :                          s1_.substr(r0_1, (r1_1 - r0_1) + 1)
   18496        3355 :                       );
   18497             :             }
   18498             :             else
   18499           0 :                return T(0);
   18500             :          }
   18501             : 
   18502       16775 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18503             :          {
   18504       16775 :             return Operation::type();
   18505             :          }
   18506             : 
   18507           0 :          inline operator_type operation() const exprtk_override
   18508             :          {
   18509           0 :             return Operation::operation();
   18510             :          }
   18511             : 
   18512             :          inline std::string& s0()
   18513             :          {
   18514             :             return s0_;
   18515             :          }
   18516             : 
   18517             :          inline std::string& s1()
   18518             :          {
   18519             :             return s1_;
   18520             :          }
   18521             : 
   18522             :       protected:
   18523             : 
   18524             :          SType0    s0_;
   18525             :          SType1    s1_;
   18526             :          RangePack rp0_;
   18527             :          RangePack rp1_;
   18528             : 
   18529             :       private:
   18530             : 
   18531             :          str_xroxr_node(const node_type&) exprtk_delete;
   18532             :          node_type& operator=(const node_type&) exprtk_delete;
   18533             :       };
   18534             : 
   18535             :       template <typename T, typename Operation>
   18536             :       class str_sogens_node exprtk_final : public binary_node<T>
   18537             :       {
   18538             :       public:
   18539             : 
   18540             :          typedef expression_node <T>* expression_ptr;
   18541             :          typedef string_base_node<T>* str_base_ptr;
   18542             :          typedef range_pack      <T>  range_t;
   18543             :          typedef range_t*             range_ptr;
   18544             :          typedef range_interface <T>  irange_t;
   18545             :          typedef irange_t*            irange_ptr;
   18546             : 
   18547             :          using binary_node<T>::branch;
   18548             : 
   18549        4846 :          str_sogens_node(const operator_type& opr,
   18550             :                          expression_ptr branch0,
   18551             :                          expression_ptr branch1)
   18552             :          : binary_node<T>(opr, branch0, branch1)
   18553        4846 :          , str0_base_ptr_ (0)
   18554        4846 :          , str1_base_ptr_ (0)
   18555        4846 :          , str0_range_ptr_(0)
   18556        4846 :          , str1_range_ptr_(0)
   18557        4846 :          , initialised_   (false)
   18558             :          {
   18559        4846 :             if (is_generally_string_node(branch(0)))
   18560             :             {
   18561        4846 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   18562             : 
   18563        4846 :                if (0 == str0_base_ptr_)
   18564           0 :                   return;
   18565             : 
   18566        4846 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
   18567             : 
   18568        4846 :                if (0 == range)
   18569           0 :                   return;
   18570             : 
   18571        4846 :                str0_range_ptr_ = &(range->range_ref());
   18572             :             }
   18573             : 
   18574        4846 :             if (is_generally_string_node(branch(1)))
   18575             :             {
   18576        4846 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   18577             : 
   18578        4846 :                if (0 == str1_base_ptr_)
   18579           0 :                   return;
   18580             : 
   18581        4846 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   18582             : 
   18583        4846 :                if (0 == range)
   18584           0 :                   return;
   18585             : 
   18586        4846 :                str1_range_ptr_ = &(range->range_ref());
   18587             :             }
   18588             : 
   18589        4846 :             initialised_ =
   18590        9692 :                str0_base_ptr_  &&
   18591        4846 :                str1_base_ptr_  &&
   18592       14538 :                str0_range_ptr_ &&
   18593        4846 :                str1_range_ptr_;
   18594             : 
   18595        4846 :             assert(valid());
   18596           0 :          }
   18597             : 
   18598        4846 :          inline T value() const exprtk_override
   18599             :          {
   18600        4846 :             branch(0)->value();
   18601        4846 :             branch(1)->value();
   18602             : 
   18603        4846 :             std::size_t str0_r0 = 0;
   18604        4846 :             std::size_t str0_r1 = 0;
   18605             : 
   18606        4846 :             std::size_t str1_r0 = 0;
   18607        4846 :             std::size_t str1_r1 = 0;
   18608             : 
   18609        4846 :             const range_t& range0 = (*str0_range_ptr_);
   18610        4846 :             const range_t& range1 = (*str1_range_ptr_);
   18611             : 
   18612        4846 :             if (
   18613        9692 :                  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
   18614        9692 :                  range1(str1_r0, str1_r1, str1_base_ptr_->size())
   18615             :                )
   18616             :             {
   18617             :                return Operation::process
   18618       14538 :                       (
   18619        4846 :                          str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)),
   18620        4846 :                          str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0))
   18621        4846 :                       );
   18622             :             }
   18623             : 
   18624           0 :             return std::numeric_limits<T>::quiet_NaN();
   18625             :          }
   18626             : 
   18627       24830 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18628             :          {
   18629       24830 :             return Operation::type();
   18630             :          }
   18631             : 
   18632        7392 :          inline bool valid() const exprtk_override
   18633             :          {
   18634        7392 :             return initialised_;
   18635             :          }
   18636             : 
   18637             :       private:
   18638             : 
   18639             :          str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete;
   18640             :          str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete;
   18641             : 
   18642             :          str_base_ptr str0_base_ptr_;
   18643             :          str_base_ptr str1_base_ptr_;
   18644             :          range_ptr    str0_range_ptr_;
   18645             :          range_ptr    str1_range_ptr_;
   18646             :          bool         initialised_;
   18647             :       };
   18648             : 
   18649             :       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
   18650             :       class sosos_node exprtk_final : public sosos_base_node<T>
   18651             :       {
   18652             :       public:
   18653             : 
   18654             :          typedef expression_node<T>* expression_ptr;
   18655             :          typedef Operation operation_t;
   18656             :          typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type;
   18657             : 
   18658             :          // string op string op string node
   18659         300 :          explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
   18660         300 :          : s0_(p0)
   18661         300 :          , s1_(p1)
   18662         300 :          , s2_(p2)
   18663         300 :          {}
   18664             : 
   18665         300 :          inline T value() const exprtk_override
   18666             :          {
   18667         300 :             return Operation::process(s0_, s1_, s2_);
   18668             :          }
   18669             : 
   18670        1500 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18671             :          {
   18672        1500 :             return Operation::type();
   18673             :          }
   18674             : 
   18675           0 :          inline operator_type operation() const exprtk_override
   18676             :          {
   18677           0 :             return Operation::operation();
   18678             :          }
   18679             : 
   18680             :          inline std::string& s0()
   18681             :          {
   18682             :             return s0_;
   18683             :          }
   18684             : 
   18685             :          inline std::string& s1()
   18686             :          {
   18687             :             return s1_;
   18688             :          }
   18689             : 
   18690             :          inline std::string& s2()
   18691             :          {
   18692             :             return s2_;
   18693             :          }
   18694             : 
   18695             :       protected:
   18696             : 
   18697             :          SType0 s0_;
   18698             :          SType1 s1_;
   18699             :          SType2 s2_;
   18700             : 
   18701             :       private:
   18702             : 
   18703             :          sosos_node(const node_type&) exprtk_delete;
   18704             :          node_type& operator=(const node_type&) exprtk_delete;
   18705             :       };
   18706             :       #endif
   18707             : 
   18708             :       template <typename T, typename PowOp>
   18709             :       class ipow_node exprtk_final: public expression_node<T>
   18710             :       {
   18711             :       public:
   18712             : 
   18713             :          typedef expression_node<T>* expression_ptr;
   18714             :          typedef PowOp operation_t;
   18715             : 
   18716       59062 :          explicit ipow_node(const T& v)
   18717       59062 :          : v_(v)
   18718       59062 :          {}
   18719             : 
   18720       59062 :          inline T value() const exprtk_override
   18721             :          {
   18722       59062 :             return PowOp::result(v_);
   18723             :          }
   18724             : 
   18725     1665218 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18726             :          {
   18727     1665218 :             return expression_node<T>::e_ipow;
   18728             :          }
   18729             : 
   18730             :       private:
   18731             : 
   18732             :          ipow_node(const ipow_node<T,PowOp>&) exprtk_delete;
   18733             :          ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete;
   18734             : 
   18735             :          const T& v_;
   18736             :       };
   18737             : 
   18738             :       template <typename T, typename PowOp>
   18739             :       class bipow_node exprtk_final : public expression_node<T>
   18740             :       {
   18741             :       public:
   18742             : 
   18743             :          typedef expression_node<T>* expression_ptr;
   18744             :          typedef std::pair<expression_ptr, bool> branch_t;
   18745             :          typedef PowOp operation_t;
   18746             : 
   18747           1 :          explicit bipow_node(expression_ptr branch)
   18748           1 :          {
   18749           1 :             construct_branch_pair(branch_, branch);
   18750           1 :             assert(valid());
   18751           1 :          }
   18752             : 
   18753           1 :          inline T value() const exprtk_override
   18754             :          {
   18755           1 :             return PowOp::result(branch_.first->value());
   18756             :          }
   18757             : 
   18758          13 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18759             :          {
   18760          13 :             return expression_node<T>::e_ipow;
   18761             :          }
   18762             : 
   18763           3 :          inline bool valid() const exprtk_override
   18764             :          {
   18765           3 :             return branch_.first && branch_.first->valid();
   18766             :          }
   18767             : 
   18768           1 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18769             :          {
   18770           1 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18771           1 :          }
   18772             : 
   18773           3 :          std::size_t node_depth() const exprtk_override
   18774             :          {
   18775           3 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18776             :          }
   18777             : 
   18778             :       private:
   18779             : 
   18780             :          bipow_node(const bipow_node<T,PowOp>&) exprtk_delete;
   18781             :          bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete;
   18782             : 
   18783             :          branch_t branch_;
   18784             :       };
   18785             : 
   18786             :       template <typename T, typename PowOp>
   18787             :       class ipowinv_node exprtk_final : public expression_node<T>
   18788             :       {
   18789             :       public:
   18790             : 
   18791             :          typedef expression_node<T>* expression_ptr;
   18792             :          typedef PowOp operation_t;
   18793             : 
   18794        3050 :          explicit ipowinv_node(const T& v)
   18795        3050 :          : v_(v)
   18796        3050 :          {}
   18797             : 
   18798        3050 :          inline T value() const exprtk_override
   18799             :          {
   18800        3050 :             return (T(1) / PowOp::result(v_));
   18801             :          }
   18802             : 
   18803       39700 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18804             :          {
   18805       39700 :             return expression_node<T>::e_ipowinv;
   18806             :          }
   18807             : 
   18808             :       private:
   18809             : 
   18810             :          ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete;
   18811             :          ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete;
   18812             : 
   18813             :          const T& v_;
   18814             :       };
   18815             : 
   18816             :       template <typename T, typename PowOp>
   18817             :       class bipowinv_node exprtk_final : public expression_node<T>
   18818             :       {
   18819             :       public:
   18820             : 
   18821             :          typedef expression_node<T>* expression_ptr;
   18822             :          typedef std::pair<expression_ptr, bool> branch_t;
   18823             :          typedef PowOp operation_t;
   18824             : 
   18825           0 :          explicit bipowinv_node(expression_ptr branch)
   18826           0 :          {
   18827           0 :             construct_branch_pair(branch_, branch);
   18828           0 :             assert(valid());
   18829           0 :          }
   18830             : 
   18831           0 :          inline T value() const exprtk_override
   18832             :          {
   18833           0 :             return (T(1) / PowOp::result(branch_.first->value()));
   18834             :          }
   18835             : 
   18836           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18837             :          {
   18838           0 :             return expression_node<T>::e_ipowinv;
   18839             :          }
   18840             : 
   18841           0 :          inline bool valid() const exprtk_override
   18842             :          {
   18843           0 :             return branch_.first && branch_.first->valid();
   18844             :          }
   18845             : 
   18846           0 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18847             :          {
   18848           0 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18849           0 :          }
   18850             : 
   18851           0 :          std::size_t node_depth() const exprtk_override
   18852             :          {
   18853           0 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18854             :          }
   18855             : 
   18856             :       private:
   18857             : 
   18858             :          bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete;
   18859             :          bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete;
   18860             : 
   18861             :          branch_t branch_;
   18862             :       };
   18863             : 
   18864             :       template <typename T>
   18865     2067140 :       inline bool is_vov_node(const expression_node<T>* node)
   18866             :       {
   18867     2067140 :          return (0 != dynamic_cast<const vov_base_node<T>*>(node));
   18868             :       }
   18869             : 
   18870             :       template <typename T>
   18871     1811130 :       inline bool is_cov_node(const expression_node<T>* node)
   18872             :       {
   18873     1811130 :          return (0 != dynamic_cast<const cov_base_node<T>*>(node));
   18874             :       }
   18875             : 
   18876             :       template <typename T>
   18877     1575481 :       inline bool is_voc_node(const expression_node<T>* node)
   18878             :       {
   18879     1575481 :          return (0 != dynamic_cast<const voc_base_node<T>*>(node));
   18880             :       }
   18881             : 
   18882             :       template <typename T>
   18883      708392 :       inline bool is_cob_node(const expression_node<T>* node)
   18884             :       {
   18885      708392 :          return (0 != dynamic_cast<const cob_base_node<T>*>(node));
   18886             :       }
   18887             : 
   18888             :       template <typename T>
   18889      764293 :       inline bool is_boc_node(const expression_node<T>* node)
   18890             :       {
   18891      764293 :          return (0 != dynamic_cast<const boc_base_node<T>*>(node));
   18892             :       }
   18893             : 
   18894             :       template <typename T>
   18895     1380548 :       inline bool is_t0ot1ot2_node(const expression_node<T>* node)
   18896             :       {
   18897     1380548 :          return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
   18898             :       }
   18899             : 
   18900             :       template <typename T>
   18901     1034311 :       inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
   18902             :       {
   18903     1034311 :          return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
   18904             :       }
   18905             : 
   18906             :       template <typename T>
   18907     1625928 :       inline bool is_uv_node(const expression_node<T>* node)
   18908             :       {
   18909     1625928 :          return (0 != dynamic_cast<const uv_base_node<T>*>(node));
   18910             :       }
   18911             : 
   18912             :       template <typename T>
   18913     7675757 :       inline bool is_string_node(const expression_node<T>* node)
   18914             :       {
   18915     7675757 :          return node && (expression_node<T>::e_stringvar == node->type());
   18916             :       }
   18917             : 
   18918             :       template <typename T>
   18919     1482567 :       inline bool is_string_range_node(const expression_node<T>* node)
   18920             :       {
   18921     1482567 :          return node && (expression_node<T>::e_stringvarrng == node->type());
   18922             :       }
   18923             : 
   18924             :       template <typename T>
   18925     1472591 :       inline bool is_const_string_node(const expression_node<T>* node)
   18926             :       {
   18927     1472591 :          return node && (expression_node<T>::e_stringconst == node->type());
   18928             :       }
   18929             : 
   18930             :       template <typename T>
   18931     1471446 :       inline bool is_const_string_range_node(const expression_node<T>* node)
   18932             :       {
   18933     1471446 :          return node && (expression_node<T>::e_cstringvarrng == node->type());
   18934             :       }
   18935             : 
   18936             :       template <typename T>
   18937       90644 :       inline bool is_string_assignment_node(const expression_node<T>* node)
   18938             :       {
   18939       90644 :          return node && (expression_node<T>::e_strass == node->type());
   18940             :       }
   18941             : 
   18942             :       template <typename T>
   18943       89044 :       inline bool is_string_concat_node(const expression_node<T>* node)
   18944             :       {
   18945       89044 :          return node && (expression_node<T>::e_strconcat == node->type());
   18946             :       }
   18947             : 
   18948             :       template <typename T>
   18949       86388 :       inline bool is_string_function_node(const expression_node<T>* node)
   18950             :       {
   18951       86388 :          return node && (expression_node<T>::e_strfunction == node->type());
   18952             :       }
   18953             : 
   18954             :       template <typename T>
   18955       86358 :       inline bool is_string_condition_node(const expression_node<T>* node)
   18956             :       {
   18957       86358 :          return node && (expression_node<T>::e_strcondition == node->type());
   18958             :       }
   18959             : 
   18960             :       template <typename T>
   18961       85252 :       inline bool is_string_ccondition_node(const expression_node<T>* node)
   18962             :       {
   18963       85252 :          return node && (expression_node<T>::e_strccondition == node->type());
   18964             :       }
   18965             : 
   18966             :       template <typename T>
   18967       85252 :       inline bool is_string_vararg_node(const expression_node<T>* node)
   18968             :       {
   18969       85252 :          return node && (expression_node<T>::e_stringvararg == node->type());
   18970             :       }
   18971             : 
   18972             :       template <typename T>
   18973       90344 :       inline bool is_genricstring_range_node(const expression_node<T>* node)
   18974             :       {
   18975       90344 :          return node && (expression_node<T>::e_strgenrange == node->type());
   18976             :       }
   18977             : 
   18978             :       template <typename T>
   18979    27749271 :       inline bool is_generally_string_node(const expression_node<T>* node)
   18980             :       {
   18981    27749271 :          if (node)
   18982             :          {
   18983    27747819 :             switch (node->type())
   18984             :             {
   18985      566229 :                case expression_node<T>::e_stringvar     :
   18986             :                case expression_node<T>::e_stringconst   :
   18987             :                case expression_node<T>::e_stringvarrng  :
   18988             :                case expression_node<T>::e_cstringvarrng :
   18989             :                case expression_node<T>::e_strgenrange   :
   18990             :                case expression_node<T>::e_strass        :
   18991             :                case expression_node<T>::e_strconcat     :
   18992             :                case expression_node<T>::e_strfunction   :
   18993             :                case expression_node<T>::e_strcondition  :
   18994             :                case expression_node<T>::e_strccondition :
   18995      566229 :                case expression_node<T>::e_stringvararg  : return true;
   18996    27181590 :                default                                  : return false;
   18997             :             }
   18998             :          }
   18999             : 
   19000        1452 :          return false;
   19001             :       }
   19002             : 
   19003             :       class node_allocator
   19004             :       {
   19005             :       public:
   19006             : 
   19007             :          template <typename ResultNode, typename OpType, typename ExprNode>
   19008      100770 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
   19009             :          {
   19010             :             expression_node<typename ResultNode::value_type>* result =
   19011      100770 :                allocate<ResultNode>(operation, branch[0]);
   19012      100770 :             result->node_depth();
   19013      100770 :             return result;
   19014             :          }
   19015             : 
   19016             :          template <typename ResultNode, typename OpType, typename ExprNode>
   19017      521344 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
   19018             :          {
   19019             :             expression_node<typename ResultNode::value_type>* result =
   19020      521344 :                allocate<ResultNode>(operation, branch[0], branch[1]);
   19021      521344 :             result->node_depth();
   19022      521344 :             return result;
   19023             :          }
   19024             : 
   19025             :          template <typename ResultNode, typename OpType, typename ExprNode>
   19026         836 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
   19027             :          {
   19028             :             expression_node<typename ResultNode::value_type>* result =
   19029         836 :                allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
   19030         836 :             result->node_depth();
   19031         836 :             return result;
   19032             :          }
   19033             : 
   19034             :          template <typename ResultNode, typename OpType, typename ExprNode>
   19035         815 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
   19036             :          {
   19037             :             expression_node<typename ResultNode::value_type>* result =
   19038         815 :                allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
   19039         815 :             result->node_depth();
   19040         815 :             return result;
   19041             :          }
   19042             : 
   19043             :          template <typename ResultNode, typename OpType, typename ExprNode>
   19044             :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
   19045             :          {
   19046             :             expression_node<typename ResultNode::value_type>* result =
   19047             :                allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
   19048             :             result->node_depth();
   19049             :             return result;
   19050             :          }
   19051             : 
   19052             :          template <typename ResultNode, typename OpType, typename ExprNode>
   19053             :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
   19054             :          {
   19055             :             expression_node<typename ResultNode::value_type>* result =
   19056             :                allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
   19057             :             result->node_depth();
   19058             :             return result;
   19059             :          }
   19060             : 
   19061             :          template <typename node_type>
   19062         795 :          inline expression_node<typename node_type::value_type>* allocate() const
   19063             :          {
   19064         795 :             return (new node_type());
   19065             :          }
   19066             : 
   19067             :          template <typename node_type,
   19068             :                    typename Type,
   19069             :                    typename Allocator,
   19070             :                    template <typename, typename> class Sequence>
   19071       52875 :          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
   19072             :          {
   19073             :             expression_node<typename node_type::value_type>*
   19074       52875 :             result = (new node_type(seq));
   19075       52875 :             result->node_depth();
   19076       52875 :             return result;
   19077             :          }
   19078             : 
   19079             :          template <typename node_type, typename T1>
   19080     2524608 :          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
   19081             :          {
   19082             :             expression_node<typename node_type::value_type>*
   19083     2524608 :             result = (new node_type(t1));
   19084     2524608 :             result->node_depth();
   19085     2524608 :             return result;
   19086             :          }
   19087             : 
   19088             :          template <typename node_type, typename T1>
   19089        5643 :          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
   19090             :          {
   19091             :             expression_node<typename node_type::value_type>*
   19092        5643 :             result = (new node_type(t1));
   19093        5643 :             result->node_depth();
   19094        5643 :             return result;
   19095             :          }
   19096             : 
   19097             :          template <typename node_type,
   19098             :                    typename T1, typename T2>
   19099      514916 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
   19100             :          {
   19101             :             expression_node<typename node_type::value_type>*
   19102      514916 :             result = (new node_type(t1, t2));
   19103      514916 :             result->node_depth();
   19104      514916 :             return result;
   19105             :          }
   19106             : 
   19107             :          template <typename node_type,
   19108             :                    typename T1, typename T2>
   19109      739000 :          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
   19110             :          {
   19111             :             expression_node<typename node_type::value_type>*
   19112      739000 :             result = (new node_type(t1, t2));
   19113      739000 :             result->node_depth();
   19114      739000 :             return result;
   19115             :          }
   19116             : 
   19117             :          template <typename node_type,
   19118             :                    typename T1, typename T2>
   19119      322750 :          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
   19120             :          {
   19121             :             expression_node<typename node_type::value_type>*
   19122      322750 :             result = (new node_type(t1, t2));
   19123      322750 :             result->node_depth();
   19124      322750 :             return result;
   19125             :          }
   19126             : 
   19127             :          template <typename node_type,
   19128             :                    typename T1, typename T2>
   19129      288264 :          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
   19130             :          {
   19131             :             expression_node<typename node_type::value_type>*
   19132      288264 :             result = (new node_type(t1, t2));
   19133      288264 :             result->node_depth();
   19134      288264 :             return result;
   19135             :          }
   19136             : 
   19137             :          template <typename node_type,
   19138             :                    typename T1, typename T2>
   19139      121349 :          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
   19140             :          {
   19141             :             expression_node<typename node_type::value_type>*
   19142      121349 :             result = (new node_type(t1, t2));
   19143      121349 :             result->node_depth();
   19144      121349 :             return result;
   19145             :          }
   19146             : 
   19147             :          template <typename node_type,
   19148             :                    typename T1, typename T2, typename T3>
   19149       12096 :          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
   19150             :          {
   19151             :             expression_node<typename node_type::value_type>*
   19152       12096 :             result = (new node_type(t1, t2, t3));
   19153       12096 :             result->node_depth();
   19154       12096 :             return result;
   19155             :          }
   19156             : 
   19157             :          template <typename node_type,
   19158             :                    typename T1, typename T2, typename T3, typename T4>
   19159        3355 :          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
   19160             :          {
   19161             :             expression_node<typename node_type::value_type>*
   19162        3355 :             result = (new node_type(t1, t2, t3, t4));
   19163        3355 :             result->node_depth();
   19164        3355 :             return result;
   19165             :          }
   19166             : 
   19167             :          template <typename node_type,
   19168             :                    typename T1, typename T2, typename T3>
   19169       29201 :          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
   19170             :          {
   19171             :             expression_node<typename node_type::value_type>*
   19172       29201 :             result = (new node_type(t1, t2, t3));
   19173       29201 :             result->node_depth();
   19174       29201 :             return result;
   19175             :          }
   19176             : 
   19177             :          template <typename node_type,
   19178             :                    typename T1, typename T2, typename T3, typename T4>
   19179        1594 :          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
   19180             :          {
   19181             :             expression_node<typename node_type::value_type>*
   19182        1594 :             result = (new node_type(t1, t2, t3, t4));
   19183        1594 :             result->node_depth();
   19184        1594 :             return result;
   19185             :          }
   19186             : 
   19187             :          template <typename node_type,
   19188             :                    typename T1, typename T2, typename T3, typename T4, typename T5>
   19189         620 :          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
   19190             :          {
   19191             :             expression_node<typename node_type::value_type>*
   19192         620 :             result = (new node_type(t1, t2, t3, t4, t5));
   19193         620 :             result->node_depth();
   19194         620 :             return result;
   19195             :          }
   19196             : 
   19197             :          template <typename node_type,
   19198             :                    typename T1, typename T2, typename T3>
   19199      543888 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19200             :                                                                           const T3& t3) const
   19201             :          {
   19202             :             expression_node<typename node_type::value_type>*
   19203      543888 :             result = (new node_type(t1, t2, t3));
   19204      543888 :             result->node_depth();
   19205      543888 :             return result;
   19206             :          }
   19207             : 
   19208             :          template <typename node_type,
   19209             :                    typename T1, typename T2,
   19210             :                    typename T3, typename T4>
   19211       20267 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19212             :                                                                           const T3& t3, const T4& t4) const
   19213             :          {
   19214             :             expression_node<typename node_type::value_type>*
   19215       20267 :             result = (new node_type(t1, t2, t3, t4));
   19216       20267 :             result->node_depth();
   19217       20267 :             return result;
   19218             :          }
   19219             : 
   19220             :          template <typename node_type,
   19221             :                    typename T1, typename T2,
   19222             :                    typename T3, typename T4, typename T5>
   19223         815 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19224             :                                                                           const T3& t3, const T4& t4,
   19225             :                                                                           const T5& t5) const
   19226             :          {
   19227             :             expression_node<typename node_type::value_type>*
   19228         815 :             result = (new node_type(t1, t2, t3, t4, t5));
   19229         815 :             result->node_depth();
   19230         815 :             return result;
   19231             :          }
   19232             : 
   19233             :          template <typename node_type,
   19234             :                    typename T1, typename T2,
   19235             :                    typename T3, typename T4, typename T5, typename T6>
   19236             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19237             :                                                                           const T3& t3, const T4& t4,
   19238             :                                                                           const T5& t5, const T6& t6) const
   19239             :          {
   19240             :             expression_node<typename node_type::value_type>*
   19241             :             result = (new node_type(t1, t2, t3, t4, t5, t6));
   19242             :             result->node_depth();
   19243             :             return result;
   19244             :          }
   19245             : 
   19246             :          template <typename node_type,
   19247             :                    typename T1, typename T2,
   19248             :                    typename T3, typename T4,
   19249             :                    typename T5, typename T6, typename T7>
   19250             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19251             :                                                                           const T3& t3, const T4& t4,
   19252             :                                                                           const T5& t5, const T6& t6,
   19253             :                                                                           const T7& t7) const
   19254             :          {
   19255             :             expression_node<typename node_type::value_type>*
   19256             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
   19257             :             result->node_depth();
   19258             :             return result;
   19259             :          }
   19260             : 
   19261             :          template <typename node_type,
   19262             :                    typename T1, typename T2,
   19263             :                    typename T3, typename T4,
   19264             :                    typename T5, typename T6,
   19265             :                    typename T7, typename T8>
   19266             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19267             :                                                                           const T3& t3, const T4& t4,
   19268             :                                                                           const T5& t5, const T6& t6,
   19269             :                                                                           const T7& t7, const T8& t8) const
   19270             :          {
   19271             :             expression_node<typename node_type::value_type>*
   19272             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
   19273             :             result->node_depth();
   19274             :             return result;
   19275             :          }
   19276             : 
   19277             :          template <typename node_type,
   19278             :                    typename T1, typename T2,
   19279             :                    typename T3, typename T4,
   19280             :                    typename T5, typename T6,
   19281             :                    typename T7, typename T8, typename T9>
   19282             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   19283             :                                                                           const T3& t3, const T4& t4,
   19284             :                                                                           const T5& t5, const T6& t6,
   19285             :                                                                           const T7& t7, const T8& t8,
   19286             :                                                                           const T9& t9) const
   19287             :          {
   19288             :             expression_node<typename node_type::value_type>*
   19289             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
   19290             :             result->node_depth();
   19291             :             return result;
   19292             :          }
   19293             : 
   19294             :          template <typename node_type,
   19295             :                    typename T1, typename T2,
   19296             :                    typename T3, typename T4,
   19297             :                    typename T5, typename T6,
   19298             :                    typename T7, typename T8,
   19299             :                    typename T9, typename T10>
   19300             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
   19301             :                                                                           const T3& t3, const  T4&  t4,
   19302             :                                                                           const T5& t5, const  T6&  t6,
   19303             :                                                                           const T7& t7, const  T8&  t8,
   19304             :                                                                           const T9& t9, const T10& t10) const
   19305             :          {
   19306             :             expression_node<typename node_type::value_type>*
   19307             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
   19308             :             result->node_depth();
   19309             :             return result;
   19310             :          }
   19311             : 
   19312             :          template <typename node_type,
   19313             :                    typename T1, typename T2, typename T3>
   19314      371380 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
   19315             :          {
   19316             :             expression_node<typename node_type::value_type>*
   19317      371380 :             result = (new node_type(t1, t2, t3));
   19318      371380 :             result->node_depth();
   19319      371380 :             return result;
   19320             :          }
   19321             : 
   19322             :          template <typename node_type,
   19323             :                    typename T1, typename T2,
   19324             :                    typename T3, typename T4>
   19325       97884 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   19326             :                                                                                T3 t3, T4 t4) const
   19327             :          {
   19328             :             expression_node<typename node_type::value_type>*
   19329       97884 :             result = (new node_type(t1, t2, t3, t4));
   19330       97884 :             result->node_depth();
   19331       97884 :             return result;
   19332             :          }
   19333             : 
   19334             :          template <typename node_type,
   19335             :                    typename T1, typename T2,
   19336             :                    typename T3, typename T4,
   19337             :                    typename T5>
   19338        5960 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   19339             :                                                                                T3 t3, T4 t4,
   19340             :                                                                                T5 t5) const
   19341             :          {
   19342             :             expression_node<typename node_type::value_type>*
   19343        5960 :             result = (new node_type(t1, t2, t3, t4, t5));
   19344        5960 :             result->node_depth();
   19345        5960 :             return result;
   19346             :          }
   19347             : 
   19348             :          template <typename node_type,
   19349             :                    typename T1, typename T2,
   19350             :                    typename T3, typename T4,
   19351             :                    typename T5, typename T6>
   19352             :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   19353             :                                                                                T3 t3, T4 t4,
   19354             :                                                                                T5 t5, T6 t6) const
   19355             :          {
   19356             :             expression_node<typename node_type::value_type>*
   19357             :             result = (new node_type(t1, t2, t3, t4, t5, t6));
   19358             :             result->node_depth();
   19359             :             return result;
   19360             :          }
   19361             : 
   19362             :          template <typename node_type,
   19363             :                    typename T1, typename T2,
   19364             :                    typename T3, typename T4,
   19365             :                    typename T5, typename T6, typename T7>
   19366        6917 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   19367             :                                                                                T3 t3, T4 t4,
   19368             :                                                                                T5 t5, T6 t6,
   19369             :                                                                                T7 t7) const
   19370             :          {
   19371             :             expression_node<typename node_type::value_type>*
   19372        6917 :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
   19373        6917 :             result->node_depth();
   19374        6917 :             return result;
   19375             :          }
   19376             : 
   19377             :          template <typename T>
   19378           1 :          void inline free(expression_node<T>*& e) const
   19379             :          {
   19380             :             exprtk_debug(("node_allocator::free() - deleting expression_node "
   19381             :                           "type: %03d addr: %p\n",
   19382             :                           static_cast<int>(e->type()),
   19383             :                           reinterpret_cast<void*>(e)));
   19384           1 :             delete e;
   19385           1 :             e = 0;
   19386           1 :          }
   19387             :       };
   19388             : 
   19389      108660 :       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
   19390             :       {
   19391             :          #define register_op(Symbol, Type, Args)                                             \
   19392             :          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
   19393             : 
   19394      217320 :          register_op("abs"       , e_abs     , 1)
   19395      217320 :          register_op("acos"      , e_acos    , 1)
   19396      217320 :          register_op("acosh"     , e_acosh   , 1)
   19397      217320 :          register_op("asin"      , e_asin    , 1)
   19398      217320 :          register_op("asinh"     , e_asinh   , 1)
   19399      217320 :          register_op("atan"      , e_atan    , 1)
   19400      217320 :          register_op("atanh"     , e_atanh   , 1)
   19401      217320 :          register_op("ceil"      , e_ceil    , 1)
   19402      217320 :          register_op("cos"       , e_cos     , 1)
   19403      217320 :          register_op("cosh"      , e_cosh    , 1)
   19404      217320 :          register_op("exp"       , e_exp     , 1)
   19405      217320 :          register_op("expm1"     , e_expm1   , 1)
   19406      217320 :          register_op("floor"     , e_floor   , 1)
   19407      217320 :          register_op("log"       , e_log     , 1)
   19408      217320 :          register_op("log10"     , e_log10   , 1)
   19409      217320 :          register_op("log2"      , e_log2    , 1)
   19410      217320 :          register_op("log1p"     , e_log1p   , 1)
   19411      217320 :          register_op("round"     , e_round   , 1)
   19412      217320 :          register_op("sin"       , e_sin     , 1)
   19413      217320 :          register_op("sinc"      , e_sinc    , 1)
   19414      217320 :          register_op("sinh"      , e_sinh    , 1)
   19415      217320 :          register_op("sec"       , e_sec     , 1)
   19416      217320 :          register_op("csc"       , e_csc     , 1)
   19417      217320 :          register_op("sqrt"      , e_sqrt    , 1)
   19418      217320 :          register_op("tan"       , e_tan     , 1)
   19419      217320 :          register_op("tanh"      , e_tanh    , 1)
   19420      217320 :          register_op("cot"       , e_cot     , 1)
   19421      217320 :          register_op("rad2deg"   , e_r2d     , 1)
   19422      217320 :          register_op("deg2rad"   , e_d2r     , 1)
   19423      217320 :          register_op("deg2grad"  , e_d2g     , 1)
   19424      217320 :          register_op("grad2deg"  , e_g2d     , 1)
   19425      217320 :          register_op("sgn"       , e_sgn     , 1)
   19426      217320 :          register_op("not"       , e_notl    , 1)
   19427      217320 :          register_op("erf"       , e_erf     , 1)
   19428      217320 :          register_op("erfc"      , e_erfc    , 1)
   19429      217320 :          register_op("ncdf"      , e_ncdf    , 1)
   19430      217320 :          register_op("frac"      , e_frac    , 1)
   19431      217320 :          register_op("trunc"     , e_trunc   , 1)
   19432      217320 :          register_op("atan2"     , e_atan2   , 2)
   19433      217320 :          register_op("mod"       , e_mod     , 2)
   19434      217320 :          register_op("logn"      , e_logn    , 2)
   19435      217320 :          register_op("pow"       , e_pow     , 2)
   19436      217320 :          register_op("root"      , e_root    , 2)
   19437      217320 :          register_op("roundn"    , e_roundn  , 2)
   19438      217320 :          register_op("equal"     , e_equal   , 2)
   19439      217320 :          register_op("not_equal" , e_nequal  , 2)
   19440      217320 :          register_op("hypot"     , e_hypot   , 2)
   19441      217320 :          register_op("shr"       , e_shr     , 2)
   19442      217320 :          register_op("shl"       , e_shl     , 2)
   19443      217320 :          register_op("clamp"     , e_clamp   , 3)
   19444      217320 :          register_op("iclamp"    , e_iclamp  , 3)
   19445      217320 :          register_op("inrange"   , e_inrange , 3)
   19446             :          #undef register_op
   19447      108660 :       }
   19448             : 
   19449             :    } // namespace details
   19450             : 
   19451             :    class function_traits
   19452             :    {
   19453             :    public:
   19454             : 
   19455      132070 :       function_traits()
   19456      132070 :       : allow_zero_parameters_(false)
   19457      132070 :       , has_side_effects_(true)
   19458      132070 :       , min_num_args_(0)
   19459      132070 :       , max_num_args_(std::numeric_limits<std::size_t>::max())
   19460      132070 :       {}
   19461             : 
   19462          79 :       inline bool& allow_zero_parameters()
   19463             :       {
   19464          79 :          return allow_zero_parameters_;
   19465             :       }
   19466             : 
   19467      135153 :       inline bool& has_side_effects()
   19468             :       {
   19469      135153 :          return has_side_effects_;
   19470             :       }
   19471             : 
   19472         115 :       std::size_t& min_num_args()
   19473             :       {
   19474         115 :          return min_num_args_;
   19475             :       }
   19476             : 
   19477          51 :       std::size_t& max_num_args()
   19478             :       {
   19479          51 :          return max_num_args_;
   19480             :       }
   19481             : 
   19482             :    private:
   19483             : 
   19484             :       bool allow_zero_parameters_;
   19485             :       bool has_side_effects_;
   19486             :       std::size_t min_num_args_;
   19487             :       std::size_t max_num_args_;
   19488             :    };
   19489             : 
   19490             :    template <typename FunctionType>
   19491          62 :    void enable_zero_parameters(FunctionType& func)
   19492             :    {
   19493          62 :       func.allow_zero_parameters() = true;
   19494             : 
   19495          62 :       if (0 != func.min_num_args())
   19496             :       {
   19497           0 :          func.min_num_args() = 0;
   19498             :       }
   19499          62 :    }
   19500             : 
   19501             :    template <typename FunctionType>
   19502             :    void disable_zero_parameters(FunctionType& func)
   19503             :    {
   19504             :       func.allow_zero_parameters() = false;
   19505             :    }
   19506             : 
   19507             :    template <typename FunctionType>
   19508             :    void enable_has_side_effects(FunctionType& func)
   19509             :    {
   19510             :       func.has_side_effects() = true;
   19511             :    }
   19512             : 
   19513             :    template <typename FunctionType>
   19514      128736 :    void disable_has_side_effects(FunctionType& func)
   19515             :    {
   19516      128736 :       func.has_side_effects() = false;
   19517      128736 :    }
   19518             : 
   19519             :    template <typename FunctionType>
   19520           2 :    void set_min_num_args(FunctionType& func, const std::size_t& num_args)
   19521             :    {
   19522           2 :       func.min_num_args() = num_args;
   19523             : 
   19524           2 :       if ((0 != func.min_num_args()) && func.allow_zero_parameters())
   19525           0 :          func.allow_zero_parameters() = false;
   19526           2 :    }
   19527             : 
   19528             :    template <typename FunctionType>
   19529           2 :    void set_max_num_args(FunctionType& func, const std::size_t& num_args)
   19530             :    {
   19531           2 :       func.max_num_args() = num_args;
   19532           2 :    }
   19533             : 
   19534             :    template <typename T>
   19535             :    class ifunction : public function_traits
   19536             :    {
   19537             :    public:
   19538             : 
   19539      131097 :       explicit ifunction(const std::size_t& pc)
   19540      131097 :       : param_count(pc)
   19541      131097 :       {}
   19542             : 
   19543      131097 :       virtual ~ifunction()
   19544      131097 :       {}
   19545             : 
   19546             :       #define empty_method_body(N)                   \
   19547             :       {                                              \
   19548             :          exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \
   19549             :          return std::numeric_limits<T>::quiet_NaN(); \
   19550             :       }                                              \
   19551             : 
   19552           0 :       inline virtual T operator() ()
   19553           0 :       empty_method_body(0)
   19554             : 
   19555           0 :       inline virtual T operator() (const T&)
   19556           0 :       empty_method_body(1)
   19557             : 
   19558           0 :       inline virtual T operator() (const T&,const T&)
   19559           0 :       empty_method_body(2)
   19560             : 
   19561           0 :       inline virtual T operator() (const T&, const T&, const T&)
   19562           0 :       empty_method_body(3)
   19563             : 
   19564           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&)
   19565           0 :       empty_method_body(4)
   19566             : 
   19567           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
   19568           0 :       empty_method_body(5)
   19569             : 
   19570           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
   19571           0 :       empty_method_body(6)
   19572             : 
   19573           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19574           0 :       empty_method_body(7)
   19575             : 
   19576           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19577           0 :       empty_method_body(8)
   19578             : 
   19579           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19580           0 :       empty_method_body(9)
   19581             : 
   19582           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19583           0 :       empty_method_body(10)
   19584             : 
   19585           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19586             :                                    const T&)
   19587           0 :       empty_method_body(11)
   19588             : 
   19589           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19590             :                                    const T&, const T&)
   19591           0 :       empty_method_body(12)
   19592             : 
   19593           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19594             :                                    const T&, const T&, const T&)
   19595           0 :       empty_method_body(13)
   19596             : 
   19597           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19598             :                                    const T&, const T&, const T&, const T&)
   19599           0 :       empty_method_body(14)
   19600             : 
   19601           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19602             :                                    const T&, const T&, const T&, const T&, const T&)
   19603           0 :       empty_method_body(15)
   19604             : 
   19605           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19606             :                                    const T&, const T&, const T&, const T&, const T&, const T&)
   19607           0 :       empty_method_body(16)
   19608             : 
   19609           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19610             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19611           0 :       empty_method_body(17)
   19612             : 
   19613           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19614             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19615           0 :       empty_method_body(18)
   19616             : 
   19617           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19618             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19619           0 :       empty_method_body(19)
   19620             : 
   19621           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
   19622             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   19623           0 :       empty_method_body(20)
   19624             : 
   19625             :       #undef empty_method_body
   19626             : 
   19627             :       std::size_t param_count;
   19628             :    };
   19629             : 
   19630             :    template <typename T>
   19631             :    class ivararg_function : public function_traits
   19632             :    {
   19633             :    public:
   19634             : 
   19635           2 :       virtual ~ivararg_function()
   19636           2 :       {}
   19637             : 
   19638           0 :       inline virtual T operator() (const std::vector<T>&)
   19639             :       {
   19640             :          exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n"));
   19641           0 :          return std::numeric_limits<T>::quiet_NaN();
   19642             :       }
   19643             :    };
   19644             : 
   19645             :    template <typename T>
   19646             :    class igeneric_function : public function_traits
   19647             :    {
   19648             :    public:
   19649             : 
   19650             :       enum return_type
   19651             :       {
   19652             :          e_rtrn_scalar   = 0,
   19653             :          e_rtrn_string   = 1,
   19654             :          e_rtrn_overload = 2
   19655             :       };
   19656             : 
   19657             :       typedef T type;
   19658             :       typedef type_store<T> generic_type;
   19659             :       typedef typename generic_type::parameter_list parameter_list_t;
   19660             : 
   19661         971 :       explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
   19662         971 :       : parameter_sequence(param_seq)
   19663         971 :       , rtrn_type(rtr_type)
   19664         971 :       {}
   19665             : 
   19666         971 :       virtual ~igeneric_function()
   19667         971 :       {}
   19668             : 
   19669             :       #define igeneric_function_empty_body(N)        \
   19670             :       {                                              \
   19671             :          exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \
   19672             :          return std::numeric_limits<T>::quiet_NaN(); \
   19673             :       }                                              \
   19674             : 
   19675             :       // f(i_0,i_1,....,i_N) --> Scalar
   19676           0 :       inline virtual T operator() (parameter_list_t)
   19677           0 :       igeneric_function_empty_body(1)
   19678             : 
   19679             :       // f(i_0,i_1,....,i_N) --> String
   19680           0 :       inline virtual T operator() (std::string&, parameter_list_t)
   19681           0 :       igeneric_function_empty_body(2)
   19682             : 
   19683             :       // f(psi,i_0,i_1,....,i_N) --> Scalar
   19684           0 :       inline virtual T operator() (const std::size_t&, parameter_list_t)
   19685           0 :       igeneric_function_empty_body(3)
   19686             : 
   19687             :       // f(psi,i_0,i_1,....,i_N) --> String
   19688           0 :       inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
   19689           0 :       igeneric_function_empty_body(4)
   19690             : 
   19691             :       #undef igeneric_function_empty_body
   19692             : 
   19693             :       std::string parameter_sequence;
   19694             :       return_type rtrn_type;
   19695             :    };
   19696             : 
   19697             :    #ifndef exprtk_disable_string_capabilities
   19698             :    template <typename T>
   19699             :    class stringvar_base
   19700             :    {
   19701             :    public:
   19702             : 
   19703             :       typedef typename details::stringvar_node<T> stringvar_node_t;
   19704             : 
   19705             :       stringvar_base(const std::string& name, stringvar_node_t* svn)
   19706             :       : name_(name)
   19707             :       , string_varnode_(svn)
   19708             :       {}
   19709             : 
   19710             :       bool valid() const
   19711             :       {
   19712             :          return !name_.empty() && (0 != string_varnode_);
   19713             :       }
   19714             : 
   19715             :       std::string name() const
   19716             :       {
   19717             :          assert(string_varnode_);
   19718             :          return name_;
   19719             :       }
   19720             : 
   19721             :       void rebase(std::string& s)
   19722             :       {
   19723             :          assert(string_varnode_);
   19724             :          string_varnode_->rebase(s);
   19725             :       }
   19726             : 
   19727             :    private:
   19728             : 
   19729             :       std::string name_;
   19730             :       stringvar_node_t* string_varnode_;
   19731             :    };
   19732             :    #endif
   19733             : 
   19734             :    template <typename T> class parser;
   19735             :    template <typename T> class expression_helper;
   19736             : 
   19737             :    template <typename T>
   19738             :    class symbol_table
   19739             :    {
   19740             :    public:
   19741             : 
   19742             :      enum symtab_mutability_type
   19743             :      {
   19744             :        e_unknown   = 0,
   19745             :        e_mutable   = 1,
   19746             :        e_immutable = 2
   19747             :      };
   19748             : 
   19749             :      typedef T (*ff00_functor)();
   19750             :      typedef T (*ff01_functor)(T);
   19751             :      typedef T (*ff02_functor)(T, T);
   19752             :      typedef T (*ff03_functor)(T, T, T);
   19753             :      typedef T (*ff04_functor)(T, T, T, T);
   19754             :      typedef T (*ff05_functor)(T, T, T, T, T);
   19755             :      typedef T (*ff06_functor)(T, T, T, T, T, T);
   19756             :      typedef T (*ff07_functor)(T, T, T, T, T, T, T);
   19757             :      typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
   19758             :      typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
   19759             :      typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
   19760             :      typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
   19761             :      typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
   19762             :      typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
   19763             :      typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
   19764             :      typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
   19765             : 
   19766             :    protected:
   19767             : 
   19768             :        struct freefunc00 exprtk_final : public exprtk::ifunction<T>
   19769             :        {
   19770             :           using exprtk::ifunction<T>::operator();
   19771             : 
   19772             :           explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
   19773             :           inline T operator() () exprtk_override
   19774             :           { return f(); }
   19775             :           ff00_functor f;
   19776             :        };
   19777             : 
   19778             :       struct freefunc01 exprtk_final : public exprtk::ifunction<T>
   19779             :       {
   19780             :          using exprtk::ifunction<T>::operator();
   19781             : 
   19782         102 :          explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
   19783           0 :          inline T operator() (const T& v0) exprtk_override
   19784           0 :          { return f(v0); }
   19785             :          ff01_functor f;
   19786             :       };
   19787             : 
   19788             :       struct freefunc02 exprtk_final : public exprtk::ifunction<T>
   19789             :       {
   19790             :          using exprtk::ifunction<T>::operator();
   19791             : 
   19792         102 :          explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
   19793           0 :          inline T operator() (const T& v0, const T& v1) exprtk_override
   19794           0 :          { return f(v0, v1); }
   19795             :          ff02_functor f;
   19796             :       };
   19797             : 
   19798             :       struct freefunc03 exprtk_final : public exprtk::ifunction<T>
   19799             :       {
   19800             :          using exprtk::ifunction<T>::operator();
   19801             : 
   19802         102 :          explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
   19803           0 :          inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override
   19804           0 :          { return f(v0, v1, v2); }
   19805             :          ff03_functor f;
   19806             :       };
   19807             : 
   19808             :       struct freefunc04 exprtk_final : public exprtk::ifunction<T>
   19809             :       {
   19810             :          using exprtk::ifunction<T>::operator();
   19811             : 
   19812         102 :          explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
   19813           0 :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override
   19814           0 :          { return f(v0, v1, v2, v3); }
   19815             :          ff04_functor f;
   19816             :       };
   19817             : 
   19818             :       struct freefunc05 : public exprtk::ifunction<T>
   19819             :       {
   19820             :          using exprtk::ifunction<T>::operator();
   19821             : 
   19822         102 :          explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
   19823           0 :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override
   19824           0 :          { return f(v0, v1, v2, v3, v4); }
   19825             :          ff05_functor f;
   19826             :       };
   19827             : 
   19828             :       struct freefunc06 exprtk_final : public exprtk::ifunction<T>
   19829             :       {
   19830             :          using exprtk::ifunction<T>::operator();
   19831             : 
   19832         102 :          explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
   19833           0 :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override
   19834           0 :          { return f(v0, v1, v2, v3, v4, v5); }
   19835             :          ff06_functor f;
   19836             :       };
   19837             : 
   19838             :       struct freefunc07 exprtk_final : public exprtk::ifunction<T>
   19839             :       {
   19840             :          using exprtk::ifunction<T>::operator();
   19841             : 
   19842             :          explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
   19843             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19844             :                               const T& v5, const T& v6) exprtk_override
   19845             :          { return f(v0, v1, v2, v3, v4, v5, v6); }
   19846             :          ff07_functor f;
   19847             :       };
   19848             : 
   19849             :       struct freefunc08 exprtk_final : public exprtk::ifunction<T>
   19850             :       {
   19851             :          using exprtk::ifunction<T>::operator();
   19852             : 
   19853             :          explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
   19854             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19855             :                               const T& v5, const T& v6, const T& v7) exprtk_override
   19856             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
   19857             :          ff08_functor f;
   19858             :       };
   19859             : 
   19860             :       struct freefunc09 exprtk_final : public exprtk::ifunction<T>
   19861             :       {
   19862             :          using exprtk::ifunction<T>::operator();
   19863             : 
   19864             :          explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
   19865             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19866             :                               const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override
   19867             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
   19868             :          ff09_functor f;
   19869             :       };
   19870             : 
   19871             :       struct freefunc10 exprtk_final : public exprtk::ifunction<T>
   19872             :       {
   19873             :          using exprtk::ifunction<T>::operator();
   19874             : 
   19875             :          explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
   19876             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19877             :                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override
   19878             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
   19879             :          ff10_functor f;
   19880             :       };
   19881             : 
   19882             :       struct freefunc11 exprtk_final : public exprtk::ifunction<T>
   19883             :       {
   19884             :          using exprtk::ifunction<T>::operator();
   19885             : 
   19886             :          explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
   19887             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19888             :                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override
   19889             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
   19890             :          ff11_functor f;
   19891             :       };
   19892             : 
   19893             :       struct freefunc12 exprtk_final : public exprtk::ifunction<T>
   19894             :       {
   19895             :          using exprtk::ifunction<T>::operator();
   19896             : 
   19897             :          explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
   19898             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19899             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19900             :                               const T& v10, const T& v11) exprtk_override
   19901             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
   19902             :          ff12_functor f;
   19903             :       };
   19904             : 
   19905             :       struct freefunc13 exprtk_final : public exprtk::ifunction<T>
   19906             :       {
   19907             :          using exprtk::ifunction<T>::operator();
   19908             : 
   19909             :          explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
   19910             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19911             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19912             :                               const T& v10, const T& v11, const T& v12) exprtk_override
   19913             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
   19914             :          ff13_functor f;
   19915             :       };
   19916             : 
   19917             :       struct freefunc14 exprtk_final : public exprtk::ifunction<T>
   19918             :       {
   19919             :          using exprtk::ifunction<T>::operator();
   19920             : 
   19921             :          explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
   19922             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19923             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19924             :                               const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override
   19925             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
   19926             :          ff14_functor f;
   19927             :       };
   19928             : 
   19929             :       struct freefunc15 exprtk_final : public exprtk::ifunction<T>
   19930             :       {
   19931             :          using exprtk::ifunction<T>::operator();
   19932             : 
   19933             :          explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
   19934             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19935             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19936             :                               const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override
   19937             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
   19938             :          ff15_functor f;
   19939             :       };
   19940             : 
   19941             :       template <typename Type, typename RawType>
   19942             :       struct type_store
   19943             :       {
   19944             :          typedef details::expression_node<T>*        expression_ptr;
   19945             :          typedef typename details::variable_node<T>  variable_node_t;
   19946             :          typedef ifunction<T>                        ifunction_t;
   19947             :          typedef ivararg_function<T>                 ivararg_function_t;
   19948             :          typedef igeneric_function<T>                igeneric_function_t;
   19949             :          typedef details::vector_holder<T>           vector_t;
   19950             :          #ifndef exprtk_disable_string_capabilities
   19951             :          typedef typename details::stringvar_node<T> stringvar_node_t;
   19952             :          #endif
   19953             : 
   19954             :          typedef Type type_t;
   19955             :          typedef type_t* type_ptr;
   19956             :          typedef std::pair<bool,type_ptr> type_pair_t;
   19957             :          typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
   19958             :          typedef typename type_map_t::iterator tm_itr_t;
   19959             :          typedef typename type_map_t::const_iterator tm_const_itr_t;
   19960             : 
   19961             :          enum { lut_size = 256 };
   19962             : 
   19963             :          type_map_t  map;
   19964             :          std::size_t size;
   19965             : 
   19966      669048 :          type_store()
   19967      669048 :          : size(0)
   19968      669048 :          {}
   19969             : 
   19970             :          struct deleter
   19971             :          {
   19972             :             #define exprtk_define_process(Type)                  \
   19973             :             static inline void process(std::pair<bool,Type*>& n) \
   19974             :             {                                                    \
   19975             :                delete n.second;                                  \
   19976             :             }                                                    \
   19977             : 
   19978      443835 :             exprtk_define_process(variable_node_t )
   19979        6422 :             exprtk_define_process(vector_t        )
   19980             :             #ifndef exprtk_disable_string_capabilities
   19981      122310 :             exprtk_define_process(stringvar_node_t)
   19982             :             #endif
   19983             : 
   19984             :             #undef exprtk_define_process
   19985             : 
   19986             :             template <typename DeleteType>
   19987      143012 :             static inline void process(std::pair<bool,DeleteType*>&)
   19988      143012 :             {}
   19989             :          };
   19990             : 
   19991     3963156 :          inline bool symbol_exists(const std::string& symbol_name) const
   19992             :          {
   19993     3963156 :             if (symbol_name.empty())
   19994           0 :                return false;
   19995     3963156 :             else if (map.end() != map.find(symbol_name))
   19996      205027 :                return true;
   19997             :             else
   19998     3758129 :                return false;
   19999             :          }
   20000             : 
   20001             :          template <typename PtrType>
   20002           4 :          inline std::string entity_name(const PtrType& ptr) const
   20003             :          {
   20004           4 :             if (map.empty())
   20005           0 :                return std::string();
   20006             : 
   20007           4 :             tm_const_itr_t itr = map.begin();
   20008             : 
   20009           7 :             while (map.end() != itr)
   20010             :             {
   20011           7 :                if (itr->second.second == ptr)
   20012             :                {
   20013           4 :                   return itr->first;
   20014             :                }
   20015             :                else
   20016           3 :                   ++itr;
   20017             :             }
   20018             : 
   20019           0 :             return std::string();
   20020             :          }
   20021             : 
   20022     1956071 :          inline bool is_constant(const std::string& symbol_name) const
   20023             :          {
   20024     1956071 :             if (symbol_name.empty())
   20025           0 :                return false;
   20026             :             else
   20027             :             {
   20028     1956071 :                const tm_const_itr_t itr = map.find(symbol_name);
   20029             : 
   20030     1956071 :                if (map.end() == itr)
   20031      102929 :                   return false;
   20032             :                else
   20033     1853142 :                   return (*itr).second.first;
   20034             :             }
   20035             :          }
   20036             : 
   20037             :          template <typename Tie, typename RType>
   20038        6422 :          inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
   20039             :          {
   20040        6422 :             if (symbol_name.size() > 1)
   20041             :             {
   20042      208800 :                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
   20043             :                {
   20044      206480 :                   if (details::imatch(symbol_name, details::reserved_symbols[i]))
   20045             :                   {
   20046           0 :                      return false;
   20047             :                   }
   20048             :                }
   20049             :             }
   20050             : 
   20051        6422 :             const tm_itr_t itr = map.find(symbol_name);
   20052             : 
   20053        6422 :             if (map.end() == itr)
   20054             :             {
   20055        6422 :                map[symbol_name] = Tie::make(t,is_const);
   20056        6422 :                ++size;
   20057             :             }
   20058             : 
   20059        6422 :             return true;
   20060             :          }
   20061             : 
   20062             :          struct tie_array
   20063             :          {
   20064        2143 :             static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
   20065             :             {
   20066        2143 :                return std::make_pair(is_const, new vector_t(v.first, v.second));
   20067             :             }
   20068             :          };
   20069             : 
   20070             :          struct tie_stdvec
   20071             :          {
   20072             :             template <typename Allocator>
   20073          84 :             static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
   20074             :             {
   20075          84 :                return std::make_pair(is_const, new vector_t(v));
   20076             :             }
   20077             :          };
   20078             : 
   20079             :          struct tie_vecview
   20080             :          {
   20081        4195 :             static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
   20082             :             {
   20083        4195 :                return std::make_pair(is_const, new vector_t(v));
   20084             :             }
   20085             :          };
   20086             : 
   20087             :          struct tie_stddeq
   20088             :          {
   20089             :             template <typename Allocator>
   20090             :             static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
   20091             :             {
   20092             :                return std::make_pair(is_const, new vector_t(v));
   20093             :             }
   20094             :          };
   20095             : 
   20096             :          template <std::size_t v_size>
   20097        2143 :          inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
   20098             :          {
   20099             :             return add_impl<tie_array,std::pair<T*,std::size_t> >
   20100        2143 :                       (symbol_name, std::make_pair(v,v_size), is_const);
   20101             :          }
   20102             : 
   20103           0 :          inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
   20104             :          {
   20105             :             return add_impl<tie_array,std::pair<T*,std::size_t> >
   20106           0 :                      (symbol_name, std::make_pair(v,v_size), is_const);
   20107             :          }
   20108             : 
   20109             :          template <typename Allocator>
   20110          84 :          inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
   20111             :          {
   20112             :             return add_impl<tie_stdvec,std::vector<T,Allocator>&>
   20113          84 :                       (symbol_name, v, is_const);
   20114             :          }
   20115             : 
   20116        4195 :          inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
   20117             :          {
   20118             :             return add_impl<tie_vecview,exprtk::vector_view<T>&>
   20119        4195 :                       (symbol_name, v, is_const);
   20120             :          }
   20121             : 
   20122             :          template <typename Allocator>
   20123             :          inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
   20124             :          {
   20125             :             return add_impl<tie_stddeq,std::deque<T,Allocator>&>
   20126             :                       (symbol_name, v, is_const);
   20127             :          }
   20128             : 
   20129      710193 :          inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false)
   20130             :          {
   20131             :             struct tie
   20132             :             {
   20133      443835 :                static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false)
   20134             :                {
   20135      443835 :                   return std::make_pair(is_constant, new variable_node_t(t));
   20136             :                }
   20137             : 
   20138             :                #ifndef exprtk_disable_string_capabilities
   20139      122310 :                static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false)
   20140             :                {
   20141      122310 :                   return std::make_pair(is_constant, new stringvar_node_t(t));
   20142             :                }
   20143             :                #endif
   20144             : 
   20145      143011 :                static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
   20146             :                {
   20147      143011 :                   return std::make_pair(is_constant,&t);
   20148             :                }
   20149             : 
   20150           2 :                static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
   20151             :                {
   20152           2 :                   return std::make_pair(is_constant,&t);
   20153             :                }
   20154             : 
   20155        1035 :                static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
   20156             :                {
   20157        1035 :                   return std::make_pair(is_constant,&t);
   20158             :                }
   20159             :             };
   20160             : 
   20161      710193 :             const tm_itr_t itr = map.find(symbol_name);
   20162             : 
   20163      710193 :             if (map.end() == itr)
   20164             :             {
   20165      710193 :                map[symbol_name] = tie::make(t_,is_const);
   20166      710193 :                ++size;
   20167             :             }
   20168             : 
   20169      710193 :             return true;
   20170             :          }
   20171             : 
   20172    14450580 :          inline type_ptr get(const std::string& symbol_name) const
   20173             :          {
   20174    14450580 :             const tm_const_itr_t itr = map.find(symbol_name);
   20175             : 
   20176    14450580 :             if (map.end() == itr)
   20177      524036 :                return reinterpret_cast<type_ptr>(0);
   20178             :             else
   20179    13926544 :                return itr->second.second;
   20180             :          }
   20181             : 
   20182             :          template <typename TType, typename TRawType, typename PtrType>
   20183             :          struct ptr_match
   20184             :          {
   20185             :             static inline bool test(const PtrType, const void*)
   20186             :             {
   20187             :                return false;
   20188             :             }
   20189             :          };
   20190             : 
   20191             :          template <typename TType, typename TRawType>
   20192             :          struct ptr_match<TType,TRawType,variable_node_t*>
   20193             :          {
   20194         960 :             static inline bool test(const variable_node_t* p, const void* ptr)
   20195             :             {
   20196             :                exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr));
   20197         960 :                return (&(p->ref()) == ptr);
   20198             :             }
   20199             :          };
   20200             : 
   20201         320 :          inline type_ptr get_from_varptr(const void* ptr) const
   20202             :          {
   20203         320 :             tm_const_itr_t itr = map.begin();
   20204             : 
   20205        1280 :             while (map.end() != itr)
   20206             :             {
   20207         960 :                type_ptr ret_ptr = itr->second.second;
   20208             : 
   20209         960 :                if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
   20210             :                {
   20211           0 :                   return ret_ptr;
   20212             :                }
   20213             : 
   20214         960 :                ++itr;
   20215             :             }
   20216             : 
   20217         320 :             return type_ptr(0);
   20218             :          }
   20219             : 
   20220         422 :          inline bool remove(const std::string& symbol_name, const bool delete_node = true)
   20221             :          {
   20222         422 :             const tm_itr_t itr = map.find(symbol_name);
   20223             : 
   20224         422 :             if (map.end() != itr)
   20225             :             {
   20226         411 :                if (delete_node)
   20227             :                {
   20228         411 :                   deleter::process((*itr).second);
   20229             :                }
   20230             : 
   20231         411 :                map.erase(itr);
   20232         411 :                --size;
   20233             : 
   20234         411 :                return true;
   20235             :             }
   20236             :             else
   20237          11 :                return false;
   20238             :          }
   20239             : 
   20240             :          inline RawType& type_ref(const std::string& symbol_name)
   20241             :          {
   20242             :             struct init_type
   20243             :             {
   20244             :                static inline double set(double)           { return (0.0);           }
   20245             :                static inline double set(long double)      { return (0.0);           }
   20246             :                static inline float  set(float)            { return (0.0f);          }
   20247             :                static inline std::string set(std::string) { return std::string(""); }
   20248             :             };
   20249             : 
   20250             :             static RawType null_type = init_type::set(RawType());
   20251             : 
   20252             :             const tm_const_itr_t itr = map.find(symbol_name);
   20253             : 
   20254             :             if (map.end() == itr)
   20255             :                return null_type;
   20256             :             else
   20257             :                return itr->second.second->ref();
   20258             :          }
   20259             : 
   20260      749468 :          inline void clear(const bool delete_node = true)
   20261             :          {
   20262      749468 :             if (!map.empty())
   20263             :             {
   20264      171891 :                if (delete_node)
   20265             :                {
   20266      171891 :                   tm_itr_t itr = map.begin();
   20267      171891 :                   tm_itr_t end = map.end  ();
   20268             : 
   20269      887059 :                   while (end != itr)
   20270             :                   {
   20271      715168 :                      deleter::process((*itr).second);
   20272      715168 :                      ++itr;
   20273             :                   }
   20274             :                }
   20275             : 
   20276      171891 :                map.clear();
   20277             :             }
   20278             : 
   20279      749468 :             size = 0;
   20280      749468 :          }
   20281             : 
   20282             :          template <typename Allocator,
   20283             :                    template <typename, typename> class Sequence>
   20284          20 :          inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
   20285             :          {
   20286          20 :             std::size_t count = 0;
   20287             : 
   20288          20 :             if (!map.empty())
   20289             :             {
   20290          20 :                tm_const_itr_t itr = map.begin();
   20291          20 :                tm_const_itr_t end = map.end  ();
   20292             : 
   20293         100 :                while (end != itr)
   20294             :                {
   20295          80 :                   list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
   20296          80 :                   ++itr;
   20297          80 :                   ++count;
   20298             :                }
   20299             :             }
   20300             : 
   20301          20 :             return count;
   20302             :          }
   20303             : 
   20304             :          template <typename Allocator,
   20305             :                    template <typename, typename> class Sequence>
   20306        3655 :          inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
   20307             :          {
   20308        3655 :             std::size_t count = 0;
   20309             : 
   20310        3655 :             if (!map.empty())
   20311             :             {
   20312         641 :                tm_const_itr_t itr = map.begin();
   20313         641 :                tm_const_itr_t end = map.end  ();
   20314             : 
   20315        2899 :                while (end != itr)
   20316             :                {
   20317        2258 :                   vlist.push_back((*itr).first);
   20318        2258 :                   ++itr;
   20319        2258 :                   ++count;
   20320             :                }
   20321             :             }
   20322             : 
   20323        3655 :             return count;
   20324             :          }
   20325             :       };
   20326             : 
   20327             :       typedef details::expression_node<T>*        expression_ptr;
   20328             :       typedef typename details::variable_node<T>  variable_t;
   20329             :       typedef typename details::vector_holder<T>  vector_holder_t;
   20330             :       typedef variable_t*                         variable_ptr;
   20331             :       #ifndef exprtk_disable_string_capabilities
   20332             :       typedef typename details::stringvar_node<T> stringvar_t;
   20333             :       typedef stringvar_t*                        stringvar_ptr;
   20334             :       #endif
   20335             :       typedef ifunction        <T>                function_t;
   20336             :       typedef ivararg_function <T>                vararg_function_t;
   20337             :       typedef igeneric_function<T>                generic_function_t;
   20338             :       typedef function_t*                         function_ptr;
   20339             :       typedef vararg_function_t*                  vararg_function_ptr;
   20340             :       typedef generic_function_t*                 generic_function_ptr;
   20341             : 
   20342             :       static const std::size_t lut_size = 256;
   20343             : 
   20344             :       // Symbol Table Holder
   20345             :       struct control_block
   20346             :       {
   20347             :          struct st_data
   20348             :          {
   20349             :             type_store<variable_t        , T                 > variable_store;
   20350             :             type_store<function_t        , function_t        > function_store;
   20351             :             type_store<vararg_function_t , vararg_function_t > vararg_function_store;
   20352             :             type_store<generic_function_t, generic_function_t> generic_function_store;
   20353             :             type_store<generic_function_t, generic_function_t> string_function_store;
   20354             :             type_store<generic_function_t, generic_function_t> overload_function_store;
   20355             :             type_store<vector_holder_t   , vector_holder_t   > vector_store;
   20356             :             #ifndef exprtk_disable_string_capabilities
   20357             :             type_store<stringvar_t       , std::string       > stringvar_store;
   20358             :             #endif
   20359             : 
   20360       83631 :             st_data()
   20361       83631 :             {
   20362     2843454 :                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
   20363             :                {
   20364     2759823 :                   reserved_symbol_table_.insert(details::reserved_words[i]);
   20365             :                }
   20366             : 
   20367     7526790 :                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
   20368             :                {
   20369     7443159 :                   reserved_symbol_table_.insert(details::reserved_symbols[i]);
   20370             :                }
   20371       83631 :             }
   20372             : 
   20373       83631 :            ~st_data()
   20374             :             {
   20375       84243 :                for (std::size_t i = 0; i < free_function_list_.size(); ++i)
   20376             :                {
   20377         612 :                   delete free_function_list_[i];
   20378             :                }
   20379       83631 :             }
   20380             : 
   20381    17696825 :             inline bool is_reserved_symbol(const std::string& symbol) const
   20382             :             {
   20383    17696825 :                return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
   20384             :             }
   20385             : 
   20386       83631 :             static inline st_data* create()
   20387             :             {
   20388       83631 :                return (new st_data);
   20389             :             }
   20390             : 
   20391       83631 :             static inline void destroy(st_data*& sd)
   20392             :             {
   20393       83631 :                delete sd;
   20394       83631 :                sd = reinterpret_cast<st_data*>(0);
   20395       83631 :             }
   20396             : 
   20397             :             std::list<T>               local_symbol_list_;
   20398             :             std::list<std::string>     local_stringvar_list_;
   20399             :             std::set<std::string>      reserved_symbol_table_;
   20400             :             std::vector<ifunction<T>*> free_function_list_;
   20401             :          };
   20402             : 
   20403       83631 :          control_block()
   20404       83631 :          : ref_count(1)
   20405       83631 :          , data_(st_data::create())
   20406       83631 :          , mutability_(e_mutable)
   20407       83631 :          {}
   20408             : 
   20409             :          explicit control_block(st_data* data)
   20410             :          : ref_count(1)
   20411             :          , data_(data)
   20412             :          , mutability_(e_mutable)
   20413             :          {}
   20414             : 
   20415       83631 :         ~control_block()
   20416             :          {
   20417       83631 :             if (data_ && (0 == ref_count))
   20418             :             {
   20419       83631 :                st_data::destroy(data_);
   20420             :             }
   20421       83631 :          }
   20422             : 
   20423       83631 :          static inline control_block* create()
   20424             :          {
   20425       83631 :             return (new control_block);
   20426             :          }
   20427             : 
   20428             :          template <typename SymTab>
   20429     1043126 :          static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
   20430             :          {
   20431     1043126 :             if (cntrl_blck)
   20432             :             {
   20433     1043126 :                if (
   20434     2086252 :                     (0 !=   cntrl_blck->ref_count) &&
   20435     1043126 :                     (0 == --cntrl_blck->ref_count)
   20436             :                   )
   20437             :                {
   20438       83631 :                   if (sym_tab)
   20439       83630 :                      sym_tab->clear();
   20440             : 
   20441       83631 :                   delete cntrl_blck;
   20442             :                }
   20443             : 
   20444     1043126 :                cntrl_blck = 0;
   20445             :             }
   20446     1043126 :          }
   20447             : 
   20448       83631 :          void set_mutability(const symtab_mutability_type mutability)
   20449             :          {
   20450       83631 :             mutability_ = mutability;
   20451       83631 :          }
   20452             : 
   20453             :          std::size_t ref_count;
   20454             :          st_data* data_;
   20455             :          symtab_mutability_type mutability_;
   20456             :       };
   20457             : 
   20458             :    public:
   20459             : 
   20460       83631 :       explicit symbol_table(const symtab_mutability_type mutability = e_mutable)
   20461       83631 :       : control_block_(control_block::create())
   20462             :       {
   20463       83631 :          control_block_->set_mutability(mutability);
   20464       83631 :          clear();
   20465       83631 :       }
   20466             : 
   20467     1043122 :      ~symbol_table()
   20468             :       {
   20469     1043122 :          exprtk::details::dump_ptr("~symbol_table", this);
   20470     1043122 :          control_block::destroy(control_block_, this);
   20471     1043122 :       }
   20472             : 
   20473      959491 :       symbol_table(const symbol_table<T>& st)
   20474             :       {
   20475      959491 :          control_block_ = st.control_block_;
   20476      959491 :          control_block_->ref_count++;
   20477      959491 :       }
   20478             : 
   20479           4 :       inline symbol_table<T>& operator=(const symbol_table<T>& st)
   20480             :       {
   20481           4 :          if (this != &st)
   20482             :          {
   20483           4 :             control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
   20484             : 
   20485           4 :             control_block_ = st.control_block_;
   20486           4 :             control_block_->ref_count++;
   20487             :          }
   20488             : 
   20489           4 :          return (*this);
   20490             :       }
   20491             : 
   20492       31545 :       inline bool operator==(const symbol_table<T>& st) const
   20493             :       {
   20494       31545 :          return (this == &st) || (control_block_ == st.control_block_);
   20495             :       }
   20496             : 
   20497     1813759 :       inline symtab_mutability_type mutability() const
   20498             :       {
   20499     1813759 :          return valid() ? control_block_->mutability_ : e_unknown;
   20500             :       }
   20501             : 
   20502      187367 :       inline void clear_variables(const bool delete_node = true)
   20503             :       {
   20504      187367 :          local_data().variable_store.clear(delete_node);
   20505      187367 :       }
   20506             : 
   20507      187367 :       inline void clear_functions()
   20508             :       {
   20509      187367 :          local_data().function_store.clear();
   20510      187367 :       }
   20511             : 
   20512      187367 :       inline void clear_strings()
   20513             :       {
   20514             :          #ifndef exprtk_disable_string_capabilities
   20515      187367 :          local_data().stringvar_store.clear();
   20516             :          #endif
   20517      187367 :       }
   20518             : 
   20519      187367 :       inline void clear_vectors()
   20520             :       {
   20521      187367 :          local_data().vector_store.clear();
   20522      187367 :       }
   20523             : 
   20524      187367 :       inline void clear_local_constants()
   20525             :       {
   20526      187367 :          local_data().local_symbol_list_.clear();
   20527      187367 :       }
   20528             : 
   20529      187367 :       inline void clear()
   20530             :       {
   20531      187367 :          if (!valid()) return;
   20532      187367 :          clear_variables      ();
   20533      187367 :          clear_functions      ();
   20534      187367 :          clear_strings        ();
   20535      187367 :          clear_vectors        ();
   20536      187367 :          clear_local_constants();
   20537             :       }
   20538             : 
   20539         600 :       inline std::size_t variable_count() const
   20540             :       {
   20541         600 :          if (valid())
   20542         600 :             return local_data().variable_store.size;
   20543             :          else
   20544           0 :             return 0;
   20545             :       }
   20546             : 
   20547             :       #ifndef exprtk_disable_string_capabilities
   20548          10 :       inline std::size_t stringvar_count() const
   20549             :       {
   20550          10 :          if (valid())
   20551          10 :             return local_data().stringvar_store.size;
   20552             :          else
   20553           0 :             return 0;
   20554             :       }
   20555             :       #endif
   20556             : 
   20557             :       inline std::size_t function_count() const
   20558             :       {
   20559             :          if (valid())
   20560             :             return local_data().function_store.size;
   20561             :          else
   20562             :             return 0;
   20563             :       }
   20564             : 
   20565             :       inline std::size_t vector_count() const
   20566             :       {
   20567             :          if (valid())
   20568             :             return local_data().vector_store.size;
   20569             :          else
   20570             :             return 0;
   20571             :       }
   20572             : 
   20573    12000045 :       inline variable_ptr get_variable(const std::string& variable_name) const
   20574             :       {
   20575    12000045 :          if (!valid())
   20576           0 :             return reinterpret_cast<variable_ptr>(0);
   20577    12000045 :          else if (!valid_symbol(variable_name))
   20578           0 :             return reinterpret_cast<variable_ptr>(0);
   20579             :          else
   20580    12000045 :             return local_data().variable_store.get(variable_name);
   20581             :       }
   20582             : 
   20583             :       inline variable_ptr get_variable(const T& var_ref) const
   20584             :       {
   20585             :          if (!valid())
   20586             :             return reinterpret_cast<variable_ptr>(0);
   20587             :          else
   20588             :             return local_data().variable_store.get_from_varptr(
   20589             :                                                   reinterpret_cast<const void*>(&var_ref));
   20590             :       }
   20591             : 
   20592             :       #ifndef exprtk_disable_string_capabilities
   20593          44 :       inline stringvar_ptr get_stringvar(const std::string& string_name) const
   20594             :       {
   20595          44 :          if (!valid())
   20596           0 :             return reinterpret_cast<stringvar_ptr>(0);
   20597          44 :          else if (!valid_symbol(string_name))
   20598           0 :             return reinterpret_cast<stringvar_ptr>(0);
   20599             :          else
   20600          44 :             return local_data().stringvar_store.get(string_name);
   20601             :       }
   20602             : 
   20603             :       inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const
   20604             :       {
   20605             :          static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0));
   20606             :          if (!valid())
   20607             :             return null_stringvar_base;
   20608             :          else if (!valid_symbol(string_name))
   20609             :             return null_stringvar_base;
   20610             : 
   20611             :          stringvar_ptr stringvar = local_data().stringvar_store.get(string_name);
   20612             : 
   20613             :          if (0 == stringvar)
   20614             :          {
   20615             :             return null_stringvar_base;
   20616             :          }
   20617             : 
   20618             :          return stringvar_base<T>(string_name,stringvar);
   20619             :       }
   20620             :       #endif
   20621             : 
   20622        2178 :       inline function_ptr get_function(const std::string& function_name) const
   20623             :       {
   20624        2178 :          if (!valid())
   20625           0 :             return reinterpret_cast<function_ptr>(0);
   20626        2178 :          else if (!valid_symbol(function_name))
   20627           0 :             return reinterpret_cast<function_ptr>(0);
   20628             :          else
   20629        2178 :             return local_data().function_store.get(function_name);
   20630             :       }
   20631             : 
   20632           0 :       inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
   20633             :       {
   20634           0 :          if (!valid())
   20635           0 :             return reinterpret_cast<vararg_function_ptr>(0);
   20636           0 :          else if (!valid_symbol(vararg_function_name))
   20637           0 :             return reinterpret_cast<vararg_function_ptr>(0);
   20638             :          else
   20639           0 :             return local_data().vararg_function_store.get(vararg_function_name);
   20640             :       }
   20641             : 
   20642           0 :       inline generic_function_ptr get_generic_function(const std::string& function_name) const
   20643             :       {
   20644           0 :          if (!valid())
   20645           0 :             return reinterpret_cast<generic_function_ptr>(0);
   20646           0 :          else if (!valid_symbol(function_name))
   20647           0 :             return reinterpret_cast<generic_function_ptr>(0);
   20648             :          else
   20649           0 :             return local_data().generic_function_store.get(function_name);
   20650             :       }
   20651             : 
   20652           0 :       inline generic_function_ptr get_string_function(const std::string& function_name) const
   20653             :       {
   20654           0 :          if (!valid())
   20655           0 :             return reinterpret_cast<generic_function_ptr>(0);
   20656           0 :          else if (!valid_symbol(function_name))
   20657           0 :             return reinterpret_cast<generic_function_ptr>(0);
   20658             :          else
   20659           0 :             return local_data().string_function_store.get(function_name);
   20660             :       }
   20661             : 
   20662           0 :       inline generic_function_ptr get_overload_function(const std::string& function_name) const
   20663             :       {
   20664           0 :          if (!valid())
   20665           0 :             return reinterpret_cast<generic_function_ptr>(0);
   20666           0 :          else if (!valid_symbol(function_name))
   20667           0 :             return reinterpret_cast<generic_function_ptr>(0);
   20668             :          else
   20669           0 :             return local_data().overload_function_store.get(function_name);
   20670             :       }
   20671             : 
   20672             :       typedef vector_holder_t* vector_holder_ptr;
   20673             : 
   20674           4 :       inline vector_holder_ptr get_vector(const std::string& vector_name) const
   20675             :       {
   20676           4 :          if (!valid())
   20677           0 :             return reinterpret_cast<vector_holder_ptr>(0);
   20678           4 :          else if (!valid_symbol(vector_name))
   20679           0 :             return reinterpret_cast<vector_holder_ptr>(0);
   20680             :          else
   20681           4 :             return local_data().vector_store.get(vector_name);
   20682             :       }
   20683             : 
   20684             :       inline T& variable_ref(const std::string& symbol_name)
   20685             :       {
   20686             :          static T null_var = T(0);
   20687             :          if (!valid())
   20688             :             return null_var;
   20689             :          else if (!valid_symbol(symbol_name))
   20690             :             return null_var;
   20691             :          else
   20692             :             return local_data().variable_store.type_ref(symbol_name);
   20693             :       }
   20694             : 
   20695             :       #ifndef exprtk_disable_string_capabilities
   20696             :       inline std::string& stringvar_ref(const std::string& symbol_name)
   20697             :       {
   20698             :          static std::string null_stringvar;
   20699             :          if (!valid())
   20700             :             return null_stringvar;
   20701             :          else if (!valid_symbol(symbol_name))
   20702             :             return null_stringvar;
   20703             :          else
   20704             :             return local_data().stringvar_store.type_ref(symbol_name);
   20705             :       }
   20706             :       #endif
   20707             : 
   20708             :       inline bool is_constant_node(const std::string& symbol_name) const
   20709             :       {
   20710             :          if (!valid())
   20711             :             return false;
   20712             :          else if (!valid_symbol(symbol_name))
   20713             :             return false;
   20714             :          else
   20715             :             return local_data().variable_store.is_constant(symbol_name);
   20716             :       }
   20717             : 
   20718             :       #ifndef exprtk_disable_string_capabilities
   20719             :       inline bool is_constant_string(const std::string& symbol_name) const
   20720             :       {
   20721             :          if (!valid())
   20722             :             return false;
   20723             :          else if (!valid_symbol(symbol_name))
   20724             :             return false;
   20725             :          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
   20726             :             return false;
   20727             :          else
   20728             :             return local_data().stringvar_store.is_constant(symbol_name);
   20729             :       }
   20730             :       #endif
   20731             : 
   20732        2302 :       inline bool create_variable(const std::string& variable_name, const T& value = T(0))
   20733             :       {
   20734        2302 :          if (!valid())
   20735           0 :             return false;
   20736        2302 :          else if (!valid_symbol(variable_name))
   20737           0 :             return false;
   20738        2302 :          else if (symbol_exists(variable_name))
   20739           0 :             return false;
   20740             : 
   20741        2302 :          local_data().local_symbol_list_.push_back(value);
   20742        2302 :          T& t = local_data().local_symbol_list_.back();
   20743             : 
   20744        2302 :          return add_variable(variable_name,t);
   20745             :       }
   20746             : 
   20747             :       #ifndef exprtk_disable_string_capabilities
   20748             :       inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
   20749             :       {
   20750             :          if (!valid())
   20751             :             return false;
   20752             :          else if (!valid_symbol(stringvar_name))
   20753             :             return false;
   20754             :          else if (symbol_exists(stringvar_name))
   20755             :             return false;
   20756             : 
   20757             :          local_data().local_stringvar_list_.push_back(value);
   20758             :          std::string& s = local_data().local_stringvar_list_.back();
   20759             : 
   20760             :          return add_stringvar(stringvar_name,s);
   20761             :       }
   20762             :       #endif
   20763             : 
   20764      443911 :       inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
   20765             :       {
   20766      443911 :          if (!valid())
   20767           0 :             return false;
   20768      443911 :          else if (!valid_symbol(variable_name))
   20769           0 :             return false;
   20770      443911 :          else if (symbol_exists(variable_name))
   20771          76 :             return false;
   20772             :          else
   20773      443835 :             return local_data().variable_store.add(variable_name, t, is_constant);
   20774             :       }
   20775             : 
   20776      101541 :       inline bool add_constant(const std::string& constant_name, const T& value)
   20777             :       {
   20778      101541 :          if (!valid())
   20779           0 :             return false;
   20780      101541 :          else if (!valid_symbol(constant_name))
   20781           0 :             return false;
   20782      101541 :          else if (symbol_exists(constant_name))
   20783           0 :             return false;
   20784             : 
   20785      101541 :          local_data().local_symbol_list_.push_back(value);
   20786      101541 :          T& t = local_data().local_symbol_list_.back();
   20787             : 
   20788      101541 :          return add_variable(constant_name, t, true);
   20789             :       }
   20790             : 
   20791             :       #ifndef exprtk_disable_string_capabilities
   20792      122386 :       inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
   20793             :       {
   20794      122386 :          if (!valid())
   20795           0 :             return false;
   20796      122386 :          else if (!valid_symbol(stringvar_name))
   20797           0 :             return false;
   20798      122386 :          else if (symbol_exists(stringvar_name))
   20799          76 :             return false;
   20800             :          else
   20801      122310 :             return local_data().stringvar_store.add(stringvar_name, s, is_constant);
   20802             :       }
   20803             :       #endif
   20804             : 
   20805      143009 :       inline bool add_function(const std::string& function_name, function_t& function)
   20806             :       {
   20807      143009 :          if (!valid())
   20808           0 :             return false;
   20809      143009 :          else if (!valid_symbol(function_name))
   20810           0 :             return false;
   20811      143009 :          else if (symbol_exists(function_name))
   20812           0 :             return false;
   20813             :          else
   20814      143009 :             return local_data().function_store.add(function_name,function);
   20815             :       }
   20816             : 
   20817           2 :       inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
   20818             :       {
   20819           2 :          if (!valid())
   20820           0 :             return false;
   20821           2 :          else if (!valid_symbol(vararg_function_name))
   20822           0 :             return false;
   20823           2 :          else if (symbol_exists(vararg_function_name))
   20824           0 :             return false;
   20825             :          else
   20826           2 :             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
   20827             :       }
   20828             : 
   20829        1035 :       inline bool add_function(const std::string& function_name, generic_function_t& function)
   20830             :       {
   20831        1035 :          if (!valid())
   20832           0 :             return false;
   20833        1035 :          else if (!valid_symbol(function_name))
   20834           0 :             return false;
   20835        1035 :          else if (symbol_exists(function_name))
   20836           0 :             return false;
   20837             :          else
   20838             :          {
   20839        1035 :             switch (function.rtrn_type)
   20840             :             {
   20841        1032 :                case generic_function_t::e_rtrn_scalar :
   20842        2064 :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20843        2064 :                          local_data().generic_function_store.add(function_name,function) : false;
   20844             : 
   20845           1 :                case generic_function_t::e_rtrn_string :
   20846           2 :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20847           2 :                          local_data().string_function_store.add(function_name,function)  : false;
   20848             : 
   20849           2 :                case generic_function_t::e_rtrn_overload :
   20850           4 :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
   20851           4 :                          local_data().overload_function_store.add(function_name,function) : false;
   20852             :             }
   20853             :          }
   20854             : 
   20855           0 :          return false;
   20856             :       }
   20857             : 
   20858             :       #define exprtk_define_freefunction(NN)                                                \
   20859             :       inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
   20860             :       {                                                                                     \
   20861             :          if (!valid())                                                                      \
   20862             :          { return false; }                                                                  \
   20863             :          if (!valid_symbol(function_name))                                                  \
   20864             :          { return false; }                                                                  \
   20865             :          if (symbol_exists(function_name))                                                  \
   20866             :          { return false; }                                                                  \
   20867             :                                                                                             \
   20868             :          exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                          \
   20869             :                                                                                             \
   20870             :          local_data().free_function_list_.push_back(ifunc);                                 \
   20871             :                                                                                             \
   20872             :          return add_function(function_name,(*local_data().free_function_list_.back()));     \
   20873             :       }                                                                                     \
   20874             : 
   20875         102 :       exprtk_define_freefunction(00) exprtk_define_freefunction(01)
   20876         204 :       exprtk_define_freefunction(02) exprtk_define_freefunction(03)
   20877         204 :       exprtk_define_freefunction(04) exprtk_define_freefunction(05)
   20878         102 :       exprtk_define_freefunction(06) exprtk_define_freefunction(07)
   20879             :       exprtk_define_freefunction(08) exprtk_define_freefunction(09)
   20880             :       exprtk_define_freefunction(10) exprtk_define_freefunction(11)
   20881             :       exprtk_define_freefunction(12) exprtk_define_freefunction(13)
   20882             :       exprtk_define_freefunction(14) exprtk_define_freefunction(15)
   20883             : 
   20884             :       #undef exprtk_define_freefunction
   20885             : 
   20886           2 :       inline bool add_reserved_function(const std::string& function_name, function_t& function)
   20887             :       {
   20888           2 :          if (!valid())
   20889           0 :             return false;
   20890           2 :          else if (!valid_symbol(function_name,false))
   20891           0 :             return false;
   20892           2 :          else if (symbol_exists(function_name,false))
   20893           0 :             return false;
   20894             :          else
   20895           2 :             return local_data().function_store.add(function_name,function);
   20896             :       }
   20897             : 
   20898             :       inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
   20899             :       {
   20900             :          if (!valid())
   20901             :             return false;
   20902             :          else if (!valid_symbol(vararg_function_name,false))
   20903             :             return false;
   20904             :          else if (symbol_exists(vararg_function_name,false))
   20905             :             return false;
   20906             :          else
   20907             :             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
   20908             :       }
   20909             : 
   20910             :       inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
   20911             :       {
   20912             :          if (!valid())
   20913             :             return false;
   20914             :          else if (!valid_symbol(function_name,false))
   20915             :             return false;
   20916             :          else if (symbol_exists(function_name,false))
   20917             :             return false;
   20918             :          else
   20919             :          {
   20920             :             switch (function.rtrn_type)
   20921             :             {
   20922             :                case generic_function_t::e_rtrn_scalar :
   20923             :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20924             :                          local_data().generic_function_store.add(function_name,function) : false;
   20925             : 
   20926             :                case generic_function_t::e_rtrn_string :
   20927             :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20928             :                          local_data().string_function_store.add(function_name,function)  : false;
   20929             : 
   20930             :                case generic_function_t::e_rtrn_overload :
   20931             :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
   20932             :                          local_data().overload_function_store.add(function_name,function) : false;
   20933             :             }
   20934             :          }
   20935             : 
   20936             :          return false;
   20937             :       }
   20938             : 
   20939             :       #define exprtk_define_reserved_function(NN)                                                    \
   20940             :       inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \
   20941             :       {                                                                                              \
   20942             :          if (!valid())                                                                               \
   20943             :          { return false; }                                                                           \
   20944             :          if (!valid_symbol(function_name,false))                                                     \
   20945             :          { return false; }                                                                           \
   20946             :          if (symbol_exists(function_name,false))                                                     \
   20947             :          { return false; }                                                                           \
   20948             :                                                                                                      \
   20949             :          exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                                   \
   20950             :                                                                                                      \
   20951             :          local_data().free_function_list_.push_back(ifunc);                                          \
   20952             :                                                                                                      \
   20953             :          return add_reserved_function(function_name,(*local_data().free_function_list_.back()));     \
   20954             :       }                                                                                              \
   20955             : 
   20956             :       exprtk_define_reserved_function(00) exprtk_define_reserved_function(01)
   20957             :       exprtk_define_reserved_function(02) exprtk_define_reserved_function(03)
   20958             :       exprtk_define_reserved_function(04) exprtk_define_reserved_function(05)
   20959             :       exprtk_define_reserved_function(06) exprtk_define_reserved_function(07)
   20960             :       exprtk_define_reserved_function(08) exprtk_define_reserved_function(09)
   20961             :       exprtk_define_reserved_function(10) exprtk_define_reserved_function(11)
   20962             :       exprtk_define_reserved_function(12) exprtk_define_reserved_function(13)
   20963             :       exprtk_define_reserved_function(14) exprtk_define_reserved_function(15)
   20964             : 
   20965             :       #undef exprtk_define_reserved_function
   20966             : 
   20967             :       template <std::size_t N>
   20968        2143 :       inline bool add_vector(const std::string& vector_name, T (&v)[N])
   20969             :       {
   20970        2143 :          if (!valid())
   20971           0 :             return false;
   20972        2143 :          else if (!valid_symbol(vector_name))
   20973           0 :             return false;
   20974        2143 :          else if (symbol_exists(vector_name))
   20975           0 :             return false;
   20976             :          else
   20977        2143 :             return local_data().vector_store.add(vector_name,v);
   20978             :       }
   20979             : 
   20980           0 :       inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
   20981             :       {
   20982           0 :          if (!valid())
   20983           0 :             return false;
   20984           0 :          else if (!valid_symbol(vector_name))
   20985           0 :             return false;
   20986           0 :          else if (symbol_exists(vector_name))
   20987           0 :             return false;
   20988           0 :          else if (0 == v_size)
   20989           0 :             return false;
   20990             :          else
   20991           0 :             return local_data().vector_store.add(vector_name, v, v_size);
   20992             :       }
   20993             : 
   20994             :       template <typename Allocator>
   20995          84 :       inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
   20996             :       {
   20997          84 :          if (!valid())
   20998           0 :             return false;
   20999          84 :          else if (!valid_symbol(vector_name))
   21000           0 :             return false;
   21001          84 :          else if (symbol_exists(vector_name))
   21002           0 :             return false;
   21003          84 :          else if (0 == v.size())
   21004           0 :             return false;
   21005             :          else
   21006          84 :             return local_data().vector_store.add(vector_name,v);
   21007             :       }
   21008             : 
   21009        4195 :       inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
   21010             :       {
   21011        4195 :          if (!valid())
   21012           0 :             return false;
   21013        4195 :          else if (!valid_symbol(vector_name))
   21014           0 :             return false;
   21015        4195 :          else if (symbol_exists(vector_name))
   21016           0 :             return false;
   21017        4195 :          else if (0 == v.size())
   21018           0 :             return false;
   21019             :          else
   21020        4195 :             return local_data().vector_store.add(vector_name,v);
   21021             :       }
   21022             : 
   21023         344 :       inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
   21024             :       {
   21025         344 :          if (!valid())
   21026           0 :             return false;
   21027             :          else
   21028         344 :             return local_data().variable_store.remove(variable_name, delete_node);
   21029             :       }
   21030             : 
   21031             :       #ifndef exprtk_disable_string_capabilities
   21032          43 :       inline bool remove_stringvar(const std::string& string_name)
   21033             :       {
   21034          43 :          if (!valid())
   21035           0 :             return false;
   21036             :          else
   21037          43 :             return local_data().stringvar_store.remove(string_name);
   21038             :       }
   21039             :       #endif
   21040             : 
   21041          29 :       inline bool remove_function(const std::string& function_name)
   21042             :       {
   21043          29 :          if (!valid())
   21044           0 :             return false;
   21045             :          else
   21046          29 :             return local_data().function_store.remove(function_name);
   21047             :       }
   21048             : 
   21049           3 :       inline bool remove_vararg_function(const std::string& vararg_function_name)
   21050             :       {
   21051           3 :          if (!valid())
   21052           0 :             return false;
   21053             :          else
   21054           3 :             return local_data().vararg_function_store.remove(vararg_function_name);
   21055             :       }
   21056             : 
   21057           3 :       inline bool remove_vector(const std::string& vector_name)
   21058             :       {
   21059           3 :          if (!valid())
   21060           0 :             return false;
   21061             :          else
   21062           3 :             return local_data().vector_store.remove(vector_name);
   21063             :       }
   21064             : 
   21065       33080 :       inline bool add_constants()
   21066             :       {
   21067       33080 :          return add_pi      () &&
   21068       66160 :                 add_epsilon () &&
   21069       66160 :                 add_infinity() ;
   21070             :       }
   21071             : 
   21072       33081 :       inline bool add_pi()
   21073             :       {
   21074       33081 :          const typename details::numeric::details::number_type<T>::type num_type;
   21075       33081 :          static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
   21076       66162 :          return add_constant("pi",local_pi);
   21077             :       }
   21078             : 
   21079       33080 :       inline bool add_epsilon()
   21080             :       {
   21081       33080 :          static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
   21082       66160 :          return add_constant("epsilon",local_epsilon);
   21083             :       }
   21084             : 
   21085       33080 :       inline bool add_infinity()
   21086             :       {
   21087             :          static const T local_infinity = std::numeric_limits<T>::infinity();
   21088       66160 :          return add_constant("inf",local_infinity);
   21089             :       }
   21090             : 
   21091             :       template <typename Package>
   21092          62 :       inline bool add_package(Package& package)
   21093             :       {
   21094          62 :          return package.register_package(*this);
   21095             :       }
   21096             : 
   21097             :       template <typename Allocator,
   21098             :                 template <typename, typename> class Sequence>
   21099          10 :       inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
   21100             :       {
   21101          10 :          if (!valid())
   21102           0 :             return 0;
   21103             :          else
   21104          10 :             return local_data().variable_store.get_list(vlist);
   21105             :       }
   21106             : 
   21107             :       template <typename Allocator,
   21108             :                 template <typename, typename> class Sequence>
   21109          10 :       inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
   21110             :       {
   21111          10 :          if (!valid())
   21112           0 :             return 0;
   21113             :          else
   21114          10 :             return local_data().variable_store.get_list(vlist);
   21115             :       }
   21116             : 
   21117             :       #ifndef exprtk_disable_string_capabilities
   21118             :       template <typename Allocator,
   21119             :                 template <typename, typename> class Sequence>
   21120          10 :       inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
   21121             :       {
   21122          10 :          if (!valid())
   21123           0 :             return 0;
   21124             :          else
   21125          10 :             return local_data().stringvar_store.get_list(svlist);
   21126             :       }
   21127             : 
   21128             :       template <typename Allocator,
   21129             :                 template <typename, typename> class Sequence>
   21130          10 :       inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
   21131             :       {
   21132          10 :          if (!valid())
   21133           0 :             return 0;
   21134             :          else
   21135          10 :             return local_data().stringvar_store.get_list(svlist);
   21136             :       }
   21137             :       #endif
   21138             : 
   21139             :       template <typename Allocator,
   21140             :                 template <typename, typename> class Sequence>
   21141             :       inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const
   21142             :       {
   21143             :          if (!valid())
   21144             :             return 0;
   21145             :          else
   21146             :             return local_data().vector_store.get_list(vec_list);
   21147             :       }
   21148             : 
   21149             :       template <typename Allocator,
   21150             :                 template <typename, typename> class Sequence>
   21151             :       inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const
   21152             :       {
   21153             :          if (!valid())
   21154             :             return 0;
   21155             : 
   21156             :          std::vector<std::string> function_names;
   21157             :          std::size_t count = 0;
   21158             : 
   21159             :          count += local_data().function_store         .get_list(function_names);
   21160             :          count += local_data().vararg_function_store  .get_list(function_names);
   21161             :          count += local_data().generic_function_store .get_list(function_names);
   21162             :          count += local_data().string_function_store  .get_list(function_names);
   21163             :          count += local_data().overload_function_store.get_list(function_names);
   21164             : 
   21165             :          std::set<std::string> function_set;
   21166             : 
   21167             :          for (std::size_t i = 0; i < function_names.size(); ++i)
   21168             :          {
   21169             :             function_set.insert(function_names[i]);
   21170             :          }
   21171             : 
   21172             :          std::copy(function_set.begin(), function_set.end(),
   21173             :                    std::back_inserter(function_list));
   21174             : 
   21175             :          return count;
   21176             :       }
   21177             : 
   21178             :       inline std::vector<std::string> get_function_list() const
   21179             :       {
   21180             :          std::vector<std::string> result;
   21181             :          get_function_list(result);
   21182             :          return result;
   21183             :       }
   21184             : 
   21185      903527 :       inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
   21186             :       {
   21187             :          /*
   21188             :             Function will return true if symbol_name exists as either a
   21189             :             reserved symbol, variable, stringvar, vector or function name
   21190             :             in any of the type stores.
   21191             :          */
   21192      903527 :          if (!valid())
   21193           0 :             return false;
   21194      903527 :          else if (local_data().variable_store.symbol_exists(symbol_name))
   21195         118 :             return true;
   21196             :          #ifndef exprtk_disable_string_capabilities
   21197      903409 :          else if (local_data().stringvar_store.symbol_exists(symbol_name))
   21198         118 :             return true;
   21199             :          #endif
   21200      903291 :          else if (local_data().vector_store.symbol_exists(symbol_name))
   21201           2 :             return true;
   21202      903289 :          else if (local_data().function_store.symbol_exists(symbol_name))
   21203          20 :             return true;
   21204      903269 :          else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
   21205           0 :             return true;
   21206             :          else
   21207      903269 :             return false;
   21208             :       }
   21209             : 
   21210         727 :       inline bool is_variable(const std::string& variable_name) const
   21211             :       {
   21212         727 :          if (!valid())
   21213           0 :             return false;
   21214             :          else
   21215         727 :             return local_data().variable_store.symbol_exists(variable_name);
   21216             :       }
   21217             : 
   21218             :       #ifndef exprtk_disable_string_capabilities
   21219         727 :       inline bool is_stringvar(const std::string& stringvar_name) const
   21220             :       {
   21221         727 :          if (!valid())
   21222           0 :             return false;
   21223             :          else
   21224         727 :             return local_data().stringvar_store.symbol_exists(stringvar_name);
   21225             :       }
   21226             : 
   21227             :       inline bool is_conststr_stringvar(const std::string& symbol_name) const
   21228             :       {
   21229             :          if (!valid())
   21230             :             return false;
   21231             :          else if (!valid_symbol(symbol_name))
   21232             :             return false;
   21233             :          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
   21234             :             return false;
   21235             : 
   21236             :          return (
   21237             :                   local_data().stringvar_store.symbol_exists(symbol_name) ||
   21238             :                   local_data().stringvar_store.is_constant  (symbol_name)
   21239             :                 );
   21240             :       }
   21241             :       #endif
   21242             : 
   21243         727 :       inline bool is_function(const std::string& function_name) const
   21244             :       {
   21245         727 :          if (!valid())
   21246           0 :             return false;
   21247             :          else
   21248         727 :             return local_data().function_store.symbol_exists(function_name);
   21249             :       }
   21250             : 
   21251         727 :       inline bool is_vararg_function(const std::string& vararg_function_name) const
   21252             :       {
   21253         727 :          if (!valid())
   21254           0 :             return false;
   21255             :          else
   21256         727 :             return local_data().vararg_function_store.symbol_exists(vararg_function_name);
   21257             :       }
   21258             : 
   21259         727 :       inline bool is_vector(const std::string& vector_name) const
   21260             :       {
   21261         727 :          if (!valid())
   21262           0 :             return false;
   21263             :          else
   21264         727 :             return local_data().vector_store.symbol_exists(vector_name);
   21265             :       }
   21266             : 
   21267             :       inline std::string get_variable_name(const expression_ptr& ptr) const
   21268             :       {
   21269             :          return local_data().variable_store.entity_name(ptr);
   21270             :       }
   21271             : 
   21272             :       inline std::string get_vector_name(const vector_holder_ptr& ptr) const
   21273             :       {
   21274             :          return local_data().vector_store.entity_name(ptr);
   21275             :       }
   21276             : 
   21277             :       #ifndef exprtk_disable_string_capabilities
   21278             :       inline std::string get_stringvar_name(const expression_ptr& ptr) const
   21279             :       {
   21280             :          return local_data().stringvar_store.entity_name(ptr);
   21281             :       }
   21282             : 
   21283             :       inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
   21284             :       {
   21285             :          return local_data().stringvar_store.entity_name(ptr);
   21286             :       }
   21287             :       #endif
   21288             : 
   21289    34522198 :       inline bool valid() const
   21290             :       {
   21291             :          // Symbol table sanity check.
   21292    34522198 :          return control_block_ && control_block_->data_;
   21293             :       }
   21294             : 
   21295         727 :       inline void load_from(const symbol_table<T>& st)
   21296             :       {
   21297             :          {
   21298         727 :             std::vector<std::string> name_list;
   21299             : 
   21300         727 :             st.local_data().function_store.get_list(name_list);
   21301             : 
   21302         727 :             if (!name_list.empty())
   21303             :             {
   21304        2799 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   21305             :                {
   21306        2178 :                   exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
   21307        2178 :                   add_function(name_list[i],ifunc);
   21308             :                }
   21309             :             }
   21310         727 :          }
   21311             : 
   21312             :          {
   21313         727 :             std::vector<std::string> name_list;
   21314             : 
   21315         727 :             st.local_data().vararg_function_store.get_list(name_list);
   21316             : 
   21317         727 :             if (!name_list.empty())
   21318             :             {
   21319           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   21320             :                {
   21321           0 :                   exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
   21322           0 :                   add_function(name_list[i],ivafunc);
   21323             :                }
   21324             :             }
   21325         727 :          }
   21326             : 
   21327             :          {
   21328         727 :             std::vector<std::string> name_list;
   21329             : 
   21330         727 :             st.local_data().generic_function_store.get_list(name_list);
   21331             : 
   21332         727 :             if (!name_list.empty())
   21333             :             {
   21334           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   21335             :                {
   21336           0 :                   exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
   21337           0 :                   add_function(name_list[i],ifunc);
   21338             :                }
   21339             :             }
   21340         727 :          }
   21341             : 
   21342             :          {
   21343         727 :             std::vector<std::string> name_list;
   21344             : 
   21345         727 :             st.local_data().string_function_store.get_list(name_list);
   21346             : 
   21347         727 :             if (!name_list.empty())
   21348             :             {
   21349           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   21350             :                {
   21351           0 :                   exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
   21352           0 :                   add_function(name_list[i],ifunc);
   21353             :                }
   21354             :             }
   21355         727 :          }
   21356             : 
   21357             :          {
   21358         727 :             std::vector<std::string> name_list;
   21359             : 
   21360         727 :             st.local_data().overload_function_store.get_list(name_list);
   21361             : 
   21362         727 :             if (!name_list.empty())
   21363             :             {
   21364           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   21365             :                {
   21366           0 :                   exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
   21367           0 :                   add_function(name_list[i],ifunc);
   21368             :                }
   21369             :             }
   21370         727 :          }
   21371         727 :       }
   21372             : 
   21373           0 :       inline void load_variables_from(const symbol_table<T>& st)
   21374             :       {
   21375           0 :          std::vector<std::string> name_list;
   21376             : 
   21377           0 :          st.local_data().variable_store.get_list(name_list);
   21378             : 
   21379           0 :          if (!name_list.empty())
   21380             :          {
   21381           0 :             for (std::size_t i = 0; i < name_list.size(); ++i)
   21382             :             {
   21383           0 :                T& variable = st.get_variable(name_list[i])->ref();
   21384           0 :                add_variable(name_list[i], variable);
   21385             :             }
   21386             :          }
   21387           0 :       }
   21388             : 
   21389           0 :       inline void load_vectors_from(const symbol_table<T>& st)
   21390             :       {
   21391           0 :          std::vector<std::string> name_list;
   21392             : 
   21393           0 :          st.local_data().vector_store.get_list(name_list);
   21394             : 
   21395           0 :          if (!name_list.empty())
   21396             :          {
   21397           0 :             for (std::size_t i = 0; i < name_list.size(); ++i)
   21398             :             {
   21399           0 :                vector_holder_t& vecholder = *st.get_vector(name_list[i]);
   21400           0 :                add_vector(name_list[i], vecholder.data(), vecholder.size());
   21401             :             }
   21402             :          }
   21403           0 :       }
   21404             : 
   21405             :    private:
   21406             : 
   21407    16793583 :       inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
   21408             :       {
   21409    16793583 :          if (symbol.empty())
   21410           0 :             return false;
   21411    16793583 :          else if (!details::is_letter(symbol[0]))
   21412          23 :             return false;
   21413    16793560 :          else if (symbol.size() > 1)
   21414             :          {
   21415     3143937 :             for (std::size_t i = 1; i < symbol.size(); ++i)
   21416             :             {
   21417     2257117 :                if (
   21418     2268303 :                     !details::is_letter_or_digit(symbol[i]) &&
   21419       11186 :                     ('_' != symbol[i])
   21420             :                   )
   21421             :                {
   21422         604 :                   if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
   21423         604 :                      continue;
   21424             :                   else
   21425           0 :                      return false;
   21426             :                }
   21427             :             }
   21428             :          }
   21429             : 
   21430    16793560 :          return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
   21431             :       }
   21432             : 
   21433      185443 :       inline bool valid_function(const std::string& symbol) const
   21434             :       {
   21435      185443 :          if (symbol.empty())
   21436           0 :             return false;
   21437      185443 :          else if (!details::is_letter(symbol[0]))
   21438         115 :             return false;
   21439      185328 :          else if (symbol.size() > 1)
   21440             :          {
   21441      662596 :             for (std::size_t i = 1; i < symbol.size(); ++i)
   21442             :             {
   21443      510054 :                if (
   21444      520099 :                     !details::is_letter_or_digit(symbol[i]) &&
   21445       10045 :                     ('_' != symbol[i])
   21446             :                   )
   21447             :                {
   21448        1820 :                   if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
   21449        1820 :                      continue;
   21450             :                   else
   21451           0 :                      return false;
   21452             :                }
   21453             :             }
   21454             :          }
   21455             : 
   21456      185328 :          return true;
   21457             :       }
   21458             : 
   21459             :       typedef typename control_block::st_data local_data_t;
   21460             : 
   21461     1862782 :       inline local_data_t& local_data()
   21462             :       {
   21463     1862782 :          return *(control_block_->data_);
   21464             :       }
   21465             : 
   21466    38071241 :       inline const local_data_t& local_data() const
   21467             :       {
   21468    38071241 :          return *(control_block_->data_);
   21469             :       }
   21470             : 
   21471             :       control_block* control_block_;
   21472             : 
   21473             :       friend class parser<T>;
   21474             :    }; // class symbol_table
   21475             : 
   21476             :    template <typename T>
   21477             :    class function_compositor;
   21478             : 
   21479             :    template <typename T>
   21480             :    class expression
   21481             :    {
   21482             :    private:
   21483             : 
   21484             :       typedef details::expression_node<T>*  expression_ptr;
   21485             :       typedef details::vector_holder<T>*    vector_holder_ptr;
   21486             :       typedef std::vector<symbol_table<T> > symtab_list_t;
   21487             : 
   21488             :       struct control_block
   21489             :       {
   21490             :          enum data_type
   21491             :          {
   21492             :             e_unknown  ,
   21493             :             e_expr     ,
   21494             :             e_vecholder,
   21495             :             e_data     ,
   21496             :             e_vecdata  ,
   21497             :             e_string
   21498             :          };
   21499             : 
   21500             :          struct data_pack
   21501             :          {
   21502             :             data_pack()
   21503             :             : pointer(0)
   21504             :             , type(e_unknown)
   21505             :             , size(0)
   21506             :             {}
   21507             : 
   21508      169435 :             data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
   21509      169435 :             : pointer(ptr)
   21510      169435 :             , type(dt)
   21511      169435 :             , size(sz)
   21512      169435 :             {}
   21513             : 
   21514             :             void*       pointer;
   21515             :             data_type   type;
   21516             :             std::size_t size;
   21517             :          };
   21518             : 
   21519             :          typedef std::vector<data_pack> local_data_list_t;
   21520             :          typedef results_context<T>     results_context_t;
   21521             :          typedef control_block*         cntrl_blck_ptr_t;
   21522             : 
   21523             :          control_block()
   21524             :          : ref_count(0)
   21525             :          , expr     (0)
   21526             :          , results  (0)
   21527             :          , retinv_null(false)
   21528             :          , return_invoked(&retinv_null)
   21529             :          {}
   21530             : 
   21531      703723 :          explicit control_block(expression_ptr e)
   21532      703723 :          : ref_count(1)
   21533      703723 :          , expr     (e)
   21534      703723 :          , results  (0)
   21535      703723 :          , retinv_null(false)
   21536      703723 :          , return_invoked(&retinv_null)
   21537      703723 :          {}
   21538             : 
   21539      703723 :         ~control_block()
   21540             :          {
   21541      703723 :             if (expr && details::branch_deletable(expr))
   21542             :             {
   21543      703478 :                destroy_node(expr);
   21544             :             }
   21545             : 
   21546      703723 :             if (!local_data_list.empty())
   21547             :             {
   21548      208222 :                for (std::size_t i = 0; i < local_data_list.size(); ++i)
   21549             :                {
   21550      169435 :                   switch (local_data_list[i].type)
   21551             :                   {
   21552       68301 :                      case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
   21553       68301 :                                         break;
   21554             : 
   21555       23261 :                      case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
   21556       23261 :                                         break;
   21557             : 
   21558       44872 :                      case e_data      : delete reinterpret_cast<T*>(local_data_list[i].pointer);
   21559       44872 :                                         break;
   21560             : 
   21561       23261 :                      case e_vecdata   : delete [] reinterpret_cast<T*>(local_data_list[i].pointer);
   21562       23261 :                                         break;
   21563             : 
   21564        9740 :                      case e_string    : delete reinterpret_cast<std::string*>(local_data_list[i].pointer);
   21565        9740 :                                         break;
   21566             : 
   21567           0 :                      default          : break;
   21568             :                   }
   21569             :                }
   21570             :             }
   21571             : 
   21572      703723 :             if (results)
   21573             :             {
   21574         111 :                delete results;
   21575             :             }
   21576      703723 :          }
   21577             : 
   21578      703723 :          static inline cntrl_blck_ptr_t create(expression_ptr e)
   21579             :          {
   21580      703723 :             return new control_block(e);
   21581             :          }
   21582             : 
   21583      594097 :          static inline void destroy(cntrl_blck_ptr_t& cntrl_blck)
   21584             :          {
   21585      594097 :             if (cntrl_blck)
   21586             :             {
   21587      584137 :                if (
   21588     1168274 :                     (0 !=   cntrl_blck->ref_count) &&
   21589      584137 :                     (0 == --cntrl_blck->ref_count)
   21590             :                   )
   21591             :                {
   21592      343641 :                   delete cntrl_blck;
   21593             :                }
   21594             : 
   21595      584137 :                cntrl_blck = 0;
   21596             :             }
   21597      594097 :          }
   21598             : 
   21599             :          std::size_t ref_count;
   21600             :          expression_ptr expr;
   21601             :          local_data_list_t local_data_list;
   21602             :          results_context_t* results;
   21603             :          bool  retinv_null;
   21604             :          bool* return_invoked;
   21605             : 
   21606             :          friend class function_compositor<T>;
   21607             :       };
   21608             : 
   21609             :    public:
   21610             : 
   21611      344564 :       expression()
   21612      344564 :       : control_block_(0)
   21613             :       {
   21614      344564 :          set_expression(new details::null_node<T>());
   21615      344564 :       }
   21616             : 
   21617      239042 :       expression(const expression<T>& e)
   21618      239042 :       : control_block_    (e.control_block_    )
   21619      239042 :       , symbol_table_list_(e.symbol_table_list_)
   21620             :       {
   21621      239042 :          control_block_->ref_count++;
   21622      239042 :       }
   21623             : 
   21624             :       explicit expression(const symbol_table<T>& symbol_table)
   21625             :       : control_block_(0)
   21626             :       {
   21627             :          set_expression(new details::null_node<T>());
   21628             :          symbol_table_list_.push_back(symbol_table);
   21629             :       }
   21630             : 
   21631        1454 :       inline expression<T>& operator=(const expression<T>& e)
   21632             :       {
   21633        1454 :          if (this != &e)
   21634             :          {
   21635        1454 :             if (control_block_)
   21636             :             {
   21637        1454 :                if (
   21638        2908 :                     (0 !=   control_block_->ref_count) &&
   21639        1454 :                     (0 == --control_block_->ref_count)
   21640             :                   )
   21641             :                {
   21642        1454 :                   delete control_block_;
   21643             :                }
   21644             : 
   21645        1454 :                control_block_ = 0;
   21646             :             }
   21647             : 
   21648        1454 :             control_block_ = e.control_block_;
   21649        1454 :             control_block_->ref_count++;
   21650        1454 :             symbol_table_list_ = e.symbol_table_list_;
   21651             :          }
   21652             : 
   21653        1454 :          return *this;
   21654             :       }
   21655             : 
   21656             :       inline bool operator==(const expression<T>& e) const
   21657             :       {
   21658             :          return (this == &e);
   21659             :       }
   21660             : 
   21661      359659 :       inline bool operator!() const
   21662             :       {
   21663             :          return (
   21664      718818 :                   (0 == control_block_      ) ||
   21665      359159 :                   (0 == control_block_->expr)
   21666      359659 :                 );
   21667             :       }
   21668             : 
   21669       10491 :       inline expression<T>& release()
   21670             :       {
   21671       10491 :          exprtk::details::dump_ptr("expression::release", this);
   21672       10491 :          control_block::destroy(control_block_);
   21673             : 
   21674       10491 :          return (*this);
   21675             :       }
   21676             : 
   21677      583606 :      ~expression()
   21678             :       {
   21679      583606 :          control_block::destroy(control_block_);
   21680      583606 :       }
   21681             : 
   21682   196282243 :       inline T value() const
   21683             :       {
   21684   196282243 :          assert(control_block_      );
   21685   196282243 :          assert(control_block_->expr);
   21686             : 
   21687   196282243 :          return control_block_->expr->value();
   21688             :       }
   21689             : 
   21690             :       inline T operator() () const
   21691             :       {
   21692             :          return value();
   21693             :       }
   21694             : 
   21695             :       inline operator T() const
   21696             :       {
   21697             :          return value();
   21698             :       }
   21699             : 
   21700             :       inline operator bool() const
   21701             :       {
   21702             :          return details::is_true(value());
   21703             :       }
   21704             : 
   21705      363842 :       inline bool register_symbol_table(symbol_table<T>& st)
   21706             :       {
   21707      375383 :          for (std::size_t i = 0; i < symbol_table_list_.size(); ++i)
   21708             :          {
   21709       31543 :             if (st == symbol_table_list_[i])
   21710             :             {
   21711       20002 :                return false;
   21712             :             }
   21713             :          }
   21714             : 
   21715      343840 :          symbol_table_list_.push_back(st);
   21716      343840 :          return true;
   21717             :       }
   21718             : 
   21719    36000003 :       inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
   21720             :       {
   21721    12000001 :          return symbol_table_list_[index];
   21722             :       }
   21723             : 
   21724             :       inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
   21725             :       {
   21726             :          return symbol_table_list_[index];
   21727             :       }
   21728             : 
   21729           4 :       std::size_t num_symbol_tables() const
   21730             :       {
   21731           4 :          return symbol_table_list_.size();
   21732             :       }
   21733             : 
   21734             :       typedef results_context<T> results_context_t;
   21735             : 
   21736          45 :       inline const results_context_t& results() const
   21737             :       {
   21738          45 :          if (control_block_->results)
   21739          45 :             return (*control_block_->results);
   21740             :          else
   21741             :          {
   21742           0 :             static const results_context_t null_results;
   21743           0 :             return null_results;
   21744             :          }
   21745             :       }
   21746             : 
   21747          30 :       inline bool return_invoked() const
   21748             :       {
   21749          30 :          return (*control_block_->return_invoked);
   21750             :       }
   21751             : 
   21752             :    private:
   21753             : 
   21754      370158 :       inline symtab_list_t get_symbol_table_list() const
   21755             :       {
   21756      370158 :          return symbol_table_list_;
   21757             :       }
   21758             : 
   21759      703723 :       inline void set_expression(const expression_ptr expr)
   21760             :       {
   21761      703723 :          if (expr)
   21762             :          {
   21763      703723 :             if (control_block_)
   21764             :             {
   21765      358628 :                if (0 == --control_block_->ref_count)
   21766             :                {
   21767      358628 :                   delete control_block_;
   21768             :                }
   21769             :             }
   21770             : 
   21771      703723 :             control_block_ = control_block::create(expr);
   21772             :          }
   21773      703723 :       }
   21774             : 
   21775       68301 :       inline void register_local_var(expression_ptr expr)
   21776             :       {
   21777       68301 :          if (expr)
   21778             :          {
   21779       68301 :             if (control_block_)
   21780             :             {
   21781       68301 :                control_block_->
   21782       68301 :                   local_data_list.push_back(
   21783             :                      typename expression<T>::control_block::
   21784      136602 :                         data_pack(reinterpret_cast<void*>(expr),
   21785             :                                   control_block::e_expr));
   21786             :             }
   21787             :          }
   21788       68301 :       }
   21789             : 
   21790       23261 :       inline void register_local_var(vector_holder_ptr vec_holder)
   21791             :       {
   21792       23261 :          if (vec_holder)
   21793             :          {
   21794       23261 :             if (control_block_)
   21795             :             {
   21796       23261 :                control_block_->
   21797       23261 :                   local_data_list.push_back(
   21798             :                      typename expression<T>::control_block::
   21799       46522 :                         data_pack(reinterpret_cast<void*>(vec_holder),
   21800             :                                   control_block::e_vecholder));
   21801             :             }
   21802             :          }
   21803       23261 :       }
   21804             : 
   21805       77873 :       inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
   21806             :       {
   21807       77873 :          if (data)
   21808             :          {
   21809       77873 :             if (control_block_)
   21810             :             {
   21811       77873 :                typename control_block::data_type dt = control_block::e_data;
   21812             : 
   21813       77873 :                switch (data_mode)
   21814             :                {
   21815       44872 :                   case 0 : dt = control_block::e_data;    break;
   21816       23261 :                   case 1 : dt = control_block::e_vecdata; break;
   21817        9740 :                   case 2 : dt = control_block::e_string;  break;
   21818             :                }
   21819             : 
   21820       77873 :                control_block_->
   21821       77873 :                   local_data_list.push_back(
   21822             :                      typename expression<T>::control_block::
   21823      155746 :                         data_pack(reinterpret_cast<void*>(data), dt, size));
   21824             :             }
   21825             :          }
   21826       77873 :       }
   21827             : 
   21828         727 :       inline const typename control_block::local_data_list_t& local_data_list()
   21829             :       {
   21830         727 :          if (control_block_)
   21831             :          {
   21832         727 :             return control_block_->local_data_list;
   21833             :          }
   21834             :          else
   21835             :          {
   21836           0 :             static typename control_block::local_data_list_t null_local_data_list;
   21837           0 :             return null_local_data_list;
   21838             :          }
   21839             :       }
   21840             : 
   21841      359159 :       inline void register_return_results(results_context_t* rc)
   21842             :       {
   21843      359159 :          if (control_block_ && rc)
   21844             :          {
   21845         111 :             control_block_->results = rc;
   21846             :          }
   21847      359159 :       }
   21848             : 
   21849      359159 :       inline void set_retinvk(bool* retinvk_ptr)
   21850             :       {
   21851      359159 :          if (control_block_)
   21852             :          {
   21853      359159 :             control_block_->return_invoked = retinvk_ptr;
   21854             :          }
   21855      359159 :       }
   21856             : 
   21857             :       control_block* control_block_;
   21858             :       symtab_list_t  symbol_table_list_;
   21859             : 
   21860             :       friend class parser<T>;
   21861             :       friend class expression_helper<T>;
   21862             :       friend class function_compositor<T>;
   21863             :       template <typename TT>
   21864             :       friend bool is_valid(const expression<TT>& expr);
   21865             :    }; // class expression
   21866             : 
   21867             :    template <typename T>
   21868             :    class expression_helper
   21869             :    {
   21870             :    public:
   21871             : 
   21872             :       enum node_types
   21873             :       {
   21874             :          e_literal,
   21875             :          e_variable,
   21876             :          e_string,
   21877             :          e_unary,
   21878             :          e_binary,
   21879             :          e_function,
   21880             :          e_vararg,
   21881             :          e_null,
   21882             :          e_assert,
   21883             :          e_sf3ext,
   21884             :          e_sf4ext
   21885             :       };
   21886             : 
   21887       10759 :       static inline bool is_literal(const expression<T>& expr)
   21888             :       {
   21889       10759 :          return expr.control_block_ && details::is_literal_node(expr.control_block_->expr);
   21890             :       }
   21891             : 
   21892             :       static inline bool is_variable(const expression<T>& expr)
   21893             :       {
   21894             :          return expr.control_block_ && details::is_variable_node(expr.control_block_->expr);
   21895             :       }
   21896             : 
   21897             :       static inline bool is_string(const expression<T>& expr)
   21898             :       {
   21899             :          return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr);
   21900             :       }
   21901             : 
   21902             :       static inline bool is_unary(const expression<T>& expr)
   21903             :       {
   21904             :          return expr.control_block_ && details::is_unary_node(expr.control_block_->expr);
   21905             :       }
   21906             : 
   21907             :       static inline bool is_binary(const expression<T>& expr)
   21908             :       {
   21909             :          return expr.control_block_ && details::is_binary_node(expr.control_block_->expr);
   21910             :       }
   21911             : 
   21912             :       static inline bool is_function(const expression<T>& expr)
   21913             :       {
   21914             :          return expr.control_block_ && details::is_function(expr.control_block_->expr);
   21915             :       }
   21916             : 
   21917          54 :       static inline bool is_vararg(const expression<T>& expr)
   21918             :       {
   21919          54 :          return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr);
   21920             :       }
   21921             : 
   21922          12 :       static inline bool is_null(const expression<T>& expr)
   21923             :       {
   21924          12 :          return expr.control_block_ && details::is_null_node(expr.control_block_->expr);
   21925             :       }
   21926             : 
   21927             :       static inline bool is_assert(const expression<T>& expr)
   21928             :       {
   21929             :          return expr.control_block_ && details::is_assert_node(expr.control_block_->expr);
   21930             :       }
   21931             : 
   21932             :       static inline bool is_sf3ext(const expression<T>& expr)
   21933             :       {
   21934             :          return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr);
   21935             :       }
   21936             : 
   21937             :       static inline bool is_sf4ext(const expression<T>& expr)
   21938             :       {
   21939             :          return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr);
   21940             :       }
   21941             : 
   21942             :       static inline bool is_type(const expression<T>& expr, const node_types node_type)
   21943             :       {
   21944             :          if (0 == expr.control_block_)
   21945             :          {
   21946             :             return false;
   21947             :          }
   21948             : 
   21949             :          switch (node_type)
   21950             :          {
   21951             :             case e_literal  : return is_literal_node(expr);
   21952             :             case e_variable : return is_variable    (expr);
   21953             :             case e_string   : return is_string      (expr);
   21954             :             case e_unary    : return is_unary       (expr);
   21955             :             case e_binary   : return is_binary      (expr);
   21956             :             case e_function : return is_function    (expr);
   21957             :             case e_null     : return is_null        (expr);
   21958             :             case e_assert   : return is_assert      (expr);
   21959             :             case e_sf3ext   : return is_sf3ext      (expr);
   21960             :             case e_sf4ext   : return is_sf4ext      (expr);
   21961             :          };
   21962             : 
   21963             :          return false;
   21964             :       }
   21965             : 
   21966          54 :       static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq)
   21967             :       {
   21968          54 :          if ((0 == expr.control_block_) || !is_vararg(expr))
   21969             :          {
   21970           0 :             return false;
   21971             :          }
   21972             : 
   21973             :          typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t;
   21974             : 
   21975          54 :          mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr);
   21976             : 
   21977          54 :          if (
   21978          54 :               (0 == vnode) ||
   21979         108 :               type_seq.empty() ||
   21980          54 :               (vnode->size() < type_seq.size())
   21981             :             )
   21982             :          {
   21983           0 :             return false;
   21984             :          }
   21985             : 
   21986         190 :          for (std::size_t i = 0; i < type_seq.size(); ++i)
   21987             :          {
   21988         136 :             assert((*vnode)[i]);
   21989             : 
   21990         136 :             switch(type_seq[i])
   21991             :             {
   21992          25 :                case e_literal  : { if (details::is_literal_node         ((*vnode)[i])) continue; } break;
   21993           0 :                case e_variable : { if (details::is_variable_node        ((*vnode)[i])) continue; } break;
   21994          26 :                case e_string   : { if (details::is_generally_string_node((*vnode)[i])) continue; } break;
   21995           0 :                case e_unary    : { if (details::is_unary_node           ((*vnode)[i])) continue; } break;
   21996           0 :                case e_binary   : { if (details::is_binary_node          ((*vnode)[i])) continue; } break;
   21997           0 :                case e_function : { if (details::is_function             ((*vnode)[i])) continue; } break;
   21998           0 :                case e_null     : { if (details::is_null_node            ((*vnode)[i])) continue; } break;
   21999          84 :                case e_assert   : { if (details::is_assert_node          ((*vnode)[i])) continue; } break;
   22000           1 :                case e_sf3ext   : { if (details::is_sf3ext_node          ((*vnode)[i])) continue; } break;
   22001           0 :                case e_sf4ext   : { if (details::is_sf4ext_node          ((*vnode)[i])) continue; } break;
   22002           0 :                case e_vararg   : break;
   22003             :             }
   22004             : 
   22005           0 :             return false;
   22006             :          }
   22007             : 
   22008          54 :          return true;
   22009             :       }
   22010             :    };
   22011             : 
   22012             :    template <typename T>
   22013             :    inline bool is_valid(const expression<T>& expr)
   22014             :    {
   22015             :       return expr.control_block_ && !expression_helper<T>::is_null(expr);
   22016             :    }
   22017             : 
   22018             :    namespace parser_error
   22019             :    {
   22020             :       enum error_mode
   22021             :       {
   22022             :          e_unknown   = 0,
   22023             :          e_syntax    = 1,
   22024             :          e_token     = 2,
   22025             :          e_numeric   = 4,
   22026             :          e_symtab    = 5,
   22027             :          e_lexer     = 6,
   22028             :          e_synthesis = 7,
   22029             :          e_helper    = 8,
   22030             :          e_parser    = 9
   22031             :       };
   22032             : 
   22033             :       struct type
   22034             :       {
   22035       43680 :          type()
   22036       87360 :          : mode(parser_error::e_unknown)
   22037       43680 :          , line_no  (0)
   22038       43680 :          , column_no(0)
   22039       43680 :          {}
   22040             : 
   22041             :          lexer::token token;
   22042             :          error_mode mode;
   22043             :          std::string diagnostic;
   22044             :          std::string src_location;
   22045             :          std::string error_line;
   22046             :          std::size_t line_no;
   22047             :          std::size_t column_no;
   22048             :       };
   22049             : 
   22050           1 :       inline type make_error(const error_mode mode,
   22051             :                              const std::string& diagnostic   = "",
   22052             :                              const std::string& src_location = "")
   22053             :       {
   22054           1 :          type t;
   22055           1 :          t.mode         = mode;
   22056           1 :          t.token.type   = lexer::token::e_error;
   22057           1 :          t.diagnostic   = diagnostic;
   22058           1 :          t.src_location = src_location;
   22059             :          exprtk_debug(("%s\n", diagnostic .c_str()));
   22060           1 :          return t;
   22061           0 :       }
   22062             : 
   22063       43679 :       inline type make_error(const error_mode mode,
   22064             :                              const lexer::token& tk,
   22065             :                              const std::string& diagnostic   = "",
   22066             :                              const std::string& src_location = "")
   22067             :       {
   22068       43679 :          type t;
   22069       43679 :          t.mode         = mode;
   22070       43679 :          t.token        = tk;
   22071       43679 :          t.diagnostic   = diagnostic;
   22072       43679 :          t.src_location = src_location;
   22073             :          exprtk_debug(("%s\n", diagnostic .c_str()));
   22074       43679 :          return t;
   22075           0 :       }
   22076             : 
   22077           0 :       inline std::string to_str(error_mode mode)
   22078             :       {
   22079           0 :          switch (mode)
   22080             :          {
   22081           0 :             case e_unknown : return std::string("Unknown Error");
   22082           0 :             case e_syntax  : return std::string("Syntax Error" );
   22083           0 :             case e_token   : return std::string("Token Error"  );
   22084           0 :             case e_numeric : return std::string("Numeric Error");
   22085           0 :             case e_symtab  : return std::string("Symbol Error" );
   22086           0 :             case e_lexer   : return std::string("Lexer Error"  );
   22087           0 :             case e_helper  : return std::string("Helper Error" );
   22088           0 :             case e_parser  : return std::string("Parser Error" );
   22089           0 :             default        : return std::string("Unknown Error");
   22090             :          }
   22091             :       }
   22092             : 
   22093           0 :       inline bool update_error(type& error, const std::string& expression)
   22094             :       {
   22095           0 :          if (
   22096           0 :               expression.empty()                         ||
   22097           0 :               (error.token.position > expression.size()) ||
   22098           0 :               (std::numeric_limits<std::size_t>::max() == error.token.position)
   22099             :             )
   22100             :          {
   22101           0 :             return false;
   22102             :          }
   22103             : 
   22104           0 :          std::size_t error_line_start = 0;
   22105             : 
   22106           0 :          for (std::size_t i = error.token.position; i > 0; --i)
   22107             :          {
   22108           0 :             const details::char_t c = expression[i];
   22109             : 
   22110           0 :             if (('\n' == c) || ('\r' == c))
   22111             :             {
   22112           0 :                error_line_start = i + 1;
   22113           0 :                break;
   22114             :             }
   22115             :          }
   22116             : 
   22117           0 :          std::size_t next_nl_position = std::min(expression.size(),
   22118           0 :                                                  expression.find_first_of('\n',error.token.position + 1));
   22119             : 
   22120           0 :          error.column_no  = error.token.position - error_line_start;
   22121           0 :          error.error_line = expression.substr(error_line_start,
   22122           0 :                                               next_nl_position - error_line_start);
   22123             : 
   22124           0 :          error.line_no = 0;
   22125             : 
   22126           0 :          for (std::size_t i = 0; i < next_nl_position; ++i)
   22127             :          {
   22128           0 :             if ('\n' == expression[i])
   22129           0 :                ++error.line_no;
   22130             :          }
   22131             : 
   22132           0 :          return true;
   22133             :       }
   22134             : 
   22135             :       inline void dump_error(const type& error)
   22136             :       {
   22137             :          printf("Position: %02d   Type: [%s]   Msg: %s\n",
   22138             :                 static_cast<int>(error.token.position),
   22139             :                 exprtk::parser_error::to_str(error.mode).c_str(),
   22140             :                 error.diagnostic.c_str());
   22141             :       }
   22142             :    }
   22143             : 
   22144             :    namespace details
   22145             :    {
   22146             :       template <typename Parser>
   22147           4 :       inline void disable_type_checking(Parser& p)
   22148             :       {
   22149           4 :          p.state_.type_check_enabled = false;
   22150           4 :       }
   22151             :    }
   22152             : 
   22153             :    template <typename T>
   22154             :    class parser : public lexer::parser_helper
   22155             :    {
   22156             :    private:
   22157             : 
   22158             :       enum precedence_level
   22159             :       {
   22160             :          e_level00, e_level01, e_level02, e_level03, e_level04,
   22161             :          e_level05, e_level06, e_level07, e_level08, e_level09,
   22162             :          e_level10, e_level11, e_level12, e_level13, e_level14
   22163             :       };
   22164             : 
   22165             :       typedef const T&                                       cref_t;
   22166             :       typedef const T                                        const_t;
   22167             :       typedef ifunction<T>                                   F;
   22168             :       typedef ivararg_function<T>                            VAF;
   22169             :       typedef igeneric_function<T>                           GF;
   22170             :       typedef ifunction<T>                                   ifunction_t;
   22171             :       typedef ivararg_function<T>                            ivararg_function_t;
   22172             :       typedef igeneric_function<T>                           igeneric_function_t;
   22173             :       typedef details::expression_node<T>                    expression_node_t;
   22174             :       typedef details::literal_node<T>                       literal_node_t;
   22175             :       typedef details::unary_node<T>                         unary_node_t;
   22176             :       typedef details::binary_node<T>                        binary_node_t;
   22177             :       typedef details::trinary_node<T>                       trinary_node_t;
   22178             :       typedef details::quaternary_node<T>                    quaternary_node_t;
   22179             :       typedef details::conditional_node<T>                   conditional_node_t;
   22180             :       typedef details::cons_conditional_node<T>              cons_conditional_node_t;
   22181             :       typedef details::while_loop_node<T>                    while_loop_node_t;
   22182             :       typedef details::repeat_until_loop_node<T>             repeat_until_loop_node_t;
   22183             :       typedef details::for_loop_node<T>                      for_loop_node_t;
   22184             :       typedef details::while_loop_rtc_node<T>                while_loop_rtc_node_t;
   22185             :       typedef details::repeat_until_loop_rtc_node<T>         repeat_until_loop_rtc_node_t;
   22186             :       typedef details::for_loop_rtc_node<T>                  for_loop_rtc_node_t;
   22187             :       #ifndef exprtk_disable_break_continue
   22188             :       typedef details::while_loop_bc_node<T>                 while_loop_bc_node_t;
   22189             :       typedef details::repeat_until_loop_bc_node<T>          repeat_until_loop_bc_node_t;
   22190             :       typedef details::for_loop_bc_node<T>                   for_loop_bc_node_t;
   22191             :       typedef details::while_loop_bc_rtc_node<T>             while_loop_bc_rtc_node_t;
   22192             :       typedef details::repeat_until_loop_bc_rtc_node<T>      repeat_until_loop_bc_rtc_node_t;
   22193             :       typedef details::for_loop_bc_rtc_node<T>               for_loop_bc_rtc_node_t;
   22194             :       #endif
   22195             :       typedef details::switch_node<T>                        switch_node_t;
   22196             :       typedef details::variable_node<T>                      variable_node_t;
   22197             :       typedef details::vector_elem_node<T>                   vector_elem_node_t;
   22198             :       typedef details::vector_celem_node<T>                  vector_celem_node_t;
   22199             :       typedef details::vector_elem_rtc_node<T>               vector_elem_rtc_node_t;
   22200             :       typedef details::vector_celem_rtc_node<T>              vector_celem_rtc_node_t;
   22201             :       typedef details::rebasevector_elem_node<T>             rebasevector_elem_node_t;
   22202             :       typedef details::rebasevector_celem_node<T>            rebasevector_celem_node_t;
   22203             :       typedef details::rebasevector_elem_rtc_node<T>         rebasevector_elem_rtc_node_t;
   22204             :       typedef details::rebasevector_celem_rtc_node<T>        rebasevector_celem_rtc_node_t;
   22205             :       typedef details::vector_node<T>                        vector_node_t;
   22206             :       typedef details::vector_size_node<T>                   vector_size_node_t;
   22207             :       typedef details::range_pack<T>                         range_t;
   22208             :       #ifndef exprtk_disable_string_capabilities
   22209             :       typedef details::stringvar_node<T>                     stringvar_node_t;
   22210             :       typedef details::string_literal_node<T>                string_literal_node_t;
   22211             :       typedef details::string_range_node<T>                  string_range_node_t;
   22212             :       typedef details::const_string_range_node<T>            const_string_range_node_t;
   22213             :       typedef details::generic_string_range_node<T>          generic_string_range_node_t;
   22214             :       typedef details::string_concat_node<T>                 string_concat_node_t;
   22215             :       typedef details::assignment_string_node<T>             assignment_string_node_t;
   22216             :       typedef details::assignment_string_range_node<T>       assignment_string_range_node_t;
   22217             :       typedef details::conditional_string_node<T>            conditional_string_node_t;
   22218             :       typedef details::cons_conditional_str_node<T>          cons_conditional_str_node_t;
   22219             :       #endif
   22220             :       typedef details::assignment_node<T>                    assignment_node_t;
   22221             :       typedef details::assignment_vec_elem_node<T>           assignment_vec_elem_node_t;
   22222             :       typedef details::assignment_vec_elem_rtc_node<T>       assignment_vec_elem_rtc_node_t;
   22223             :       typedef details::assignment_rebasevec_elem_node<T>     assignment_rebasevec_elem_node_t;
   22224             :       typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t;
   22225             :       typedef details::assignment_rebasevec_celem_node<T>    assignment_rebasevec_celem_node_t;
   22226             :       typedef details::assignment_vec_node<T>                assignment_vec_node_t;
   22227             :       typedef details::assignment_vecvec_node<T>             assignment_vecvec_node_t;
   22228             :       typedef details::conditional_vector_node<T>            conditional_vector_node_t;
   22229             :       typedef details::scand_node<T>                         scand_node_t;
   22230             :       typedef details::scor_node<T>                          scor_node_t;
   22231             :       typedef lexer::token                                   token_t;
   22232             :       typedef expression_node_t*                             expression_node_ptr;
   22233             :       typedef expression<T>                                  expression_t;
   22234             :       typedef symbol_table<T>                                symbol_table_t;
   22235             :       typedef typename expression<T>::symtab_list_t          symbol_table_list_t;
   22236             :       typedef details::vector_holder<T>                      vector_holder_t;
   22237             :       typedef vector_holder_t*                               vector_holder_ptr;
   22238             : 
   22239             :       typedef typename details::functor_t<T> functor_t;
   22240             :       typedef typename functor_t::qfunc_t    quaternary_functor_t;
   22241             :       typedef typename functor_t::tfunc_t    trinary_functor_t;
   22242             :       typedef typename functor_t::bfunc_t    binary_functor_t;
   22243             :       typedef typename functor_t::ufunc_t    unary_functor_t;
   22244             : 
   22245             :       typedef details::operator_type operator_t;
   22246             : 
   22247             :       typedef std::map<operator_t, unary_functor_t  > unary_op_map_t;
   22248             :       typedef std::map<operator_t, binary_functor_t > binary_op_map_t;
   22249             :       typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t;
   22250             : 
   22251             :       typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
   22252             :       typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
   22253             : 
   22254             :       typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
   22255             :       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
   22256             :       typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
   22257             : 
   22258             :       typedef details::T0oT1_define<T, cref_t , cref_t > vov_t;
   22259             :       typedef details::T0oT1_define<T, const_t, cref_t > cov_t;
   22260             :       typedef details::T0oT1_define<T, cref_t , const_t> voc_t;
   22261             : 
   22262             :       typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t;
   22263             :       typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t;
   22264             :       typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t;
   22265             :       typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t;
   22266             :       typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t;
   22267             :       typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t;
   22268             :       typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t;
   22269             : 
   22270             :       typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t;
   22271             :       typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t;
   22272             :       typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t;
   22273             :       typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t;
   22274             :       typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t;
   22275             : 
   22276             :       typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t;
   22277             :       typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t;
   22278             :       typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t;
   22279             :       typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t;
   22280             : 
   22281             :       typedef results_context<T> results_context_t;
   22282             : 
   22283             :       typedef parser_helper prsrhlpr_t;
   22284             : 
   22285             :       struct scope_element
   22286             :       {
   22287             :          enum element_type
   22288             :          {
   22289             :             e_none    ,
   22290             :             e_literal ,
   22291             :             e_variable,
   22292             :             e_vector  ,
   22293             :             e_vecelem ,
   22294             :             e_string
   22295             :          };
   22296             : 
   22297             :          typedef details::vector_holder<T> vector_holder_t;
   22298             :          typedef literal_node_t*           literal_node_ptr;
   22299             :          typedef variable_node_t*          variable_node_ptr;
   22300             :          typedef vector_holder_t*          vector_holder_ptr;
   22301             :          typedef expression_node_t*        expression_node_ptr;
   22302             :          #ifndef exprtk_disable_string_capabilities
   22303             :          typedef stringvar_node_t*         stringvar_node_ptr;
   22304             :          #endif
   22305             : 
   22306      200318 :          scope_element()
   22307      400636 :          : name("???")
   22308      200318 :          , size (std::numeric_limits<std::size_t>::max())
   22309      200318 :          , index(std::numeric_limits<std::size_t>::max())
   22310      200318 :          , depth(std::numeric_limits<std::size_t>::max())
   22311      200318 :          , ref_count(0)
   22312      200318 :          , ip_index (0)
   22313      200318 :          , type     (e_none)
   22314      200318 :          , active   (false)
   22315      200318 :          , data     (0)
   22316      200318 :          , var_node (0)
   22317      200318 :          , vec_node (0)
   22318             :          #ifndef exprtk_disable_string_capabilities
   22319      200318 :          , str_node(0)
   22320             :          #endif
   22321      200318 :          {}
   22322             : 
   22323      209277 :          bool operator < (const scope_element& se) const
   22324             :          {
   22325      209277 :             if (ip_index < se.ip_index)
   22326           2 :                return true;
   22327      209275 :             else if (ip_index > se.ip_index)
   22328        7040 :                return false;
   22329      202235 :             else if (depth < se.depth)
   22330         919 :                return true;
   22331      201316 :             else if (depth > se.depth)
   22332        6768 :                return false;
   22333      194548 :             else if (index < se.index)
   22334       15660 :                return true;
   22335      178888 :             else if (index > se.index)
   22336       41916 :                return false;
   22337             :             else
   22338      136972 :                return (name < se.name);
   22339             :          }
   22340             : 
   22341       47184 :          void clear()
   22342             :          {
   22343       47184 :             name   = "???";
   22344       47184 :             size   = std::numeric_limits<std::size_t>::max();
   22345       47184 :             index  = std::numeric_limits<std::size_t>::max();
   22346       47184 :             depth  = std::numeric_limits<std::size_t>::max();
   22347       47184 :             type   = e_none;
   22348       47184 :             active = false;
   22349       47184 :             ref_count = 0;
   22350       47184 :             ip_index  = 0;
   22351       47184 :             data      = 0;
   22352       47184 :             var_node  = 0;
   22353       47184 :             vec_node  = 0;
   22354             :             #ifndef exprtk_disable_string_capabilities
   22355       47184 :             str_node  = 0;
   22356             :             #endif
   22357       47184 :          }
   22358             : 
   22359             :          std::string  name;
   22360             :          std::size_t  size;
   22361             :          std::size_t  index;
   22362             :          std::size_t  depth;
   22363             :          std::size_t  ref_count;
   22364             :          std::size_t  ip_index;
   22365             :          element_type type;
   22366             :          bool         active;
   22367             :          void*        data;
   22368             :          expression_node_ptr var_node;
   22369             :          vector_holder_ptr   vec_node;
   22370             :          #ifndef exprtk_disable_string_capabilities
   22371             :          stringvar_node_ptr str_node;
   22372             :          #endif
   22373             :       };
   22374             : 
   22375             :       class scope_element_manager
   22376             :       {
   22377             :       public:
   22378             : 
   22379             :          typedef expression_node_t* expression_node_ptr;
   22380             :          typedef variable_node_t*   variable_node_ptr;
   22381             :          typedef parser<T>          parser_t;
   22382             : 
   22383      108660 :          explicit scope_element_manager(parser<T>& p)
   22384      108660 :          : parser_(p)
   22385      108660 :          , input_param_cnt_(0)
   22386      108660 :          {}
   22387             : 
   22388      450721 :          inline std::size_t size() const
   22389             :          {
   22390      450721 :             return element_.size();
   22391             :          }
   22392             : 
   22393      257179 :          inline bool empty() const
   22394             :          {
   22395      257179 :             return element_.empty();
   22396             :          }
   22397             : 
   22398       91562 :          inline scope_element& get_element(const std::size_t& index)
   22399             :          {
   22400       91562 :             if (index < element_.size())
   22401       91562 :                return element_[index];
   22402             :             else
   22403           0 :                return null_element_;
   22404             :          }
   22405             : 
   22406      177539 :          inline scope_element& get_element(const std::string& var_name,
   22407             :                                            const std::size_t index = std::numeric_limits<std::size_t>::max())
   22408             :          {
   22409      177539 :             const std::size_t current_depth = parser_.state_.scope_depth;
   22410             : 
   22411      350384 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22412             :             {
   22413      180047 :                scope_element& se = element_[i];
   22414             : 
   22415      180047 :                if (se.depth > current_depth)
   22416        1524 :                   continue;
   22417      178523 :                else if (
   22418      206306 :                          details::imatch(se.name, var_name) &&
   22419       27783 :                          (se.index == index)
   22420             :                        )
   22421        7202 :                   return se;
   22422             :             }
   22423             : 
   22424      170337 :             return null_element_;
   22425             :          }
   22426             : 
   22427      252592 :          inline scope_element& get_active_element(const std::string& var_name,
   22428             :                                                   const std::size_t index = std::numeric_limits<std::size_t>::max())
   22429             :          {
   22430      252592 :             const std::size_t current_depth = parser_.state_.scope_depth;
   22431             : 
   22432      439396 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22433             :             {
   22434      372947 :                scope_element& se = element_[i];
   22435             : 
   22436      372947 :                if (se.depth > current_depth)
   22437          38 :                   continue;
   22438      372909 :                else if (
   22439      372909 :                          details::imatch(se.name, var_name) &&
   22440      559292 :                          (se.index == index)                &&
   22441      186383 :                          (se.active)
   22442             :                        )
   22443      186143 :                   return se;
   22444             :             }
   22445             : 
   22446       66449 :             return null_element_;
   22447             :          }
   22448             : 
   22449       91658 :          inline bool add_element(const scope_element& se)
   22450             :          {
   22451      194164 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22452             :             {
   22453      102506 :                scope_element& cse = element_[i];
   22454             : 
   22455      102506 :                if (
   22456      102506 :                     details::imatch(cse.name, se.name) &&
   22457       22239 :                     (cse.depth <= se.depth)            &&
   22458       21319 :                     (cse.index == se.index)            &&
   22459        1120 :                     (cse.size  == se.size )            &&
   22460      124905 :                     (cse.type  == se.type )            &&
   22461         160 :                     (cse.active)
   22462             :                   )
   22463           0 :                   return false;
   22464             :             }
   22465             : 
   22466       91658 :             element_.push_back(se);
   22467       91658 :             std::sort(element_.begin(),element_.end());
   22468             : 
   22469       91658 :             return true;
   22470             :          }
   22471             : 
   22472       23679 :          inline void deactivate(const std::size_t& scope_depth)
   22473             :          {
   22474             :             exprtk_debug(("deactivate() - Scope depth: %d\n",
   22475             :                           static_cast<int>(parser_.state_.scope_depth)));
   22476             : 
   22477       74454 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22478             :             {
   22479       50775 :                scope_element& se = element_[i];
   22480             : 
   22481       50775 :                if (se.active && (se.depth >= scope_depth))
   22482             :                {
   22483             :                   exprtk_debug(("deactivate() - element[%02d] '%s'\n",
   22484             :                                 static_cast<int>(i),
   22485             :                                 se.name.c_str()));
   22486             : 
   22487       27407 :                   se.active = false;
   22488             :                }
   22489             :             }
   22490       23679 :          }
   22491             : 
   22492       47184 :          inline void free_element(scope_element& se)
   22493             :          {
   22494             :             exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
   22495             : 
   22496       47184 :             switch (se.type)
   22497             :             {
   22498        2635 :                case scope_element::e_literal    : delete reinterpret_cast<T*>(se.data);
   22499        2635 :                                                   delete se.var_node;
   22500        2635 :                                                   break;
   22501             : 
   22502       22133 :                case scope_element::e_variable   : delete reinterpret_cast<T*>(se.data);
   22503       22133 :                                                   delete se.var_node;
   22504       22133 :                                                   break;
   22505             : 
   22506       15785 :                case scope_element::e_vector     : delete[] reinterpret_cast<T*>(se.data);
   22507       15785 :                                                   delete se.vec_node;
   22508       15785 :                                                   break;
   22509             : 
   22510        5821 :                case scope_element::e_vecelem    : delete se.var_node;
   22511        5821 :                                                   break;
   22512             : 
   22513             :                #ifndef exprtk_disable_string_capabilities
   22514         810 :                case scope_element::e_string     : delete reinterpret_cast<std::string*>(se.data);
   22515         810 :                                                   delete se.str_node;
   22516         810 :                                                   break;
   22517             :                #endif
   22518             : 
   22519           0 :                default                          : return;
   22520             :             }
   22521             : 
   22522       47184 :             se.clear();
   22523             :          }
   22524             : 
   22525      391685 :          inline void cleanup()
   22526             :          {
   22527      438869 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22528             :             {
   22529       47184 :                free_element(element_[i]);
   22530             :             }
   22531             : 
   22532      391685 :             element_.clear();
   22533             : 
   22534      391685 :             input_param_cnt_ = 0;
   22535      391685 :          }
   22536             : 
   22537        2140 :          inline std::size_t next_ip_index()
   22538             :          {
   22539        2140 :             return ++input_param_cnt_;
   22540             :          }
   22541             : 
   22542         320 :          inline expression_node_ptr get_variable(const T& v)
   22543             :          {
   22544         480 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22545             :             {
   22546         480 :                scope_element& se = element_[i];
   22547             : 
   22548         480 :                if (
   22549         960 :                     se.active   &&
   22550         960 :                     se.var_node &&
   22551         480 :                     details::is_variable_node(se.var_node)
   22552             :                   )
   22553             :                {
   22554         480 :                   variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
   22555             : 
   22556         480 :                   if (&(vn->ref()) == (&v))
   22557             :                   {
   22558         320 :                      return se.var_node;
   22559             :                   }
   22560             :                }
   22561             :             }
   22562             : 
   22563           0 :             return expression_node_ptr(0);
   22564             :          }
   22565             : 
   22566         660 :          inline std::string get_vector_name(const T* data)
   22567             :          {
   22568        2603 :             for (std::size_t i = 0; i < element_.size(); ++i)
   22569             :             {
   22570        1943 :                scope_element& se = element_[i];
   22571             : 
   22572        1943 :                if (
   22573        3886 :                     se.active   &&
   22574        2521 :                     se.vec_node &&
   22575         578 :                     (se.vec_node->data() == data)
   22576             :                   )
   22577             :                {
   22578           0 :                   return se.name;
   22579             :                }
   22580             :             }
   22581             : 
   22582        1320 :             return "neo-vector";
   22583             :          }
   22584             : 
   22585             :       private:
   22586             : 
   22587             :          scope_element_manager(const scope_element_manager&) exprtk_delete;
   22588             :          scope_element_manager& operator=(const scope_element_manager&) exprtk_delete;
   22589             : 
   22590             :          parser_t& parser_;
   22591             :          std::vector<scope_element> element_;
   22592             :          scope_element null_element_;
   22593             :          std::size_t input_param_cnt_;
   22594             :       };
   22595             : 
   22596             :       class scope_handler
   22597             :       {
   22598             :       public:
   22599             : 
   22600             :          typedef parser<T> parser_t;
   22601             : 
   22602       23679 :          explicit scope_handler(parser<T>& p)
   22603       23679 :          : parser_(p)
   22604             :          {
   22605       23679 :             parser_.state_.scope_depth++;
   22606             :             #ifdef exprtk_enable_debugging
   22607             :             const std::string depth(2 * parser_.state_.scope_depth,'-');
   22608             :             exprtk_debug(("%s> Scope Depth: %02d\n",
   22609             :                           depth.c_str(),
   22610             :                           static_cast<int>(parser_.state_.scope_depth)));
   22611             :             #endif
   22612       23679 :          }
   22613             : 
   22614       23679 :         ~scope_handler()
   22615             :          {
   22616       23679 :             parser_.sem_.deactivate(parser_.state_.scope_depth);
   22617       23679 :             parser_.state_.scope_depth--;
   22618             :             #ifdef exprtk_enable_debugging
   22619             :             const std::string depth(2 * parser_.state_.scope_depth,'-');
   22620             :             exprtk_debug(("<%s Scope Depth: %02d\n",
   22621             :                           depth.c_str(),
   22622             :                           static_cast<int>(parser_.state_.scope_depth)));
   22623             :             #endif
   22624       23679 :          }
   22625             : 
   22626             :       private:
   22627             : 
   22628             :          scope_handler(const scope_handler&) exprtk_delete;
   22629             :          scope_handler& operator=(const scope_handler&) exprtk_delete;
   22630             : 
   22631             :          parser_t& parser_;
   22632             :       };
   22633             : 
   22634             :       template <typename T_>
   22635             :       struct halfopen_range_policy
   22636             :       {
   22637          51 :          static inline bool is_within(const T_& v, const T_& begin, const T_& end)
   22638             :          {
   22639          51 :             assert(begin <= end);
   22640          51 :             return (begin <= v) && (v < end);
   22641             :          }
   22642             : 
   22643             :          static inline bool is_less(const T_& v, const T_& begin)
   22644             :          {
   22645             :             return (v < begin);
   22646             :          }
   22647             : 
   22648          20 :          static inline bool is_greater(const T_& v, const T_& end)
   22649             :          {
   22650          20 :             return (end <= v);
   22651             :          }
   22652             : 
   22653       76789 :          static inline bool end_inclusive()
   22654             :          {
   22655       76789 :             return false;
   22656             :          }
   22657             :       };
   22658             : 
   22659             :       template <typename T_>
   22660             :       struct closed_range_policy
   22661             :       {
   22662             :          static inline bool is_within(const T_& v, const T_& begin, const T_& end)
   22663             :          {
   22664             :             assert(begin <= end);
   22665             :             return (begin <= v) && (v <= end);
   22666             :          }
   22667             : 
   22668             :          static inline bool is_less(const T_& v, const T_& begin)
   22669             :          {
   22670             :             return (v < begin);
   22671             :          }
   22672             : 
   22673             :          static inline bool is_greater(const T_& v, const T_& end)
   22674             :          {
   22675             :             return (end < v);
   22676             :          }
   22677             : 
   22678             :          static inline bool end_inclusive()
   22679             :          {
   22680             :             return true;
   22681             :          }
   22682             :       };
   22683             : 
   22684             :       template <typename IntervalPointType,
   22685             :                 typename RangePolicy = halfopen_range_policy<IntervalPointType> >
   22686             :       class interval_container_t
   22687             :       {
   22688             :       public:
   22689             : 
   22690             :          typedef IntervalPointType interval_point_t;
   22691             :          typedef std::pair<interval_point_t, interval_point_t> interval_t;
   22692             :          typedef std::map<interval_point_t, interval_t> interval_map_t;
   22693             :          typedef typename interval_map_t::const_iterator interval_map_citr_t;
   22694             : 
   22695             :          std::size_t size() const
   22696             :          {
   22697             :             return interval_map_.size();
   22698             :          }
   22699             : 
   22700      380686 :          void reset()
   22701             :          {
   22702      380686 :             interval_map_.clear();
   22703      380686 :          }
   22704             : 
   22705       76789 :          bool in_interval(const interval_point_t point, interval_t& interval) const
   22706             :          {
   22707       76789 :             interval_map_citr_t itr = RangePolicy::end_inclusive() ?
   22708           0 :                                       interval_map_.lower_bound(point):
   22709       76789 :                                       interval_map_.upper_bound(point);
   22710             : 
   22711       76809 :             for (; itr != interval_map_.end(); ++itr)
   22712             :             {
   22713          51 :                const interval_point_t& begin = itr->second.first;
   22714          51 :                const interval_point_t& end   = itr->second.second;
   22715             : 
   22716          51 :                if (RangePolicy::is_within(point, begin, end))
   22717             :                {
   22718          31 :                   interval = interval_t(begin,end);
   22719          31 :                   return true;
   22720             :                }
   22721          20 :                else if (RangePolicy::is_greater(point, end))
   22722             :                {
   22723           0 :                   break;
   22724             :                }
   22725             :             }
   22726             : 
   22727       76758 :             return false;
   22728             :          }
   22729             : 
   22730         107 :          bool in_interval(const interval_point_t point) const
   22731             :          {
   22732         107 :             interval_t interval;
   22733         214 :             return in_interval(point,interval);
   22734             :          }
   22735             : 
   22736          55 :          bool add_interval(const interval_point_t begin, const interval_point_t end)
   22737             :          {
   22738          55 :             if ((end <= begin) || in_interval(begin) || in_interval(end))
   22739             :             {
   22740           3 :                return false;
   22741             :             }
   22742             : 
   22743          52 :             interval_map_[end] = std::make_pair(begin, end);
   22744             : 
   22745          52 :             return true;
   22746             :          }
   22747             : 
   22748          55 :          bool add_interval(const interval_t interval)
   22749             :          {
   22750          55 :             return add_interval(interval.first, interval.second);
   22751             :          }
   22752             : 
   22753             :       private:
   22754             : 
   22755             :          interval_map_t interval_map_;
   22756             :       };
   22757             : 
   22758             :       class stack_limit_handler
   22759             :       {
   22760             :       public:
   22761             : 
   22762             :          typedef parser<T> parser_t;
   22763             : 
   22764    12693582 :          explicit stack_limit_handler(parser<T>& p)
   22765    12693582 :          : parser_(p)
   22766    12693582 :          , limit_exceeded_(false)
   22767             :          {
   22768    12693582 :             if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
   22769             :             {
   22770           0 :                limit_exceeded_ = true;
   22771           0 :                parser_.set_error(make_error(
   22772             :                   parser_error::e_parser,
   22773           0 :                   "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
   22774           0 :                   " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
   22775             :                   exprtk_error_location));
   22776             :             }
   22777    12693582 :          }
   22778             : 
   22779    12693582 :         ~stack_limit_handler()
   22780             :          {
   22781    12693582 :             assert(parser_.state_.stack_depth > 0);
   22782    12693582 :             parser_.state_.stack_depth--;
   22783    12693582 :          }
   22784             : 
   22785    12693582 :          bool operator!()
   22786             :          {
   22787    12693582 :             return limit_exceeded_;
   22788             :          }
   22789             : 
   22790             :       private:
   22791             : 
   22792             :          stack_limit_handler(const stack_limit_handler&) exprtk_delete;
   22793             :          stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete;
   22794             : 
   22795             :          parser_t& parser_;
   22796             :          bool limit_exceeded_;
   22797             :       };
   22798             : 
   22799             :       struct symtab_store
   22800             :       {
   22801             :          symbol_table_list_t symtab_list_;
   22802             : 
   22803             :          typedef typename symbol_table_t::local_data_t local_data_t;
   22804             :          typedef typename symbol_table_t::variable_ptr variable_ptr;
   22805             :          typedef typename symbol_table_t::function_ptr function_ptr;
   22806             :          #ifndef exprtk_disable_string_capabilities
   22807             :          typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
   22808             :          #endif
   22809             :          typedef typename symbol_table_t::vector_holder_ptr    vector_holder_ptr;
   22810             :          typedef typename symbol_table_t::vararg_function_ptr  vararg_function_ptr;
   22811             :          typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
   22812             : 
   22813             :          struct variable_context
   22814             :          {
   22815     2057676 :             variable_context()
   22816     2057676 :             : symbol_table(0)
   22817     2057676 :             , variable(0)
   22818     2057676 :             {}
   22819             : 
   22820             :             const symbol_table_t* symbol_table;
   22821             :             variable_ptr variable;
   22822             :          };
   22823             : 
   22824             :          struct vector_context
   22825             :          {
   22826        6869 :             vector_context()
   22827        6869 :             : symbol_table(0)
   22828        6869 :             , vector_holder(0)
   22829        6869 :             {}
   22830             : 
   22831             :             const symbol_table_t* symbol_table;
   22832             :             vector_holder_ptr vector_holder;
   22833             :          };
   22834             : 
   22835             :          #ifndef exprtk_disable_string_capabilities
   22836             :          struct string_context
   22837             :          {
   22838       49475 :             string_context()
   22839       49475 :             : symbol_table(0)
   22840       49475 :             , str_var(0)
   22841       49475 :             {}
   22842             : 
   22843             :             const symbol_table_t* symbol_table;
   22844             :             stringvar_ptr str_var;
   22845             :          };
   22846             :          #endif
   22847             : 
   22848     2055564 :          inline bool empty() const
   22849             :          {
   22850     2055564 :             return symtab_list_.empty();
   22851             :          }
   22852             : 
   22853             :          inline void clear()
   22854             :          {
   22855             :             symtab_list_.clear();
   22856             :          }
   22857             : 
   22858     2055564 :          inline bool valid() const
   22859             :          {
   22860     2055564 :             if (!empty())
   22861             :             {
   22862     2055396 :                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22863             :                {
   22864     2055396 :                   if (symtab_list_[i].valid())
   22865     2055396 :                      return true;
   22866             :                }
   22867             :             }
   22868             : 
   22869         168 :             return false;
   22870             :          }
   22871             : 
   22872     3970164 :          inline bool valid_symbol(const std::string& symbol) const
   22873             :          {
   22874     3970164 :             if (!symtab_list_.empty())
   22875     3970090 :                return symtab_list_[0].valid_symbol(symbol);
   22876             :             else
   22877          74 :                return false;
   22878             :          }
   22879             : 
   22880      185503 :          inline bool valid_function_name(const std::string& symbol) const
   22881             :          {
   22882      185503 :             if (!symtab_list_.empty())
   22883      185443 :                return symtab_list_[0].valid_function(symbol);
   22884             :             else
   22885          60 :                return false;
   22886             :          }
   22887             : 
   22888     2057676 :          inline variable_context get_variable_context(const std::string& variable_name) const
   22889             :          {
   22890     2057676 :             variable_context result;
   22891             : 
   22892     2057676 :             if (valid_symbol(variable_name))
   22893             :             {
   22894     2377584 :                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22895             :                {
   22896     2123070 :                   if (!symtab_list_[i].valid())
   22897             :                   {
   22898           0 :                      continue;
   22899             :                   }
   22900             : 
   22901     2123070 :                   result.variable = local_data(i)
   22902     2123070 :                                        .variable_store.get(variable_name);
   22903     2123070 :                   if (result.variable)
   22904             :                   {
   22905     1800665 :                      result.symbol_table = &symtab_list_[i];
   22906     1800665 :                      break;
   22907             :                   }
   22908             :                }
   22909             :             }
   22910             : 
   22911     2057676 :             return result;
   22912             :          }
   22913             : 
   22914        3002 :          inline variable_ptr get_variable(const std::string& variable_name) const
   22915             :          {
   22916        3002 :             if (!valid_symbol(variable_name))
   22917           0 :                return reinterpret_cast<variable_ptr>(0);
   22918             : 
   22919        3002 :             variable_ptr result = reinterpret_cast<variable_ptr>(0);
   22920             : 
   22921        3002 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22922             :             {
   22923        3002 :                if (!symtab_list_[i].valid())
   22924           0 :                   continue;
   22925             :                else
   22926        3002 :                   result = local_data(i)
   22927        3002 :                               .variable_store.get(variable_name);
   22928             : 
   22929        3002 :                if (result) break;
   22930             :             }
   22931             : 
   22932        3002 :             return result;
   22933             :          }
   22934             : 
   22935         320 :          inline variable_ptr get_variable(const T& var_ref) const
   22936             :          {
   22937         320 :             variable_ptr result = reinterpret_cast<variable_ptr>(0);
   22938             : 
   22939         640 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22940             :             {
   22941         320 :                if (!symtab_list_[i].valid())
   22942           0 :                   continue;
   22943             :                else
   22944         320 :                   result = local_data(i).variable_store
   22945         320 :                               .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
   22946             : 
   22947         320 :                if (result) break;
   22948             :             }
   22949             : 
   22950         320 :             return result;
   22951             :          }
   22952             : 
   22953             :          #ifndef exprtk_disable_string_capabilities
   22954       49475 :          inline string_context get_string_context(const std::string& string_name) const
   22955             :          {
   22956       49475 :             string_context result;
   22957             : 
   22958       49475 :             if (!valid_symbol(string_name))
   22959           0 :                return result;
   22960             : 
   22961       49475 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22962             :             {
   22963       49475 :                if (!symtab_list_[i].valid())
   22964             :                {
   22965           0 :                   continue;
   22966             :                }
   22967             : 
   22968       49475 :                result.str_var = local_data(i).stringvar_store.get(string_name);
   22969             : 
   22970       49475 :                if (result.str_var)
   22971             :                {
   22972       49475 :                   result.symbol_table = &symtab_list_[i];
   22973       49475 :                   break;
   22974             :                }
   22975             :             }
   22976             : 
   22977       49475 :             return result;
   22978             :          }
   22979             : 
   22980             :          inline stringvar_ptr get_stringvar(const std::string& string_name) const
   22981             :          {
   22982             :             if (!valid_symbol(string_name))
   22983             :                return reinterpret_cast<stringvar_ptr>(0);
   22984             : 
   22985             :             stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
   22986             : 
   22987             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22988             :             {
   22989             :                if (!symtab_list_[i].valid())
   22990             :                   continue;
   22991             :                else
   22992             :                   result = local_data(i)
   22993             :                               .stringvar_store.get(string_name);
   22994             : 
   22995             :                if (result) break;
   22996             :             }
   22997             : 
   22998             :             return result;
   22999             :          }
   23000             :          #endif
   23001             : 
   23002       87026 :          inline function_ptr get_function(const std::string& function_name) const
   23003             :          {
   23004       87026 :             if (!valid_function_name(function_name))
   23005          35 :                return reinterpret_cast<function_ptr>(0);
   23006             : 
   23007       86991 :             function_ptr result = reinterpret_cast<function_ptr>(0);
   23008             : 
   23009      131404 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23010             :             {
   23011      105024 :                if (!symtab_list_[i].valid())
   23012           0 :                   continue;
   23013             :                else
   23014      105024 :                   result = local_data(i)
   23015      105024 :                               .function_store.get(function_name);
   23016             : 
   23017      105024 :                if (result) break;
   23018             :             }
   23019             : 
   23020       86991 :             return result;
   23021             :          }
   23022             : 
   23023       26415 :          inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
   23024             :          {
   23025       26415 :             if (!valid_function_name(vararg_function_name))
   23026          35 :                return reinterpret_cast<vararg_function_ptr>(0);
   23027             : 
   23028       26380 :             vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
   23029             : 
   23030       68344 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23031             :             {
   23032       42013 :                if (!symtab_list_[i].valid())
   23033           0 :                   continue;
   23034             :                else
   23035       42013 :                   result = local_data(i)
   23036       42013 :                               .vararg_function_store.get(vararg_function_name);
   23037             : 
   23038       42013 :                if (result) break;
   23039             :             }
   23040             : 
   23041       26380 :             return result;
   23042             :          }
   23043             : 
   23044       26366 :          inline generic_function_ptr get_generic_function(const std::string& function_name) const
   23045             :          {
   23046       26366 :             if (!valid_function_name(function_name))
   23047          35 :                return reinterpret_cast<generic_function_ptr>(0);
   23048             : 
   23049       26331 :             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
   23050             : 
   23051       64795 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23052             :             {
   23053       41964 :                if (!symtab_list_[i].valid())
   23054           0 :                   continue;
   23055             :                else
   23056       41964 :                   result = local_data(i)
   23057       41964 :                               .generic_function_store.get(function_name);
   23058             : 
   23059       41964 :                if (result) break;
   23060             :             }
   23061             : 
   23062       26331 :             return result;
   23063             :          }
   23064             : 
   23065       22866 :          inline generic_function_ptr get_string_function(const std::string& function_name) const
   23066             :          {
   23067       22866 :             if (!valid_function_name(function_name))
   23068          35 :                return reinterpret_cast<generic_function_ptr>(0);
   23069             : 
   23070       22831 :             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
   23071             : 
   23072       61259 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23073             :             {
   23074       38464 :                if (!symtab_list_[i].valid())
   23075           0 :                   continue;
   23076             :                else
   23077             :                   result =
   23078       38464 :                      local_data(i).string_function_store.get(function_name);
   23079             : 
   23080       38464 :                if (result) break;
   23081             :             }
   23082             : 
   23083       22831 :             return result;
   23084             :          }
   23085             : 
   23086       22830 :          inline generic_function_ptr get_overload_function(const std::string& function_name) const
   23087             :          {
   23088       22830 :             if (!valid_function_name(function_name))
   23089          35 :                return reinterpret_cast<generic_function_ptr>(0);
   23090             : 
   23091       22795 :             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
   23092             : 
   23093       61151 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23094             :             {
   23095       38428 :                if (!symtab_list_[i].valid())
   23096           0 :                   continue;
   23097             :                else
   23098             :                   result =
   23099       38428 :                      local_data(i).overload_function_store.get(function_name);
   23100             : 
   23101       38428 :                if (result) break;
   23102             :             }
   23103             : 
   23104       22795 :             return result;
   23105             :          }
   23106             : 
   23107        6869 :          inline vector_context get_vector_context(const std::string& vector_name) const
   23108             :          {
   23109        6869 :             vector_context result;
   23110        6869 :             if (!valid_symbol(vector_name))
   23111           0 :                return result;
   23112             : 
   23113        6869 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23114             :             {
   23115        6869 :                if (!symtab_list_[i].valid())
   23116             :                {
   23117           0 :                   continue;
   23118             :                }
   23119             : 
   23120        6869 :                result.vector_holder = local_data(i).vector_store.get(vector_name);
   23121             : 
   23122        6869 :                if (result.vector_holder)
   23123             :                {
   23124        6869 :                   result.symbol_table = &symtab_list_[i];
   23125        6869 :                   break;
   23126             :                }
   23127             :             }
   23128             : 
   23129        6869 :             return result;
   23130             :          }
   23131             : 
   23132             :          inline vector_holder_ptr get_vector(const std::string& vector_name) const
   23133             :          {
   23134             :             if (!valid_symbol(vector_name))
   23135             :                return reinterpret_cast<vector_holder_ptr>(0);
   23136             : 
   23137             :             vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
   23138             : 
   23139             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23140             :             {
   23141             :                if (!symtab_list_[i].valid())
   23142             :                {
   23143             :                   continue;
   23144             :                }
   23145             : 
   23146             :                result = local_data(i).vector_store.get(vector_name);
   23147             : 
   23148             :                if (result)
   23149             :                {
   23150             :                   break;
   23151             :                }
   23152             :             }
   23153             : 
   23154             :             return result;
   23155             :          }
   23156             : 
   23157     1803667 :          inline bool is_constant_node(const std::string& symbol_name) const
   23158             :          {
   23159     1803667 :             if (!valid_symbol(symbol_name))
   23160           0 :                return false;
   23161             : 
   23162     3665513 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23163             :             {
   23164     1906596 :                if (!symtab_list_[i].valid())
   23165             :                {
   23166           0 :                   continue;
   23167             :                }
   23168             : 
   23169     1906596 :                if (local_data(i).variable_store.is_constant(symbol_name))
   23170             :                {
   23171       44750 :                   return true;
   23172             :                }
   23173             :             }
   23174             : 
   23175     1758917 :             return false;
   23176             :          }
   23177             : 
   23178             :          #ifndef exprtk_disable_string_capabilities
   23179       49475 :          inline bool is_constant_string(const std::string& symbol_name) const
   23180             :          {
   23181       49475 :             if (!valid_symbol(symbol_name))
   23182           0 :                return false;
   23183             : 
   23184       98974 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23185             :             {
   23186       49499 :                if (!symtab_list_[i].valid())
   23187           0 :                   continue;
   23188       49499 :                else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
   23189          24 :                   continue;
   23190       49475 :                else if (local_data(i).stringvar_store.is_constant(symbol_name))
   23191           0 :                   return true;
   23192             :             }
   23193             : 
   23194       49475 :             return false;
   23195             :          }
   23196             :          #endif
   23197             : 
   23198       82250 :          inline bool symbol_exists(const std::string& symbol) const
   23199             :          {
   23200      164443 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23201             :             {
   23202       82193 :                if (!symtab_list_[i].valid())
   23203             :                {
   23204           0 :                   continue;
   23205             :                }
   23206             : 
   23207       82193 :                if (symtab_list_[i].symbol_exists(symbol))
   23208             :                {
   23209           0 :                   return true;
   23210             :                }
   23211             :             }
   23212             : 
   23213       82250 :             return false;
   23214             :          }
   23215             : 
   23216         400 :          inline bool is_variable(const std::string& variable_name) const
   23217             :          {
   23218         800 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23219             :             {
   23220         400 :                if (!symtab_list_[i].valid())
   23221           0 :                   continue;
   23222         400 :                else if (
   23223         400 :                          symtab_list_[i].local_data().variable_store
   23224         400 :                            .symbol_exists(variable_name)
   23225             :                        )
   23226           0 :                   return true;
   23227             :             }
   23228             : 
   23229         400 :             return false;
   23230             :          }
   23231             : 
   23232             :          #ifndef exprtk_disable_string_capabilities
   23233      136501 :          inline bool is_stringvar(const std::string& stringvar_name) const
   23234             :          {
   23235      245748 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23236             :             {
   23237      158722 :                if (!symtab_list_[i].valid())
   23238           0 :                   continue;
   23239      158722 :                else if (
   23240      158722 :                          symtab_list_[i].local_data().stringvar_store
   23241      158722 :                            .symbol_exists(stringvar_name)
   23242             :                        )
   23243       49475 :                   return true;
   23244             :             }
   23245             : 
   23246       87026 :             return false;
   23247             :          }
   23248             : 
   23249       49475 :          inline bool is_conststr_stringvar(const std::string& symbol_name) const
   23250             :          {
   23251       49475 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23252             :             {
   23253       49475 :                if (!symtab_list_[i].valid())
   23254           0 :                   continue;
   23255       49475 :                else if (
   23256       49475 :                          symtab_list_[i].local_data().stringvar_store
   23257       49475 :                            .symbol_exists(symbol_name)
   23258             :                        )
   23259             :                {
   23260             :                   return (
   23261       49475 :                            local_data(i).stringvar_store.symbol_exists(symbol_name) ||
   23262           0 :                            local_data(i).stringvar_store.is_constant  (symbol_name)
   23263       49475 :                          );
   23264             : 
   23265             :                }
   23266             :             }
   23267             : 
   23268           0 :             return false;
   23269             :          }
   23270             :          #endif
   23271             : 
   23272             :          inline bool is_function(const std::string& function_name) const
   23273             :          {
   23274             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23275             :             {
   23276             :                if (!symtab_list_[i].valid())
   23277             :                   continue;
   23278             :                else if (
   23279             :                          local_data(i).vararg_function_store
   23280             :                            .symbol_exists(function_name)
   23281             :                        )
   23282             :                   return true;
   23283             :             }
   23284             : 
   23285             :             return false;
   23286             :          }
   23287             : 
   23288             :          inline bool is_vararg_function(const std::string& vararg_function_name) const
   23289             :          {
   23290             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23291             :             {
   23292             :                if (!symtab_list_[i].valid())
   23293             :                   continue;
   23294             :                else if (
   23295             :                          local_data(i).vararg_function_store
   23296             :                            .symbol_exists(vararg_function_name)
   23297             :                        )
   23298             :                   return true;
   23299             :             }
   23300             : 
   23301             :             return false;
   23302             :          }
   23303             : 
   23304       22838 :          inline bool is_vector(const std::string& vector_name) const
   23305             :          {
   23306       54403 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   23307             :             {
   23308       38434 :                if (!symtab_list_[i].valid())
   23309           0 :                   continue;
   23310       38434 :                else if (
   23311       38434 :                          local_data(i).vector_store
   23312       38434 :                            .symbol_exists(vector_name)
   23313             :                        )
   23314        6869 :                   return true;
   23315             :             }
   23316             : 
   23317       15969 :             return false;
   23318             :          }
   23319             : 
   23320           3 :          inline std::string get_variable_name(const expression_node_ptr& ptr) const
   23321             :          {
   23322           6 :             return local_data().variable_store.entity_name(ptr);
   23323             :          }
   23324             : 
   23325           0 :          inline std::string get_vector_name(const vector_holder_ptr& ptr) const
   23326             :          {
   23327           0 :             return local_data().vector_store.entity_name(ptr);
   23328             :          }
   23329             : 
   23330             :          #ifndef exprtk_disable_string_capabilities
   23331           1 :          inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
   23332             :          {
   23333           2 :             return local_data().stringvar_store.entity_name(ptr);
   23334             :          }
   23335             : 
   23336             :          inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
   23337             :          {
   23338             :             return local_data().stringvar_store.entity_name(ptr);
   23339             :          }
   23340             :          #endif
   23341             : 
   23342             :          inline local_data_t& local_data(const std::size_t& index = 0)
   23343             :          {
   23344             :             return symtab_list_[index].local_data();
   23345             :          }
   23346             : 
   23347           8 :          inline const local_data_t& local_data(const std::size_t& index = 0) const
   23348             :          {
   23349     4542112 :             return symtab_list_[index].local_data();
   23350             :          }
   23351             : 
   23352       15624 :          inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
   23353             :          {
   23354        5208 :             return symtab_list_[index];
   23355             :          }
   23356             :       };
   23357             : 
   23358             :       struct parser_state
   23359             :       {
   23360      108660 :          parser_state()
   23361      108660 :          : type_check_enabled(true)
   23362             :          {
   23363      108660 :             reset();
   23364      108660 :          }
   23365             : 
   23366      489346 :          void reset()
   23367             :          {
   23368      489346 :             parsing_return_stmt     = false;
   23369      489346 :             parsing_break_stmt      = false;
   23370      489346 :             parsing_assert_stmt     = false;
   23371      489346 :             return_stmt_present     = false;
   23372      489346 :             side_effect_present     = false;
   23373      489346 :             scope_depth             = 0;
   23374      489346 :             stack_depth             = 0;
   23375      489346 :             parsing_loop_stmt_count = 0;
   23376      489346 :          }
   23377             : 
   23378             :          #ifndef exprtk_enable_debugging
   23379      280926 :          void activate_side_effect(const std::string&)
   23380             :          #else
   23381             :          void activate_side_effect(const std::string& source)
   23382             :          #endif
   23383             :          {
   23384      280926 :             if (!side_effect_present)
   23385             :             {
   23386      163728 :                side_effect_present = true;
   23387             : 
   23388             :                exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str()));
   23389             :             }
   23390      280926 :          }
   23391             : 
   23392             :          bool parsing_return_stmt;
   23393             :          bool parsing_break_stmt;
   23394             :          bool parsing_assert_stmt;
   23395             :          bool return_stmt_present;
   23396             :          bool side_effect_present;
   23397             :          bool type_check_enabled;
   23398             :          std::size_t scope_depth;
   23399             :          std::size_t stack_depth;
   23400             :          std::size_t parsing_loop_stmt_count;
   23401             :       };
   23402             : 
   23403             :    public:
   23404             : 
   23405             :       struct unknown_symbol_resolver
   23406             :       {
   23407             : 
   23408             :          enum usr_symbol_type
   23409             :          {
   23410             :             e_usr_unknown_type  = 0,
   23411             :             e_usr_variable_type = 1,
   23412             :             e_usr_constant_type = 2
   23413             :          };
   23414             : 
   23415             :          enum usr_mode
   23416             :          {
   23417             :             e_usrmode_default  = 0,
   23418             :             e_usrmode_extended = 1
   23419             :          };
   23420             : 
   23421             :          usr_mode mode;
   23422             : 
   23423      108864 :          unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
   23424      108864 :          : mode(m)
   23425      108864 :          {}
   23426             : 
   23427      108864 :          virtual ~unknown_symbol_resolver()
   23428      108864 :          {}
   23429             : 
   23430           2 :          virtual bool process(const std::string& /*unknown_symbol*/,
   23431             :                               usr_symbol_type&   st,
   23432             :                               T&                 default_value,
   23433             :                               std::string&       error_message)
   23434             :          {
   23435           2 :             if (e_usrmode_default != mode)
   23436           0 :                return false;
   23437             : 
   23438           2 :             st = e_usr_variable_type;
   23439           2 :             default_value = T(0);
   23440           2 :             error_message.clear();
   23441             : 
   23442           2 :             return true;
   23443             :          }
   23444             : 
   23445           0 :          virtual bool process(const std::string& /* unknown_symbol */,
   23446             :                               symbol_table_t&    /* symbol_table   */,
   23447             :                               std::string&       /* error_message  */)
   23448             :          {
   23449           0 :             return false;
   23450             :          }
   23451             :       };
   23452             : 
   23453             :       enum collect_type
   23454             :       {
   23455             :          e_ct_none        = 0,
   23456             :          e_ct_variables   = 1,
   23457             :          e_ct_functions   = 2,
   23458             :          e_ct_assignments = 4
   23459             :       };
   23460             : 
   23461             :       enum symbol_type
   23462             :       {
   23463             :          e_st_unknown        = 0,
   23464             :          e_st_variable       = 1,
   23465             :          e_st_vector         = 2,
   23466             :          e_st_vecelem        = 3,
   23467             :          e_st_string         = 4,
   23468             :          e_st_function       = 5,
   23469             :          e_st_local_variable = 6,
   23470             :          e_st_local_vector   = 7,
   23471             :          e_st_local_string   = 8
   23472             :       };
   23473             : 
   23474             :       class dependent_entity_collector
   23475             :       {
   23476             :       public:
   23477             : 
   23478             :          typedef std::pair<std::string,symbol_type> symbol_t;
   23479             :          typedef std::vector<symbol_t> symbol_list_t;
   23480             : 
   23481      108660 :          dependent_entity_collector(const std::size_t options = e_ct_none)
   23482      108660 :          : options_(options)
   23483      108660 :          , collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  )
   23484      108660 :          , collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  )
   23485      108660 :          , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments)
   23486      108660 :          , return_present_   (false)
   23487      108660 :          , final_stmt_return_(false)
   23488      108660 :          {}
   23489             : 
   23490             :          template <typename Allocator,
   23491             :                    template <typename, typename> class Sequence>
   23492           3 :          inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
   23493             :          {
   23494           3 :             if (!collect_variables_ && !collect_functions_)
   23495           0 :                return 0;
   23496           3 :             else if (symbol_name_list_.empty())
   23497           0 :                return 0;
   23498             : 
   23499          23 :             for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
   23500             :             {
   23501          20 :                details::case_normalise(symbol_name_list_[i].first);
   23502             :             }
   23503             : 
   23504           3 :             std::sort(symbol_name_list_.begin(), symbol_name_list_.end());
   23505             : 
   23506             :             std::unique_copy
   23507           3 :             (
   23508             :                symbol_name_list_.begin(),
   23509             :                symbol_name_list_.end  (),
   23510             :                std::back_inserter(symbols_list)
   23511             :             );
   23512             : 
   23513           3 :             return symbols_list.size();
   23514             :          }
   23515             : 
   23516             :          template <typename Allocator,
   23517             :                    template <typename, typename> class Sequence>
   23518           1 :          inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
   23519             :          {
   23520           1 :             if (!collect_assignments_)
   23521           0 :                return 0;
   23522           1 :             else if (assignment_name_list_.empty())
   23523           0 :                return 0;
   23524             : 
   23525           5 :             for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
   23526             :             {
   23527           4 :                details::case_normalise(assignment_name_list_[i].first);
   23528             :             }
   23529             : 
   23530           1 :             std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
   23531             : 
   23532             :             std::unique_copy
   23533           1 :             (
   23534             :                assignment_name_list_.begin(),
   23535             :                assignment_name_list_.end  (),
   23536             :                std::back_inserter(assignment_list)
   23537             :             );
   23538             : 
   23539           1 :             return assignment_list.size();
   23540             :          }
   23541             : 
   23542      381157 :          void clear()
   23543             :          {
   23544      381157 :             symbol_name_list_    .clear();
   23545      381157 :             assignment_name_list_.clear();
   23546      381157 :             retparam_list_       .clear();
   23547      381157 :             return_present_    = false;
   23548      381157 :             final_stmt_return_ = false;
   23549      381157 :          }
   23550             : 
   23551      108663 :          bool& collect_variables()
   23552             :          {
   23553      108663 :             return collect_variables_;
   23554             :          }
   23555             : 
   23556      108663 :          bool& collect_functions()
   23557             :          {
   23558      108663 :             return collect_functions_;
   23559             :          }
   23560             : 
   23561      185315 :          bool& collect_assignments()
   23562             :          {
   23563      185315 :             return collect_assignments_;
   23564             :          }
   23565             : 
   23566        1484 :          bool return_present() const
   23567             :          {
   23568        1484 :             return return_present_;
   23569             :          }
   23570             : 
   23571             :          bool final_stmt_return() const
   23572             :          {
   23573             :             return final_stmt_return_;
   23574             :          }
   23575             : 
   23576             :          typedef std::vector<std::string> retparam_list_t;
   23577             : 
   23578           0 :          retparam_list_t return_param_type_list() const
   23579             :          {
   23580           0 :             return retparam_list_;
   23581             :          }
   23582             : 
   23583             :       private:
   23584             : 
   23585     2427545 :          inline void add_symbol(const std::string& symbol, const symbol_type st)
   23586             :          {
   23587     2427545 :             switch (st)
   23588             :             {
   23589     2017783 :                case e_st_variable       :
   23590             :                case e_st_vector         :
   23591             :                case e_st_string         :
   23592             :                case e_st_local_variable :
   23593             :                case e_st_local_vector   :
   23594     2017783 :                case e_st_local_string   : if (collect_variables_)
   23595             :                                              symbol_name_list_
   23596          19 :                                                 .push_back(std::make_pair(symbol, st));
   23597     2017783 :                                           break;
   23598             : 
   23599      409762 :                case e_st_function       : if (collect_functions_)
   23600             :                                              symbol_name_list_
   23601           5 :                                                 .push_back(std::make_pair(symbol, st));
   23602      409762 :                                           break;
   23603             : 
   23604           0 :                default                  : return;
   23605             :             }
   23606             :          }
   23607             : 
   23608           4 :          inline void add_assignment(const std::string& symbol, const symbol_type st)
   23609             :          {
   23610           4 :             switch (st)
   23611             :             {
   23612           4 :                case e_st_variable       :
   23613             :                case e_st_vector         :
   23614           4 :                case e_st_string         : if (collect_assignments_)
   23615             :                                              assignment_name_list_
   23616           4 :                                                 .push_back(std::make_pair(symbol, st));
   23617           4 :                                           break;
   23618             : 
   23619           0 :                default                  : return;
   23620             :             }
   23621             :          }
   23622             : 
   23623             :          std::size_t options_;
   23624             :          bool collect_variables_;
   23625             :          bool collect_functions_;
   23626             :          bool collect_assignments_;
   23627             :          bool return_present_;
   23628             :          bool final_stmt_return_;
   23629             :          symbol_list_t symbol_name_list_;
   23630             :          symbol_list_t assignment_name_list_;
   23631             :          retparam_list_t retparam_list_;
   23632             : 
   23633             :          friend class parser<T>;
   23634             :       };
   23635             : 
   23636             :       class settings_store
   23637             :       {
   23638             :       private:
   23639             : 
   23640             :          typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
   23641             :          typedef disabled_entity_set_t::iterator des_itr_t;
   23642             : 
   23643             :       public:
   23644             : 
   23645             :          enum settings_compilation_options
   23646             :          {
   23647             :             e_unknown              =    0,
   23648             :             e_replacer             =    1,
   23649             :             e_joiner               =    2,
   23650             :             e_numeric_check        =    4,
   23651             :             e_bracket_check        =    8,
   23652             :             e_sequence_check       =   16,
   23653             :             e_commutative_check    =   32,
   23654             :             e_strength_reduction   =   64,
   23655             :             e_disable_vardef       =  128,
   23656             :             e_collect_vars         =  256,
   23657             :             e_collect_funcs        =  512,
   23658             :             e_collect_assings      = 1024,
   23659             :             e_disable_usr_on_rsrvd = 2048,
   23660             :             e_disable_zero_return  = 4096
   23661             :          };
   23662             : 
   23663             :          enum settings_base_funcs
   23664             :          {
   23665             :             e_bf_unknown = 0,
   23666             :             e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin    ,
   23667             :             e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh   ,
   23668             :             e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos     ,
   23669             :             e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal   ,
   23670             :             e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1   ,
   23671             :             e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp  ,
   23672             :             e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p   ,
   23673             :             e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max     ,
   23674             :             e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul     ,
   23675             :             e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round   ,
   23676             :             e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin     ,
   23677             :             e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum     ,
   23678             :             e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc   ,
   23679             :             e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad ,
   23680             :             e_bf_rad2deg   , e_bf_grad2deg
   23681             :          };
   23682             : 
   23683             :          enum settings_control_structs
   23684             :          {
   23685             :             e_ctrl_unknown = 0,
   23686             :             e_ctrl_ifelse,
   23687             :             e_ctrl_switch,
   23688             :             e_ctrl_for_loop,
   23689             :             e_ctrl_while_loop,
   23690             :             e_ctrl_repeat_loop,
   23691             :             e_ctrl_return
   23692             :          };
   23693             : 
   23694             :          enum settings_logic_opr
   23695             :          {
   23696             :             e_logic_unknown = 0,
   23697             :             e_logic_and, e_logic_nand , e_logic_nor ,
   23698             :             e_logic_not, e_logic_or   , e_logic_xnor,
   23699             :             e_logic_xor, e_logic_scand, e_logic_scor
   23700             :          };
   23701             : 
   23702             :          enum settings_arithmetic_opr
   23703             :          {
   23704             :             e_arith_unknown = 0,
   23705             :             e_arith_add, e_arith_sub, e_arith_mul,
   23706             :             e_arith_div, e_arith_mod, e_arith_pow
   23707             :          };
   23708             : 
   23709             :          enum settings_assignment_opr
   23710             :          {
   23711             :             e_assign_unknown = 0,
   23712             :             e_assign_assign, e_assign_addass, e_assign_subass,
   23713             :             e_assign_mulass, e_assign_divass, e_assign_modass
   23714             :          };
   23715             : 
   23716             :          enum settings_inequality_opr
   23717             :          {
   23718             :             e_ineq_unknown = 0,
   23719             :             e_ineq_lt   , e_ineq_lte, e_ineq_eq    ,
   23720             :             e_ineq_equal, e_ineq_ne , e_ineq_nequal,
   23721             :             e_ineq_gte  , e_ineq_gt
   23722             :          };
   23723             : 
   23724             :          static const std::size_t default_compile_all_opts =
   23725             :                                      e_replacer          +
   23726             :                                      e_joiner            +
   23727             :                                      e_numeric_check     +
   23728             :                                      e_bracket_check     +
   23729             :                                      e_sequence_check    +
   23730             :                                      e_commutative_check +
   23731             :                                      e_strength_reduction;
   23732             : 
   23733      108660 :          settings_store(const std::size_t compile_options = default_compile_all_opts)
   23734      108660 :          : max_stack_depth_(400)
   23735      108660 :          , max_node_depth_(10000)
   23736      108660 :          , max_local_vector_size_(2000000000)
   23737             :          {
   23738      108660 :            load_compile_options(compile_options);
   23739      108660 :          }
   23740             : 
   23741             :          settings_store& enable_all_base_functions()
   23742             :          {
   23743             :             disabled_func_set_.clear();
   23744             :             return (*this);
   23745             :          }
   23746             : 
   23747             :          settings_store& enable_all_control_structures()
   23748             :          {
   23749             :             disabled_ctrl_set_.clear();
   23750             :             return (*this);
   23751             :          }
   23752             : 
   23753             :          settings_store& enable_all_logic_ops()
   23754             :          {
   23755             :             disabled_logic_set_.clear();
   23756             :             return (*this);
   23757             :          }
   23758             : 
   23759             :          settings_store& enable_all_arithmetic_ops()
   23760             :          {
   23761             :             disabled_arithmetic_set_.clear();
   23762             :             return (*this);
   23763             :          }
   23764             : 
   23765             :          settings_store& enable_all_assignment_ops()
   23766             :          {
   23767             :             disabled_assignment_set_.clear();
   23768             :             return (*this);
   23769             :          }
   23770             : 
   23771             :          settings_store& enable_all_inequality_ops()
   23772             :          {
   23773             :             disabled_inequality_set_.clear();
   23774             :             return (*this);
   23775             :          }
   23776             : 
   23777             :          settings_store& enable_local_vardef()
   23778             :          {
   23779             :             disable_vardef_ = false;
   23780             :             return (*this);
   23781             :          }
   23782             : 
   23783             :          settings_store& enable_commutative_check()
   23784             :          {
   23785             :             enable_commutative_check_ = true;
   23786             :             return (*this);
   23787             :          }
   23788             : 
   23789             :          settings_store& enable_strength_reduction()
   23790             :          {
   23791             :             enable_strength_reduction_ = true;
   23792             :             return (*this);
   23793             :          }
   23794             : 
   23795             :          settings_store& disable_all_base_functions()
   23796             :          {
   23797             :             std::copy(details::base_function_list,
   23798             :                       details::base_function_list + details::base_function_list_size,
   23799             :                       std::insert_iterator<disabled_entity_set_t>
   23800             :                          (disabled_func_set_, disabled_func_set_.begin()));
   23801             :             return (*this);
   23802             :          }
   23803             : 
   23804             :          settings_store& disable_all_control_structures()
   23805             :          {
   23806             :             std::copy(details::cntrl_struct_list,
   23807             :                       details::cntrl_struct_list + details::cntrl_struct_list_size,
   23808             :                       std::insert_iterator<disabled_entity_set_t>
   23809             :                          (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
   23810             :             return (*this);
   23811             :          }
   23812             : 
   23813             :          settings_store& disable_all_logic_ops()
   23814             :          {
   23815             :             std::copy(details::logic_ops_list,
   23816             :                       details::logic_ops_list + details::logic_ops_list_size,
   23817             :                       std::insert_iterator<disabled_entity_set_t>
   23818             :                         (disabled_logic_set_, disabled_logic_set_.begin()));
   23819             :             return (*this);
   23820             :          }
   23821             : 
   23822             :          settings_store& disable_all_arithmetic_ops()
   23823             :          {
   23824             :             std::copy(details::arithmetic_ops_list,
   23825             :                       details::arithmetic_ops_list + details::arithmetic_ops_list_size,
   23826             :                       std::insert_iterator<disabled_entity_set_t>
   23827             :                          (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
   23828             :             return (*this);
   23829             :          }
   23830             : 
   23831             :          settings_store& disable_all_assignment_ops()
   23832             :          {
   23833             :             std::copy(details::assignment_ops_list,
   23834             :                       details::assignment_ops_list + details::assignment_ops_list_size,
   23835             :                       std::insert_iterator<disabled_entity_set_t>
   23836             :                          (disabled_assignment_set_, disabled_assignment_set_.begin()));
   23837             :             return (*this);
   23838             :          }
   23839             : 
   23840             :          settings_store& disable_all_inequality_ops()
   23841             :          {
   23842             :             std::copy(details::inequality_ops_list,
   23843             :                       details::inequality_ops_list + details::inequality_ops_list_size,
   23844             :                       std::insert_iterator<disabled_entity_set_t>
   23845             :                          (disabled_inequality_set_, disabled_inequality_set_.begin()));
   23846             :             return (*this);
   23847             :          }
   23848             : 
   23849             :          settings_store& disable_local_vardef()
   23850             :          {
   23851             :             disable_vardef_ = true;
   23852             :             return (*this);
   23853             :          }
   23854             : 
   23855             :          settings_store& disable_commutative_check()
   23856             :          {
   23857             :             enable_commutative_check_ = false;
   23858             :             return (*this);
   23859             :          }
   23860             : 
   23861             :          settings_store& disable_strength_reduction()
   23862             :          {
   23863             :             enable_strength_reduction_ = false;
   23864             :             return (*this);
   23865             :          }
   23866             : 
   23867      491757 :          bool replacer_enabled           () const { return enable_replacer_;           }
   23868      502098 :          bool commutative_check_enabled  () const { return enable_commutative_check_;  }
   23869      488557 :          bool joiner_enabled             () const { return enable_joiner_;             }
   23870      597217 :          bool numeric_check_enabled      () const { return enable_numeric_check_;      }
   23871      108660 :          bool bracket_check_enabled      () const { return enable_bracket_check_;      }
   23872      108660 :          bool sequence_check_enabled     () const { return enable_sequence_check_;     }
   23873      604013 :          bool strength_reduction_enabled () const { return enable_strength_reduction_; }
   23874      108660 :          bool collect_variables_enabled  () const { return enable_collect_vars_;       }
   23875      108660 :          bool collect_functions_enabled  () const { return enable_collect_funcs_;      }
   23876      108660 :          bool collect_assignments_enabled() const { return enable_collect_assings_;    }
   23877       82250 :          bool vardef_disabled            () const { return disable_vardef_;            }
   23878        5208 :          bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }
   23879           1 :          bool zero_return_disabled       () const { return disable_zero_return_;       }
   23880             : 
   23881      570903 :          bool function_enabled(const std::string& function_name) const
   23882             :          {
   23883      570903 :             if (disabled_func_set_.empty())
   23884      564903 :                return true;
   23885             :             else
   23886        6000 :                return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
   23887             :          }
   23888             : 
   23889        9387 :          bool control_struct_enabled(const std::string& control_struct) const
   23890             :          {
   23891        9387 :             if (disabled_ctrl_set_.empty())
   23892        9387 :                return true;
   23893             :             else
   23894           0 :                return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
   23895             :          }
   23896             : 
   23897             :          bool logic_enabled(const std::string& logic_operation) const
   23898             :          {
   23899             :             if (disabled_logic_set_.empty())
   23900             :                return true;
   23901             :             else
   23902             :                return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
   23903             :          }
   23904             : 
   23905             :          bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
   23906             :          {
   23907             :             if (disabled_logic_set_.empty())
   23908             :                return true;
   23909             :             else
   23910             :                return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
   23911             :                                                             .find(arith_opr_to_string(arithmetic_operation));
   23912             :          }
   23913             : 
   23914       23715 :          bool assignment_enabled(const details::operator_type& assignment) const
   23915             :          {
   23916       23715 :             if (disabled_assignment_set_.empty())
   23917       23715 :                return true;
   23918             :             else
   23919           0 :                return disabled_assignment_set_.end() == disabled_assignment_set_
   23920           0 :                                                            .find(assign_opr_to_string(assignment));
   23921             :          }
   23922             : 
   23923             :          bool inequality_enabled(const details::operator_type& inequality) const
   23924             :          {
   23925             :             if (disabled_inequality_set_.empty())
   23926             :                return true;
   23927             :             else
   23928             :                return disabled_inequality_set_.end() == disabled_inequality_set_
   23929             :                                                            .find(inequality_opr_to_string(inequality));
   23930             :          }
   23931             : 
   23932             :          bool function_disabled(const std::string& function_name) const
   23933             :          {
   23934             :             if (disabled_func_set_.empty())
   23935             :                return false;
   23936             :             else
   23937             :                return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
   23938             :          }
   23939             : 
   23940             :          bool control_struct_disabled(const std::string& control_struct) const
   23941             :          {
   23942             :             if (disabled_ctrl_set_.empty())
   23943             :                return false;
   23944             :             else
   23945             :                return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
   23946             :          }
   23947             : 
   23948         728 :          bool logic_disabled(const std::string& logic_operation) const
   23949             :          {
   23950         728 :             if (disabled_logic_set_.empty())
   23951         728 :                return false;
   23952             :             else
   23953           0 :                return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
   23954             :          }
   23955             : 
   23956     2796166 :          bool assignment_disabled(const details::operator_type assignment_operation) const
   23957             :          {
   23958     2796166 :             if (disabled_assignment_set_.empty())
   23959     2796166 :                return false;
   23960             :             else
   23961           0 :                return disabled_assignment_set_.end() != disabled_assignment_set_
   23962           0 :                                                            .find(assign_opr_to_string(assignment_operation));
   23963             :          }
   23964             : 
   23965     2796166 :          bool logic_disabled(const details::operator_type logic_operation) const
   23966             :          {
   23967     2796166 :             if (disabled_logic_set_.empty())
   23968     2796166 :                return false;
   23969             :             else
   23970           0 :                return disabled_logic_set_.end() != disabled_logic_set_
   23971           0 :                                                            .find(logic_opr_to_string(logic_operation));
   23972             :          }
   23973             : 
   23974     2796166 :          bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
   23975             :          {
   23976     2796166 :             if (disabled_arithmetic_set_.empty())
   23977     2796166 :                return false;
   23978             :             else
   23979           0 :                return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
   23980           0 :                                                            .find(arith_opr_to_string(arithmetic_operation));
   23981             :          }
   23982             : 
   23983     2796166 :          bool inequality_disabled(const details::operator_type& inequality) const
   23984             :          {
   23985     2796166 :             if (disabled_inequality_set_.empty())
   23986     2796166 :                return false;
   23987             :             else
   23988           0 :                return disabled_inequality_set_.end() != disabled_inequality_set_
   23989           0 :                                                            .find(inequality_opr_to_string(inequality));
   23990             :          }
   23991             : 
   23992        3200 :          settings_store& disable_base_function(const settings_base_funcs bf)
   23993             :          {
   23994        3200 :             if (
   23995        3200 :                  (e_bf_unknown != bf) &&
   23996             :                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
   23997             :                )
   23998             :             {
   23999        3200 :                disabled_func_set_.insert(details::base_function_list[bf - 1]);
   24000             :             }
   24001             : 
   24002        3200 :             return (*this);
   24003             :          }
   24004             : 
   24005             :          settings_store& disable_control_structure(const settings_control_structs ctrl_struct)
   24006             :          {
   24007             :             if (
   24008             :                  (e_ctrl_unknown != ctrl_struct) &&
   24009             :                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
   24010             :                )
   24011             :             {
   24012             :                disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
   24013             :             }
   24014             : 
   24015             :             return (*this);
   24016             :          }
   24017             : 
   24018             :          settings_store& disable_logic_operation(const settings_logic_opr logic)
   24019             :          {
   24020             :             if (
   24021             :                  (e_logic_unknown != logic) &&
   24022             :                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
   24023             :                )
   24024             :             {
   24025             :                disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
   24026             :             }
   24027             : 
   24028             :             return (*this);
   24029             :          }
   24030             : 
   24031             :          settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
   24032             :          {
   24033             :             if (
   24034             :                  (e_arith_unknown != arithmetic) &&
   24035             :                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
   24036             :                )
   24037             :             {
   24038             :                disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
   24039             :             }
   24040             : 
   24041             :             return (*this);
   24042             :          }
   24043             : 
   24044             :          settings_store& disable_assignment_operation(const settings_assignment_opr assignment)
   24045             :          {
   24046             :             if (
   24047             :                  (e_assign_unknown != assignment) &&
   24048             :                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
   24049             :                )
   24050             :             {
   24051             :                disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
   24052             :             }
   24053             : 
   24054             :             return (*this);
   24055             :          }
   24056             : 
   24057             :          settings_store& disable_inequality_operation(const settings_inequality_opr inequality)
   24058             :          {
   24059             :             if (
   24060             :                  (e_ineq_unknown != inequality) &&
   24061             :                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
   24062             :                )
   24063             :             {
   24064             :                disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
   24065             :             }
   24066             : 
   24067             :             return (*this);
   24068             :          }
   24069             : 
   24070             :          settings_store& enable_base_function(const settings_base_funcs bf)
   24071             :          {
   24072             :             if (
   24073             :                  (e_bf_unknown != bf) &&
   24074             :                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
   24075             :                )
   24076             :             {
   24077             :                const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
   24078             : 
   24079             :                if (disabled_func_set_.end() != itr)
   24080             :                {
   24081             :                   disabled_func_set_.erase(itr);
   24082             :                }
   24083             :             }
   24084             : 
   24085             :             return (*this);
   24086             :          }
   24087             : 
   24088             :          settings_store& enable_control_structure(const settings_control_structs ctrl_struct)
   24089             :          {
   24090             :             if (
   24091             :                  (e_ctrl_unknown != ctrl_struct) &&
   24092             :                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
   24093             :                )
   24094             :             {
   24095             :                const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
   24096             : 
   24097             :                if (disabled_ctrl_set_.end() != itr)
   24098             :                {
   24099             :                   disabled_ctrl_set_.erase(itr);
   24100             :                }
   24101             :             }
   24102             : 
   24103             :             return (*this);
   24104             :          }
   24105             : 
   24106             :          settings_store& enable_logic_operation(const settings_logic_opr logic)
   24107             :          {
   24108             :             if (
   24109             :                  (e_logic_unknown != logic) &&
   24110             :                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
   24111             :                )
   24112             :             {
   24113             :                const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
   24114             : 
   24115             :                if (disabled_logic_set_.end() != itr)
   24116             :                {
   24117             :                   disabled_logic_set_.erase(itr);
   24118             :                }
   24119             :             }
   24120             : 
   24121             :             return (*this);
   24122             :          }
   24123             : 
   24124             :          settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
   24125             :          {
   24126             :             if (
   24127             :                  (e_arith_unknown != arithmetic) &&
   24128             :                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
   24129             :                )
   24130             :             {
   24131             :                const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
   24132             : 
   24133             :                if (disabled_arithmetic_set_.end() != itr)
   24134             :                {
   24135             :                   disabled_arithmetic_set_.erase(itr);
   24136             :                }
   24137             :             }
   24138             : 
   24139             :             return (*this);
   24140             :          }
   24141             : 
   24142             :          settings_store& enable_assignment_operation(const settings_assignment_opr assignment)
   24143             :          {
   24144             :             if (
   24145             :                  (e_assign_unknown != assignment) &&
   24146             :                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
   24147             :                )
   24148             :             {
   24149             :                const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
   24150             : 
   24151             :                if (disabled_assignment_set_.end() != itr)
   24152             :                {
   24153             :                   disabled_assignment_set_.erase(itr);
   24154             :                }
   24155             :             }
   24156             : 
   24157             :             return (*this);
   24158             :          }
   24159             : 
   24160             :          settings_store& enable_inequality_operation(const settings_inequality_opr inequality)
   24161             :          {
   24162             :             if (
   24163             :                  (e_ineq_unknown != inequality) &&
   24164             :                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
   24165             :                )
   24166             :             {
   24167             :                const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
   24168             : 
   24169             :                if (disabled_inequality_set_.end() != itr)
   24170             :                {
   24171             :                   disabled_inequality_set_.erase(itr);
   24172             :                }
   24173             :             }
   24174             : 
   24175             :             return (*this);
   24176             :          }
   24177             : 
   24178             :          void set_max_stack_depth(const std::size_t max_stack_depth)
   24179             :          {
   24180             :             max_stack_depth_ = max_stack_depth;
   24181             :          }
   24182             : 
   24183             :          void set_max_node_depth(const std::size_t max_node_depth)
   24184             :          {
   24185             :             max_node_depth_ = max_node_depth;
   24186             :          }
   24187             : 
   24188             :          void set_max_local_vector_size(const std::size_t max_local_vector_size)
   24189             :          {
   24190             :             max_local_vector_size_ = max_local_vector_size;
   24191             :          }
   24192             : 
   24193             :          std::size_t max_stack_depth() const
   24194             :          {
   24195             :             return max_stack_depth_;
   24196             :          }
   24197             : 
   24198             :          std::size_t max_node_depth() const
   24199             :          {
   24200             :             return max_node_depth_;
   24201             :          }
   24202             : 
   24203       24277 :          std::size_t max_local_vector_size() const
   24204             :          {
   24205       24277 :             return max_local_vector_size_;
   24206             :          }
   24207             : 
   24208             :       private:
   24209             : 
   24210      108660 :          void load_compile_options(const std::size_t compile_options)
   24211             :          {
   24212      108660 :             enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;
   24213      108660 :             enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;
   24214      108660 :             enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;
   24215      108660 :             enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;
   24216      108660 :             enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;
   24217      108660 :             enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;
   24218      108660 :             enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;
   24219      108660 :             enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;
   24220      108660 :             enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;
   24221      108660 :             enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;
   24222      108660 :             disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;
   24223      108660 :             disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
   24224      108660 :             disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
   24225      108660 :          }
   24226             : 
   24227           0 :          std::string assign_opr_to_string(details::operator_type opr) const
   24228             :          {
   24229           0 :             switch (opr)
   24230             :             {
   24231           0 :                case details::e_assign : return ":=";
   24232           0 :                case details::e_addass : return "+=";
   24233           0 :                case details::e_subass : return "-=";
   24234           0 :                case details::e_mulass : return "*=";
   24235           0 :                case details::e_divass : return "/=";
   24236           0 :                case details::e_modass : return "%=";
   24237           0 :                default                : return ""  ;
   24238             :             }
   24239             :          }
   24240             : 
   24241           0 :          std::string arith_opr_to_string(details::operator_type opr) const
   24242             :          {
   24243           0 :             switch (opr)
   24244             :             {
   24245           0 :                case details::e_add : return "+";
   24246           0 :                case details::e_sub : return "-";
   24247           0 :                case details::e_mul : return "*";
   24248           0 :                case details::e_div : return "/";
   24249           0 :                case details::e_mod : return "%";
   24250           0 :                case details::e_pow : return "^";
   24251           0 :                default             : return "" ;
   24252             :             }
   24253             :          }
   24254             : 
   24255           0 :          std::string inequality_opr_to_string(details::operator_type opr) const
   24256             :          {
   24257           0 :             switch (opr)
   24258             :             {
   24259           0 :                case details::e_lt    : return "<" ;
   24260           0 :                case details::e_lte   : return "<=";
   24261           0 :                case details::e_eq    : return "==";
   24262           0 :                case details::e_equal : return "=" ;
   24263           0 :                case details::e_ne    : return "!=";
   24264           0 :                case details::e_nequal: return "<>";
   24265           0 :                case details::e_gte   : return ">=";
   24266           0 :                case details::e_gt    : return ">" ;
   24267           0 :                default               : return ""  ;
   24268             :             }
   24269             :          }
   24270             : 
   24271           0 :          std::string logic_opr_to_string(details::operator_type opr) const
   24272             :          {
   24273           0 :             switch (opr)
   24274             :             {
   24275           0 :                case details::e_and  : return "and" ;
   24276           0 :                case details::e_or   : return "or"  ;
   24277           0 :                case details::e_xor  : return "xor" ;
   24278           0 :                case details::e_nand : return "nand";
   24279           0 :                case details::e_nor  : return "nor" ;
   24280           0 :                case details::e_xnor : return "xnor";
   24281           0 :                case details::e_notl : return "not" ;
   24282           0 :                default              : return ""    ;
   24283             :             }
   24284             :          }
   24285             : 
   24286             :          bool enable_replacer_;
   24287             :          bool enable_joiner_;
   24288             :          bool enable_numeric_check_;
   24289             :          bool enable_bracket_check_;
   24290             :          bool enable_sequence_check_;
   24291             :          bool enable_commutative_check_;
   24292             :          bool enable_strength_reduction_;
   24293             :          bool enable_collect_vars_;
   24294             :          bool enable_collect_funcs_;
   24295             :          bool enable_collect_assings_;
   24296             :          bool disable_vardef_;
   24297             :          bool disable_rsrvd_sym_usr_;
   24298             :          bool disable_zero_return_;
   24299             : 
   24300             :          disabled_entity_set_t disabled_func_set_ ;
   24301             :          disabled_entity_set_t disabled_ctrl_set_ ;
   24302             :          disabled_entity_set_t disabled_logic_set_;
   24303             :          disabled_entity_set_t disabled_arithmetic_set_;
   24304             :          disabled_entity_set_t disabled_assignment_set_;
   24305             :          disabled_entity_set_t disabled_inequality_set_;
   24306             : 
   24307             :          std::size_t max_stack_depth_;
   24308             :          std::size_t max_node_depth_;
   24309             :          std::size_t max_local_vector_size_;
   24310             : 
   24311             :          friend class parser<T>;
   24312             :       };
   24313             : 
   24314             :       typedef settings_store settings_t;
   24315             : 
   24316      108660 :       explicit parser(const settings_t& settings = settings_t())
   24317      108660 :       : settings_(settings)
   24318      108660 :       , resolve_unknown_symbol_(false)
   24319      108660 :       , results_context_(0)
   24320      108660 :       , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0))
   24321             :         #ifdef _MSC_VER
   24322             :         #pragma warning(push)
   24323             :         #pragma warning (disable:4355)
   24324             :         #endif
   24325      108660 :       , sem_(*this)
   24326             :         #ifdef _MSC_VER
   24327             :         #pragma warning(pop)
   24328             :         #endif
   24329      108660 :       , operator_joiner_2_(2)
   24330      108660 :       , operator_joiner_3_(3)
   24331      108660 :       , loop_runtime_check_(0)
   24332      108660 :       , vector_access_runtime_check_(0)
   24333      108660 :       , compilation_check_ptr_(0)
   24334      434640 :       , assert_check_(0)
   24335             :       {
   24336      108660 :          init_precompilation();
   24337             : 
   24338      108660 :          load_operations_map           (base_ops_map_     );
   24339      108660 :          load_unary_operations_map     (unary_op_map_     );
   24340      108660 :          load_binary_operations_map    (binary_op_map_    );
   24341      108660 :          load_inv_binary_operations_map(inv_binary_op_map_);
   24342      108660 :          load_sf3_map                  (sf3_map_          );
   24343      108660 :          load_sf4_map                  (sf4_map_          );
   24344             : 
   24345      108660 :          expression_generator_.init_synthesize_map();
   24346      108660 :          expression_generator_.set_parser(*this);
   24347      108660 :          expression_generator_.set_uom (unary_op_map_     );
   24348      108660 :          expression_generator_.set_bom (binary_op_map_    );
   24349      108660 :          expression_generator_.set_ibom(inv_binary_op_map_);
   24350      108660 :          expression_generator_.set_sf3m(sf3_map_          );
   24351      108660 :          expression_generator_.set_sf4m(sf4_map_          );
   24352      108660 :          expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
   24353      108660 :       }
   24354             : 
   24355      108660 :      ~parser()
   24356      108660 :       {}
   24357             : 
   24358      108660 :       inline void init_precompilation()
   24359             :       {
   24360      108660 :          dec_.collect_variables() =
   24361      108660 :             settings_.collect_variables_enabled();
   24362             : 
   24363      108660 :          dec_.collect_functions() =
   24364      108660 :             settings_.collect_functions_enabled();
   24365             : 
   24366      108660 :          dec_.collect_assignments() =
   24367      108660 :             settings_.collect_assignments_enabled();
   24368             : 
   24369      108660 :          if (settings_.replacer_enabled())
   24370             :          {
   24371      108660 :             symbol_replacer_.clear();
   24372      434640 :             symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
   24373      434640 :             symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
   24374      108660 :             helper_assembly_.token_modifier_list.clear();
   24375      108660 :             helper_assembly_.register_modifier(&symbol_replacer_);
   24376             :          }
   24377             : 
   24378      108660 :          if (settings_.commutative_check_enabled())
   24379             :          {
   24380     3694406 :             for (std::size_t i = 0; i < details::reserved_words_size; ++i)
   24381             :             {
   24382     3585747 :                commutative_inserter_.ignore_symbol(details::reserved_words[i]);
   24383             :             }
   24384             : 
   24385      108659 :             helper_assembly_.token_inserter_list.clear();
   24386      108659 :             helper_assembly_.register_inserter(&commutative_inserter_);
   24387             :          }
   24388             : 
   24389      108660 :          if (settings_.joiner_enabled())
   24390             :          {
   24391      108660 :             helper_assembly_.token_joiner_list.clear();
   24392      108660 :             helper_assembly_.register_joiner(&operator_joiner_2_);
   24393      108660 :             helper_assembly_.register_joiner(&operator_joiner_3_);
   24394             :          }
   24395             : 
   24396      108660 :          if (
   24397      108660 :               settings_.numeric_check_enabled () ||
   24398      108660 :               settings_.bracket_check_enabled () ||
   24399           0 :               settings_.sequence_check_enabled()
   24400             :             )
   24401             :          {
   24402      108660 :             helper_assembly_.token_scanner_list.clear();
   24403             : 
   24404      108660 :             if (settings_.numeric_check_enabled())
   24405             :             {
   24406      108660 :                helper_assembly_.register_scanner(&numeric_checker_);
   24407             :             }
   24408             : 
   24409      108660 :             if (settings_.bracket_check_enabled())
   24410             :             {
   24411      108660 :                helper_assembly_.register_scanner(&bracket_checker_);
   24412             :             }
   24413             : 
   24414      108660 :             if (settings_.sequence_check_enabled())
   24415             :             {
   24416      108660 :                helper_assembly_.register_scanner(&sequence_validator_      );
   24417      108660 :                helper_assembly_.register_scanner(&sequence_validator_3tkns_);
   24418             :             }
   24419             :          }
   24420      108660 :       }
   24421             : 
   24422      380686 :       inline bool compile(const std::string& expression_string, expression<T>& expr)
   24423             :       {
   24424      380686 :          state_               .reset();
   24425      380686 :          error_list_          .clear();
   24426      380686 :          brkcnt_list_         .clear();
   24427      380686 :          synthesis_error_     .clear();
   24428      380686 :          immutable_memory_map_.reset();
   24429      380686 :          immutable_symtok_map_.clear();
   24430      380686 :          current_state_stack_ .clear();
   24431      380686 :          assert_ids_          .clear();
   24432      380686 :          sem_                 .cleanup();
   24433             : 
   24434      380686 :          return_cleanup();
   24435             : 
   24436      380686 :          expression_generator_.set_allocator(node_allocator_);
   24437             : 
   24438      380686 :          if (expression_string.empty())
   24439             :          {
   24440           0 :             set_error(make_error(
   24441             :                parser_error::e_syntax,
   24442             :                "ERR001 - Empty expression!",
   24443             :                exprtk_error_location));
   24444             : 
   24445           0 :             return false;
   24446             :          }
   24447             : 
   24448      380686 :          if (!init(expression_string))
   24449             :          {
   24450         788 :             process_lexer_errors();
   24451         788 :             return false;
   24452             :          }
   24453             : 
   24454      379898 :          if (lexer().empty())
   24455             :          {
   24456           3 :             set_error(make_error(
   24457             :                parser_error::e_syntax,
   24458             :                "ERR002 - Empty expression!",
   24459             :                exprtk_error_location));
   24460             : 
   24461           1 :             return false;
   24462             :          }
   24463             : 
   24464      379897 :          if (halt_compilation_check())
   24465             :          {
   24466             :             exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n"));
   24467           0 :             return false;
   24468             :          }
   24469             : 
   24470      379897 :          if (!run_assemblies())
   24471             :          {
   24472        9739 :             return false;
   24473             :          }
   24474             : 
   24475      370158 :          if (halt_compilation_check())
   24476             :          {
   24477             :             exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n"));
   24478           0 :             return false;
   24479             :          }
   24480             : 
   24481      370158 :          symtab_store_.symtab_list_ = expr.get_symbol_table_list();
   24482      370158 :          dec_.clear();
   24483             : 
   24484      370158 :          lexer().begin();
   24485             : 
   24486      370158 :          next_token();
   24487             : 
   24488      370158 :          expression_node_ptr e = parse_corpus();
   24489             : 
   24490      370158 :          if ((0 != e) && (token_t::e_eof == current_token().type))
   24491             :          {
   24492      359159 :             bool* retinvk_ptr = 0;
   24493             : 
   24494      359159 :             if (state_.return_stmt_present)
   24495             :             {
   24496         111 :                dec_.return_present_ = true;
   24497             : 
   24498         111 :                e = expression_generator_
   24499         111 :                      .return_envelope(e, results_context_, retinvk_ptr);
   24500             :             }
   24501             : 
   24502      359159 :             expr.set_expression(e);
   24503      359159 :             expr.set_retinvk(retinvk_ptr);
   24504             : 
   24505      359159 :             register_local_vars(expr);
   24506      359159 :             register_return_results(expr);
   24507             : 
   24508      359159 :             return !(!expr);
   24509             :          }
   24510             :          else
   24511             :          {
   24512       10999 :             if (error_list_.empty())
   24513             :             {
   24514           0 :                set_error(make_error(
   24515             :                   parser_error::e_syntax,
   24516           0 :                   current_token(),
   24517             :                   "ERR003 - Invalid expression encountered",
   24518             :                   exprtk_error_location));
   24519             :             }
   24520             : 
   24521       10999 :             if ((0 != e) && branch_deletable(e))
   24522             :             {
   24523           0 :                destroy_node(e);
   24524             :             }
   24525             : 
   24526       10999 :             dec_.clear    ();
   24527       10999 :             sem_.cleanup  ();
   24528       10999 :             return_cleanup();
   24529             : 
   24530       10999 :             return false;
   24531             :          }
   24532             :       }
   24533             : 
   24534             :       inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
   24535             :       {
   24536             :          expression_t expression;
   24537             :          expression.register_symbol_table(symtab);
   24538             :          compile(expression_string,expression);
   24539             :          return expression;
   24540             :       }
   24541             : 
   24542         788 :       void process_lexer_errors()
   24543             :       {
   24544       78215 :          for (std::size_t i = 0; i < lexer().size(); ++i)
   24545             :          {
   24546       77427 :             if (lexer()[i].is_error())
   24547             :             {
   24548         788 :                std::string diagnostic = "ERR004 - ";
   24549             : 
   24550         788 :                switch (lexer()[i].type)
   24551             :                {
   24552         491 :                   case lexer::token::e_error      : diagnostic += "General token error";
   24553         491 :                                                     break;
   24554             : 
   24555           0 :                   case lexer::token::e_err_symbol : diagnostic += "Symbol error";
   24556           0 :                                                     break;
   24557             : 
   24558          60 :                   case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
   24559          60 :                                                     break;
   24560             : 
   24561         237 :                   case lexer::token::e_err_string : diagnostic += "Invalid string token";
   24562         237 :                                                     break;
   24563             : 
   24564           0 :                   case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
   24565           0 :                                                     break;
   24566             : 
   24567           0 :                   default                         : diagnostic += "Unknown compiler error";
   24568             :                }
   24569             : 
   24570        2364 :                set_error(make_error(
   24571             :                   parser_error::e_lexer,
   24572         788 :                   lexer()[i],
   24573         788 :                   diagnostic + ": " + lexer()[i].value,
   24574             :                   exprtk_error_location));
   24575         788 :             }
   24576             :          }
   24577         788 :       }
   24578             : 
   24579      379897 :       inline bool run_assemblies()
   24580             :       {
   24581      379897 :          if (settings_.commutative_check_enabled())
   24582             :          {
   24583      379887 :             helper_assembly_.run_inserters(lexer());
   24584             :          }
   24585             : 
   24586      379897 :          if (settings_.joiner_enabled())
   24587             :          {
   24588      379897 :             helper_assembly_.run_joiners(lexer());
   24589             :          }
   24590             : 
   24591      379897 :          if (settings_.replacer_enabled())
   24592             :          {
   24593      379897 :             helper_assembly_.run_modifiers(lexer());
   24594             :          }
   24595             : 
   24596      379897 :          if (
   24597      379897 :               settings_.numeric_check_enabled () ||
   24598      379897 :               settings_.bracket_check_enabled () ||
   24599           0 :               settings_.sequence_check_enabled()
   24600             :             )
   24601             :          {
   24602      379897 :             if (!helper_assembly_.run_scanners(lexer()))
   24603             :             {
   24604        9739 :                if (helper_assembly_.error_token_scanner)
   24605             :                {
   24606        9739 :                   lexer::helper::bracket_checker*            bracket_checker_ptr     = 0;
   24607        9739 :                   lexer::helper::numeric_checker<T>*         numeric_checker_ptr     = 0;
   24608        9739 :                   lexer::helper::sequence_validator*         sequence_validator_ptr  = 0;
   24609        9739 :                   lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
   24610             : 
   24611        9739 :                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
   24612             :                   {
   24613       26682 :                      set_error(make_error(
   24614             :                         parser_error::e_token,
   24615             :                         bracket_checker_ptr->error_token(),
   24616       17788 :                         "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
   24617             :                         exprtk_error_location));
   24618             :                   }
   24619         845 :                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner)))
   24620             :                   {
   24621          28 :                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
   24622             :                      {
   24623          14 :                         lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
   24624             : 
   24625          14 :                         set_error(make_error(
   24626             :                            parser_error::e_token,
   24627             :                            error_token,
   24628             :                            "ERR006 - Invalid numeric token: '" + error_token.value + "'",
   24629             :                            exprtk_error_location));
   24630             :                      }
   24631             : 
   24632          14 :                      if (numeric_checker_ptr->error_count())
   24633             :                      {
   24634          14 :                         numeric_checker_ptr->clear_errors();
   24635             :                      }
   24636             :                   }
   24637         831 :                   else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
   24638             :                   {
   24639        1831 :                      for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
   24640             :                      {
   24641        1002 :                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
   24642             : 
   24643        1002 :                         set_error(make_error(
   24644             :                            parser_error::e_token,
   24645             :                            error_token.first,
   24646             :                            "ERR007 - Invalid token sequence: '" +
   24647             :                            error_token.first.value  + "' and '" +
   24648             :                            error_token.second.value + "'",
   24649             :                            exprtk_error_location));
   24650             :                      }
   24651             : 
   24652         829 :                      if (sequence_validator_ptr->error_count())
   24653             :                      {
   24654         829 :                         sequence_validator_ptr->clear_errors();
   24655             :                      }
   24656             :                   }
   24657           2 :                   else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
   24658             :                   {
   24659           6 :                      for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
   24660             :                      {
   24661           4 :                         std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
   24662             : 
   24663           4 :                         set_error(make_error(
   24664             :                            parser_error::e_token,
   24665             :                            error_token.first,
   24666             :                            "ERR008 - Invalid token sequence: '" +
   24667             :                            error_token.first.value  + "' and '" +
   24668             :                            error_token.second.value + "'",
   24669             :                            exprtk_error_location));
   24670             :                      }
   24671             : 
   24672           2 :                      if (sequence_validator3_ptr->error_count())
   24673             :                      {
   24674           2 :                         sequence_validator3_ptr->clear_errors();
   24675             :                      }
   24676             :                   }
   24677             :                }
   24678             : 
   24679        9739 :                return false;
   24680             :             }
   24681             :          }
   24682             : 
   24683      370158 :          return true;
   24684             :       }
   24685             : 
   24686        1600 :       inline settings_store& settings()
   24687             :       {
   24688        1600 :          return settings_;
   24689             :       }
   24690             : 
   24691           0 :       inline parser_error::type get_error(const std::size_t& index) const
   24692             :       {
   24693           0 :          if (index < error_list_.size())
   24694             :          {
   24695           0 :             return error_list_[index];
   24696             :          }
   24697             : 
   24698           0 :          throw std::invalid_argument("parser::get_error() - Invalid error index specified");
   24699             :       }
   24700             : 
   24701           0 :       inline std::string error() const
   24702             :       {
   24703           0 :          if (!error_list_.empty())
   24704             :          {
   24705           0 :             return error_list_[0].diagnostic;
   24706             :          }
   24707             :          else
   24708           0 :             return std::string("No Error");
   24709             :       }
   24710             : 
   24711           0 :       inline std::size_t error_count() const
   24712             :       {
   24713           0 :          return error_list_.size();
   24714             :       }
   24715             : 
   24716        1495 :       inline dependent_entity_collector& dec()
   24717             :       {
   24718        1495 :          return dec_;
   24719             :       }
   24720             : 
   24721        3200 :       inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
   24722             :       {
   24723        3200 :          if (!settings_.replacer_enabled())
   24724           0 :             return false;
   24725        3200 :          else if (details::is_reserved_word(old_symbol))
   24726           0 :             return false;
   24727             :          else
   24728        3200 :             return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
   24729             :       }
   24730             : 
   24731             :       inline bool remove_replace_symbol(const std::string& symbol)
   24732             :       {
   24733             :          if (!settings_.replacer_enabled())
   24734             :             return false;
   24735             :          else if (details::is_reserved_word(symbol))
   24736             :             return false;
   24737             :          else
   24738             :             return symbol_replacer_.remove(symbol);
   24739             :       }
   24740             : 
   24741         204 :       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
   24742             :       {
   24743         204 :          resolve_unknown_symbol_ = true;
   24744             : 
   24745         204 :          if (usr)
   24746         202 :             unknown_symbol_resolver_ = usr;
   24747             :          else
   24748           2 :             unknown_symbol_resolver_ = &default_usr_;
   24749         204 :       }
   24750             : 
   24751             :       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
   24752             :       {
   24753             :          enable_unknown_symbol_resolver(&usr);
   24754             :       }
   24755             : 
   24756             :       inline void disable_unknown_symbol_resolver()
   24757             :       {
   24758             :          resolve_unknown_symbol_  = false;
   24759             :          unknown_symbol_resolver_ = &default_usr_;
   24760             :       }
   24761             : 
   24762             :       inline void register_loop_runtime_check(loop_runtime_check& lrtchk)
   24763             :       {
   24764             :          loop_runtime_check_ = &lrtchk;
   24765             :       }
   24766             : 
   24767          70 :       inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk)
   24768             :       {
   24769          70 :          vector_access_runtime_check_ = &vartchk;
   24770          70 :       }
   24771             : 
   24772             :       inline void register_compilation_timeout_check(compilation_check& compchk)
   24773             :       {
   24774             :          compilation_check_ptr_ = &compchk;
   24775             :       }
   24776             : 
   24777          54 :       inline void register_assert_check(assert_check& assrt_chck)
   24778             :       {
   24779          54 :          assert_check_ = &assrt_chck;
   24780          54 :       }
   24781             : 
   24782             :       inline void clear_loop_runtime_check()
   24783             :       {
   24784             :          loop_runtime_check_ = loop_runtime_check_ptr(0);
   24785             :       }
   24786             : 
   24787             :       inline void clear_vector_access_runtime_check()
   24788             :       {
   24789             :          vector_access_runtime_check_ = vector_access_runtime_check_ptr(0);
   24790             :       }
   24791             : 
   24792             :       inline void clear_compilation_timeout_check()
   24793             :       {
   24794             :          compilation_check_ptr_ = compilation_check_ptr(0);
   24795             :       }
   24796             : 
   24797             :       inline void clear_assert_check()
   24798             :       {
   24799             :          assert_check_ = assert_check_ptr(0);
   24800             :       }
   24801             : 
   24802             :    private:
   24803             : 
   24804     2511953 :       inline bool valid_base_operation(const std::string& symbol) const
   24805             :       {
   24806     2511953 :          const std::size_t length = symbol.size();
   24807             : 
   24808     2511953 :          if (
   24809      549903 :               (length < 3) || // Shortest base op symbol length
   24810             :               (length > 9)    // Longest base op symbol length
   24811             :             )
   24812     1963400 :             return false;
   24813             :          else
   24814     1094706 :             return settings_.function_enabled(symbol) &&
   24815     1094706 :                    (base_ops_map_.end() != base_ops_map_.find(symbol));
   24816             :       }
   24817             : 
   24818     2535008 :       inline bool valid_vararg_operation(const std::string& symbol) const
   24819             :       {
   24820     2535010 :          static const std::string s_sum     = "sum" ;
   24821     2535010 :          static const std::string s_mul     = "mul" ;
   24822     2535010 :          static const std::string s_avg     = "avg" ;
   24823     2535010 :          static const std::string s_min     = "min" ;
   24824     2535010 :          static const std::string s_max     = "max" ;
   24825     2535010 :          static const std::string s_mand    = "mand";
   24826     2535010 :          static const std::string s_mor     = "mor" ;
   24827     2535010 :          static const std::string s_multi   = "~"   ;
   24828     2535010 :          static const std::string s_mswitch = "[*]" ;
   24829             : 
   24830             :          return
   24831             :                (
   24832     5067812 :                   details::imatch(symbol,s_sum    ) ||
   24833     5065384 :                   details::imatch(symbol,s_mul    ) ||
   24834     5064822 :                   details::imatch(symbol,s_avg    ) ||
   24835     5060072 :                   details::imatch(symbol,s_min    ) ||
   24836     5055281 :                   details::imatch(symbol,s_max    ) ||
   24837     5054646 :                   details::imatch(symbol,s_mand   ) ||
   24838     5054133 :                   details::imatch(symbol,s_mor    ) ||
   24839     5039809 :                   details::imatch(symbol,s_multi  ) ||
   24840     2512871 :                   details::imatch(symbol,s_mswitch)
   24841     5070016 :                ) &&
   24842     2557335 :                settings_.function_enabled(symbol);
   24843             :       }
   24844             : 
   24845     2796166 :       bool is_invalid_logic_operation(const details::operator_type operation) const
   24846             :       {
   24847     2796166 :          return settings_.logic_disabled(operation);
   24848             :       }
   24849             : 
   24850     2796166 :       bool is_invalid_arithmetic_operation(const details::operator_type operation) const
   24851             :       {
   24852     2796166 :          return settings_.arithmetic_disabled(operation);
   24853             :       }
   24854             : 
   24855     2796166 :       bool is_invalid_assignment_operation(const details::operator_type operation) const
   24856             :       {
   24857     2796166 :          return settings_.assignment_disabled(operation);
   24858             :       }
   24859             : 
   24860     2796166 :       bool is_invalid_inequality_operation(const details::operator_type operation) const
   24861             :       {
   24862     2796166 :          return settings_.inequality_disabled(operation);
   24863             :       }
   24864             : 
   24865             :       #ifdef exprtk_enable_debugging
   24866             :       inline void next_token()
   24867             :       {
   24868             :          const std::string ct_str = current_token().value;
   24869             :          const std::size_t ct_pos = current_token().position;
   24870             :          parser_helper::next_token();
   24871             :          const std::string depth(2 * state_.scope_depth,' ');
   24872             :          exprtk_debug(("%s"
   24873             :                        "prev[%s | %04d] --> curr[%s | %04d]  stack_level: %3d\n",
   24874             :                        depth.c_str(),
   24875             :                        ct_str.c_str(),
   24876             :                        static_cast<unsigned int>(ct_pos),
   24877             :                        current_token().value.c_str(),
   24878             :                        static_cast<unsigned int>(current_token().position),
   24879             :                        static_cast<unsigned int>(state_.stack_depth)));
   24880             :       }
   24881             :       #endif
   24882             : 
   24883      370158 :       inline expression_node_ptr parse_corpus()
   24884             :       {
   24885      370158 :          std::vector<expression_node_ptr> arg_list;
   24886      370158 :          std::vector<bool> side_effect_list;
   24887             : 
   24888      370158 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   24889             : 
   24890      370158 :          lexer::token begin_token;
   24891      370158 :          lexer::token end_token;
   24892             : 
   24893       75652 :          for ( ; ; )
   24894             :          {
   24895      445810 :             state_.side_effect_present = false;
   24896             : 
   24897      445810 :             begin_token = current_token();
   24898             : 
   24899      445810 :             expression_node_ptr arg = parse_expression();
   24900             : 
   24901      445810 :             if (0 == arg)
   24902             :             {
   24903       10999 :                if (error_list_.empty())
   24904             :                {
   24905           0 :                   set_error(make_error(
   24906             :                      parser_error::e_syntax,
   24907           0 :                      current_token(),
   24908             :                      "ERR009 - Invalid expression encountered",
   24909             :                      exprtk_error_location));
   24910             :                }
   24911             : 
   24912       10999 :                return error_node();
   24913             :             }
   24914             :             else
   24915             :             {
   24916      434811 :                arg_list.push_back(arg);
   24917             : 
   24918      434811 :                side_effect_list.push_back(state_.side_effect_present);
   24919             : 
   24920      434811 :                end_token = current_token();
   24921             : 
   24922      434811 :                const std::string sub_expr = construct_subexpr(begin_token, end_token);
   24923             : 
   24924             :                exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
   24925             :                              static_cast<int>(arg_list.size() - 1),
   24926             :                              sub_expr.c_str()));
   24927             : 
   24928             :                exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
   24929             :                              static_cast<int>(arg_list.size() - 1),
   24930             :                              state_.side_effect_present ? "true" : "false"));
   24931             : 
   24932             :                exprtk_debug(("-------------------------------------------------\n"));
   24933      434811 :             }
   24934             : 
   24935      434811 :             if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
   24936             :             {
   24937      421620 :                if (lexer().finished())
   24938      359159 :                   break;
   24939             :                else
   24940       62461 :                   next_token();
   24941             :             }
   24942             :          }
   24943             : 
   24944      359159 :          if (
   24945      718318 :               !arg_list.empty() &&
   24946      359159 :               is_return_node(arg_list.back())
   24947             :             )
   24948             :          {
   24949           2 :             dec_.final_stmt_return_ = true;
   24950             :          }
   24951             : 
   24952      359159 :          const expression_node_ptr result = simplify(arg_list,side_effect_list);
   24953             : 
   24954      359159 :          sdd.delete_ptr = (0 == result);
   24955             : 
   24956      359159 :          return result;
   24957      370158 :       }
   24958             : 
   24959      434811 :       std::string construct_subexpr(lexer::token& begin_token,
   24960             :                                     lexer::token& end_token,
   24961             :                                     const bool cleanup_whitespace = true)
   24962             :       {
   24963      434811 :          std::string result = lexer().substr(begin_token.position,end_token.position);
   24964      434811 :          if (cleanup_whitespace)
   24965             :          {
   24966    30648260 :             for (std::size_t i = 0; i < result.size(); ++i)
   24967             :             {
   24968    30213449 :                if (details::is_whitespace(result[i])) result[i] = ' ';
   24969             :             }
   24970             :          }
   24971             : 
   24972      434811 :          return result;
   24973           0 :       }
   24974             : 
   24975             :       static const precedence_level default_precedence = e_level00;
   24976             : 
   24977             :       struct state_t
   24978             :       {
   24979     3998707 :          inline void set(const precedence_level& l,
   24980             :                          const precedence_level& r,
   24981             :                          const details::operator_type& o,
   24982             :                          const token_t tkn = token_t())
   24983             :          {
   24984     3998707 :             left      = l;
   24985     3998707 :             right     = r;
   24986     3998707 :             operation = o;
   24987     3998707 :             token     = tkn;
   24988     3998707 :          }
   24989             : 
   24990     8875389 :          inline void reset()
   24991             :          {
   24992     8875389 :             left      = e_level00;
   24993     8875389 :             right     = e_level00;
   24994     8875389 :             operation = details::e_default;
   24995     8875389 :          }
   24996             : 
   24997             :          precedence_level left;
   24998             :          precedence_level right;
   24999             :          details::operator_type operation;
   25000             :          token_t token;
   25001             :       };
   25002             : 
   25003     2682168 :       inline void push_current_state(const state_t current_state)
   25004             :       {
   25005     2682168 :          current_state_stack_.push_back(current_state);
   25006     2682168 :       }
   25007             : 
   25008     2682168 :       inline void pop_current_state()
   25009             :       {
   25010     2682168 :          if (!current_state_stack_.empty())
   25011             :          {
   25012     2682168 :             current_state_stack_.pop_back();
   25013             :          }
   25014     2682168 :       }
   25015             : 
   25016           3 :       inline state_t current_state() const
   25017             :       {
   25018           3 :          return (!current_state_stack_.empty()) ?
   25019           3 :                 current_state_stack_.back()     :
   25020           3 :                 state_t();
   25021             :       }
   25022             : 
   25023     7096846 :       inline bool halt_compilation_check()
   25024             :       {
   25025     7096846 :          compilation_check::compilation_context context;
   25026             : 
   25027     7096846 :          if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context))
   25028             :          {
   25029           0 :             const std::string error_message =
   25030           0 :                !context.error_message.empty() ? " Details: " + context.error_message : "";
   25031             : 
   25032           0 :             set_error(make_error(
   25033             :                parser_error::e_parser,
   25034           0 :                token_t(),
   25035             :                "ERR010 - Internal compilation check failed." + error_message,
   25036             :                exprtk_error_location));
   25037             : 
   25038           0 :             return true;
   25039           0 :          }
   25040             : 
   25041     7096846 :          return false;
   25042     7096846 :       }
   25043             : 
   25044     6346791 :       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
   25045             :       {
   25046     6346791 :          if (halt_compilation_check())
   25047             :          {
   25048             :             exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n"));
   25049           0 :             return error_node();
   25050             :          }
   25051             : 
   25052     6346791 :          stack_limit_handler slh(*this);
   25053             : 
   25054     6346791 :          if (!slh)
   25055             :          {
   25056           0 :             return error_node();
   25057             :          }
   25058             : 
   25059     6346791 :          expression_node_ptr expression = parse_branch(precedence);
   25060             : 
   25061     6346791 :          if (0 == expression)
   25062             :          {
   25063      153527 :             return error_node();
   25064             :          }
   25065             : 
   25066     6193264 :          bool break_loop = false;
   25067             : 
   25068     6193264 :          state_t current_state;
   25069             : 
   25070     5478291 :          for ( ; ; )
   25071             :          {
   25072     8875389 :             current_state.reset();
   25073             : 
   25074     8875389 :             switch (current_token().type)
   25075             :             {
   25076       11348 :                case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break;
   25077       10080 :                case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break;
   25078        1048 :                case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break;
   25079         330 :                case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break;
   25080         331 :                case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break;
   25081          75 :                case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break;
   25082        2728 :                case token_t::e_swap   : current_state.set(e_level00, e_level00, details::e_swap  , current_token()); break;
   25083        7491 :                case token_t::e_lt     : current_state.set(e_level05, e_level06, details::e_lt    , current_token()); break;
   25084        2256 :                case token_t::e_lte    : current_state.set(e_level05, e_level06, details::e_lte   , current_token()); break;
   25085       71765 :                case token_t::e_eq     : current_state.set(e_level05, e_level06, details::e_eq    , current_token()); break;
   25086        3045 :                case token_t::e_ne     : current_state.set(e_level05, e_level06, details::e_ne    , current_token()); break;
   25087         690 :                case token_t::e_gte    : current_state.set(e_level05, e_level06, details::e_gte   , current_token()); break;
   25088        7424 :                case token_t::e_gt     : current_state.set(e_level05, e_level06, details::e_gt    , current_token()); break;
   25089     1416909 :                case token_t::e_add    : current_state.set(e_level07, e_level08, details::e_add   , current_token()); break;
   25090      815459 :                case token_t::e_sub    : current_state.set(e_level07, e_level08, details::e_sub   , current_token()); break;
   25091      643982 :                case token_t::e_div    : current_state.set(e_level10, e_level11, details::e_div   , current_token()); break;
   25092      884906 :                case token_t::e_mul    : current_state.set(e_level10, e_level11, details::e_mul   , current_token()); break;
   25093         498 :                case token_t::e_mod    : current_state.set(e_level10, e_level11, details::e_mod   , current_token()); break;
   25094       94523 :                case token_t::e_pow    : current_state.set(e_level12, e_level12, details::e_pow   , current_token()); break;
   25095     4900501 :                default                :
   25096     4900501 :                   if (token_t::e_symbol == current_token().type)
   25097             :                   {
   25098       43631 :                      static const std::string s_and   = "and"  ;
   25099       43631 :                      static const std::string s_nand  = "nand" ;
   25100       43631 :                      static const std::string s_or    = "or"   ;
   25101       43631 :                      static const std::string s_nor   = "nor"  ;
   25102       43631 :                      static const std::string s_xor   = "xor"  ;
   25103       43631 :                      static const std::string s_xnor  = "xnor" ;
   25104       43631 :                      static const std::string s_in    = "in"   ;
   25105       43631 :                      static const std::string s_like  = "like" ;
   25106       43631 :                      static const std::string s_ilike = "ilike";
   25107       43631 :                      static const std::string s_and1  = "&"    ;
   25108       43631 :                      static const std::string s_or1   = "|"    ;
   25109       43631 :                      static const std::string s_not   = "not"  ;
   25110             : 
   25111       43629 :                      if (details::imatch(current_token().value,s_and))
   25112             :                      {
   25113       13565 :                         current_state.set(e_level03, e_level04, details::e_and, current_token());
   25114       13565 :                         break;
   25115             :                      }
   25116       30064 :                      else if (details::imatch(current_token().value,s_and1))
   25117             :                      {
   25118             :                         #ifndef exprtk_disable_sc_andor
   25119         463 :                         current_state.set(e_level03, e_level04, details::e_scand, current_token());
   25120             :                         #else
   25121             :                         current_state.set(e_level03, e_level04, details::e_and, current_token());
   25122             :                         #endif
   25123         463 :                         break;
   25124             :                      }
   25125       29601 :                      else if (details::imatch(current_token().value,s_nand))
   25126             :                      {
   25127         604 :                         current_state.set(e_level03, e_level04, details::e_nand, current_token());
   25128         604 :                         break;
   25129             :                      }
   25130       28997 :                      else if (details::imatch(current_token().value,s_or))
   25131             :                      {
   25132         723 :                         current_state.set(e_level01, e_level02, details::e_or, current_token());
   25133         723 :                         break;
   25134             :                      }
   25135       28274 :                      else if (details::imatch(current_token().value,s_or1))
   25136             :                      {
   25137             :                         #ifndef exprtk_disable_sc_andor
   25138         420 :                         current_state.set(e_level01, e_level02, details::e_scor, current_token());
   25139             :                         #else
   25140             :                         current_state.set(e_level01, e_level02, details::e_or, current_token());
   25141             :                         #endif
   25142         420 :                         break;
   25143             :                      }
   25144       27854 :                      else if (details::imatch(current_token().value,s_nor))
   25145             :                      {
   25146         604 :                         current_state.set(e_level01, e_level02, details::e_nor, current_token());
   25147         604 :                         break;
   25148             :                      }
   25149       27250 :                      else if (details::imatch(current_token().value,s_xor))
   25150             :                      {
   25151         265 :                         current_state.set(e_level01, e_level02, details::e_xor, current_token());
   25152         265 :                         break;
   25153             :                      }
   25154       26985 :                      else if (details::imatch(current_token().value,s_xnor))
   25155             :                      {
   25156          80 :                         current_state.set(e_level01, e_level02, details::e_xnor, current_token());
   25157          80 :                         break;
   25158             :                      }
   25159       26905 :                      else if (details::imatch(current_token().value,s_in))
   25160             :                      {
   25161         780 :                         current_state.set(e_level04, e_level04, details::e_in, current_token());
   25162         780 :                         break;
   25163             :                      }
   25164       26125 :                      else if (details::imatch(current_token().value,s_like))
   25165             :                      {
   25166        3070 :                         current_state.set(e_level04, e_level04, details::e_like, current_token());
   25167        3070 :                         break;
   25168             :                      }
   25169       23055 :                      else if (details::imatch(current_token().value,s_ilike))
   25170             :                      {
   25171        3245 :                         current_state.set(e_level04, e_level04, details::e_ilike, current_token());
   25172        3245 :                         break;
   25173             :                      }
   25174       19810 :                      else if (details::imatch(current_token().value,s_not))
   25175             :                      {
   25176           0 :                         break;
   25177             :                      }
   25178             :                   }
   25179             : 
   25180     4876682 :                   break_loop = true;
   25181             :             }
   25182             : 
   25183     8875389 :             if (break_loop)
   25184             :             {
   25185     4876682 :                parse_pending_string_rangesize(expression);
   25186     4876682 :                break;
   25187             :             }
   25188     3998707 :             else if (current_state.left < precedence)
   25189     1202541 :                break;
   25190             : 
   25191     2796166 :             const lexer::token prev_token = current_token();
   25192             : 
   25193     2796166 :             next_token();
   25194             : 
   25195     2796166 :             expression_node_ptr right_branch   = error_node();
   25196     2796166 :             expression_node_ptr new_expression = error_node();
   25197             : 
   25198     2796166 :             if (is_invalid_logic_operation(current_state.operation))
   25199             :             {
   25200           0 :                free_node(node_allocator_,expression);
   25201             : 
   25202           0 :                set_error(make_error(
   25203             :                   parser_error::e_syntax,
   25204             :                   prev_token,
   25205             :                   "ERR011 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
   25206             :                   exprtk_error_location));
   25207             : 
   25208           0 :                return error_node();
   25209             :             }
   25210     2796166 :             else if (is_invalid_arithmetic_operation(current_state.operation))
   25211             :             {
   25212           0 :                free_node(node_allocator_,expression);
   25213             : 
   25214           0 :                set_error(make_error(
   25215             :                   parser_error::e_syntax,
   25216             :                   prev_token,
   25217             :                   "ERR012 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
   25218             :                   exprtk_error_location));
   25219             : 
   25220           0 :                return error_node();
   25221             :             }
   25222     2796166 :             else if (is_invalid_inequality_operation(current_state.operation))
   25223             :             {
   25224           0 :                free_node(node_allocator_,expression);
   25225             : 
   25226           0 :                set_error(make_error(
   25227             :                   parser_error::e_syntax,
   25228             :                   prev_token,
   25229             :                   "ERR013 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
   25230             :                   exprtk_error_location));
   25231             : 
   25232           0 :                return error_node();
   25233             :             }
   25234     2796166 :             else if (is_invalid_assignment_operation(current_state.operation))
   25235             :             {
   25236           0 :                free_node(node_allocator_,expression);
   25237             : 
   25238           0 :                set_error(make_error(
   25239             :                   parser_error::e_syntax,
   25240             :                   prev_token,
   25241             :                   "ERR014 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
   25242             :                   exprtk_error_location));
   25243             : 
   25244           0 :                return error_node();
   25245             :             }
   25246             : 
   25247     2796166 :             if (0 != (right_branch = parse_expression(current_state.right)))
   25248             :             {
   25249     2682168 :                if (
   25250     5364336 :                     details::is_return_node(expression  ) ||
   25251     2682168 :                     details::is_return_node(right_branch)
   25252             :                   )
   25253             :                {
   25254           0 :                   free_node(node_allocator_, expression  );
   25255           0 :                   free_node(node_allocator_, right_branch);
   25256             : 
   25257           0 :                   set_error(make_error(
   25258             :                      parser_error::e_syntax,
   25259             :                      prev_token,
   25260             :                      "ERR015 - Return statements cannot be part of sub-expressions",
   25261             :                      exprtk_error_location));
   25262             : 
   25263           0 :                   return error_node();
   25264             :                }
   25265             : 
   25266     2682168 :                push_current_state(current_state);
   25267             : 
   25268             :                new_expression = expression_generator_
   25269     2682168 :                                   (
   25270             :                                     current_state.operation,
   25271             :                                     expression,
   25272             :                                     right_branch
   25273             :                                   );
   25274             : 
   25275     2682168 :                pop_current_state();
   25276             :             }
   25277             : 
   25278     2796166 :             if (0 == new_expression)
   25279             :             {
   25280      114041 :                if (error_list_.empty())
   25281             :                {
   25282          36 :                   set_error(make_error(
   25283             :                      parser_error::e_syntax,
   25284             :                      prev_token,
   25285          24 :                      !synthesis_error_.empty() ?
   25286           0 :                      synthesis_error_ :
   25287             :                      "ERR016 - General parsing error at token: '" + prev_token.value + "'",
   25288             :                      exprtk_error_location));
   25289             :                }
   25290             : 
   25291      114041 :                free_node(node_allocator_, expression  );
   25292      114041 :                free_node(node_allocator_, right_branch);
   25293             : 
   25294      114041 :                return error_node();
   25295             :             }
   25296             :             else
   25297             :             {
   25298     2682125 :                if (
   25299     2682125 :                     token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
   25300             :                     (e_level00 == precedence)
   25301             :                   )
   25302             :                {
   25303        2111 :                   expression = parse_ternary_conditional_statement(new_expression);
   25304             :                }
   25305             :                else
   25306     2680014 :                   expression = new_expression;
   25307             : 
   25308     2682125 :                parse_pending_string_rangesize(expression);
   25309             :             }
   25310             :          }
   25311             : 
   25312     6079223 :          if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
   25313             :          {
   25314           0 :             set_error(make_error(
   25315             :                parser_error::e_syntax,
   25316           0 :                current_token(),
   25317           0 :                "ERR017 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
   25318           0 :                " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
   25319             :                exprtk_error_location));
   25320             : 
   25321           0 :             free_node(node_allocator_,expression);
   25322             : 
   25323           0 :             return error_node();
   25324             :          }
   25325             : 
   25326     6079223 :          return expression;
   25327     6346791 :       }
   25328             : 
   25329        1780 :       bool simplify_unary_negation_branch(expression_node_ptr& node)
   25330             :       {
   25331             :          {
   25332             :             typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
   25333        1780 :             ubn_t* n = dynamic_cast<ubn_t*>(node);
   25334             : 
   25335        1780 :             if (n)
   25336             :             {
   25337        1460 :                expression_node_ptr un_r = n->branch(0);
   25338        1460 :                n->release();
   25339        1460 :                free_node(node_allocator_,node);
   25340        1460 :                node = un_r;
   25341             : 
   25342        1460 :                return true;
   25343             :             }
   25344             :          }
   25345             : 
   25346             :          {
   25347             :             typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
   25348             : 
   25349         320 :             uvn_t* n = dynamic_cast<uvn_t*>(node);
   25350             : 
   25351         320 :             if (n)
   25352             :             {
   25353         320 :                const T& v = n->v();
   25354         320 :                expression_node_ptr return_node = error_node();
   25355             : 
   25356         320 :                if (
   25357         640 :                     (0 != (return_node = symtab_store_.get_variable(v))) ||
   25358         320 :                     (0 != (return_node = sem_         .get_variable(v)))
   25359             :                   )
   25360             :                {
   25361         320 :                   free_node(node_allocator_,node);
   25362         320 :                   node = return_node;
   25363             : 
   25364         320 :                   return true;
   25365             :                }
   25366             :                else
   25367             :                {
   25368           0 :                   set_error(make_error(
   25369             :                      parser_error::e_syntax,
   25370           0 :                      current_token(),
   25371             :                      "ERR018 - Failed to find variable node in symbol table",
   25372             :                      exprtk_error_location));
   25373             : 
   25374           0 :                   free_node(node_allocator_,node);
   25375             : 
   25376           0 :                   return false;
   25377             :                }
   25378             :             }
   25379             :          }
   25380             : 
   25381           0 :          return false;
   25382             :       }
   25383             : 
   25384    23486486 :       static inline expression_node_ptr error_node()
   25385             :       {
   25386    23486486 :          return reinterpret_cast<expression_node_ptr>(0);
   25387             :       }
   25388             : 
   25389             :       struct scoped_expression_delete
   25390             :       {
   25391        1195 :          scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
   25392        1195 :          : delete_ptr(true)
   25393        1195 :          , parser_(pr)
   25394        1195 :          , expression_(expression)
   25395        1195 :          {}
   25396             : 
   25397        1195 :         ~scoped_expression_delete()
   25398             :          {
   25399        1195 :             if (delete_ptr)
   25400             :             {
   25401           0 :                free_node(parser_.node_allocator_, expression_);
   25402             :             }
   25403        1195 :          }
   25404             : 
   25405             :          bool delete_ptr;
   25406             :          parser<T>& parser_;
   25407             :          expression_node_ptr& expression_;
   25408             : 
   25409             :       private:
   25410             : 
   25411             :          scoped_expression_delete(const scoped_expression_delete&) exprtk_delete;
   25412             :          scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete;
   25413             :       };
   25414             : 
   25415             :       template <typename Type, std::size_t N>
   25416             :       struct scoped_delete
   25417             :       {
   25418             :          typedef Type* ptr_t;
   25419             : 
   25420             :          scoped_delete(parser<T>& pr, ptr_t& p)
   25421             :          : delete_ptr(true)
   25422             :          , parser_(pr)
   25423             :          , p_(&p)
   25424             :          {}
   25425             : 
   25426      423974 :          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
   25427      423974 :          : delete_ptr(true)
   25428      423974 :          , parser_(pr)
   25429      423974 :          , p_(&p[0])
   25430      423974 :          {}
   25431             : 
   25432      423974 :         ~scoped_delete()
   25433             :          {
   25434      423974 :             if (delete_ptr)
   25435             :             {
   25436      109625 :                for (std::size_t i = 0; i < N; ++i)
   25437             :                {
   25438       87700 :                   free_node(parser_.node_allocator_, p_[i]);
   25439             :                }
   25440             :             }
   25441      423974 :          }
   25442             : 
   25443             :          bool delete_ptr;
   25444             :          parser<T>& parser_;
   25445             :          ptr_t* p_;
   25446             : 
   25447             :       private:
   25448             : 
   25449             :          scoped_delete(const scoped_delete<Type,N>&) exprtk_delete;
   25450             :          scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete;
   25451             :       };
   25452             : 
   25453             :       template <typename Type>
   25454             :       struct scoped_deq_delete
   25455             :       {
   25456             :          typedef Type* ptr_t;
   25457             : 
   25458             :          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
   25459             :          : delete_ptr(true)
   25460             :          , parser_(pr)
   25461             :          , deq_(deq)
   25462             :          {}
   25463             : 
   25464             :         ~scoped_deq_delete()
   25465             :          {
   25466             :             if (delete_ptr && !deq_.empty())
   25467             :             {
   25468             :                for (std::size_t i = 0; i < deq_.size(); ++i)
   25469             :                {
   25470             :                   free_node(parser_.node_allocator_,deq_[i]);
   25471             :                }
   25472             : 
   25473             :                deq_.clear();
   25474             :             }
   25475             :          }
   25476             : 
   25477             :          bool delete_ptr;
   25478             :          parser<T>& parser_;
   25479             :          std::deque<ptr_t>& deq_;
   25480             : 
   25481             :       private:
   25482             : 
   25483             :          scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete;
   25484             :          scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete;
   25485             :       };
   25486             : 
   25487             :       template <typename Type>
   25488             :       struct scoped_vec_delete
   25489             :       {
   25490             :          typedef Type* ptr_t;
   25491             : 
   25492      428715 :          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
   25493      428715 :          : delete_ptr(true)
   25494      428715 :          , parser_(pr)
   25495      428715 :          , vec_(vec)
   25496      428715 :          {}
   25497             : 
   25498      428715 :         ~scoped_vec_delete()
   25499             :          {
   25500      428715 :             if (delete_ptr && !vec_.empty())
   25501             :             {
   25502         273 :                for (std::size_t i = 0; i < vec_.size(); ++i)
   25503             :                {
   25504             :                   exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i])));
   25505         183 :                   free_node(parser_.node_allocator_,vec_[i]);
   25506             :                }
   25507             : 
   25508          90 :                vec_.clear();
   25509             :             }
   25510      428715 :          }
   25511             : 
   25512             :          ptr_t operator[](const std::size_t index)
   25513             :          {
   25514             :             return vec_[index];
   25515             :          }
   25516             : 
   25517             :          bool delete_ptr;
   25518             :          parser<T>& parser_;
   25519             :          std::vector<ptr_t>& vec_;
   25520             : 
   25521             :       private:
   25522             : 
   25523             :          scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete;
   25524             :          scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete;
   25525             :       };
   25526             : 
   25527             :       struct scoped_bool_negator
   25528             :       {
   25529         707 :          explicit scoped_bool_negator(bool& bb)
   25530         707 :          : b(bb)
   25531         707 :          { b = !b; }
   25532             : 
   25533         707 :         ~scoped_bool_negator()
   25534         707 :          { b = !b; }
   25535             : 
   25536             :          bool& b;
   25537             :       };
   25538             : 
   25539             :       struct scoped_bool_or_restorer
   25540             :       {
   25541       20944 :          explicit scoped_bool_or_restorer(bool& bb)
   25542       20944 :          : b(bb)
   25543       20944 :          , original_value_(bb)
   25544       20944 :          {}
   25545             : 
   25546       20944 :         ~scoped_bool_or_restorer()
   25547             :          {
   25548       20944 :             b = b || original_value_;
   25549       20944 :          }
   25550             : 
   25551             :          bool& b;
   25552             :          bool original_value_;
   25553             :       };
   25554             : 
   25555             :       struct scoped_inc_dec
   25556             :       {
   25557        2837 :          explicit scoped_inc_dec(std::size_t& v)
   25558        2837 :          : v_(v)
   25559        2837 :          { ++v_; }
   25560             : 
   25561        2837 :         ~scoped_inc_dec()
   25562             :          {
   25563        2837 :            assert(v_ > 0);
   25564        2837 :            --v_;
   25565        2837 :          }
   25566             : 
   25567             :          std::size_t& v_;
   25568             :       };
   25569             : 
   25570       60611 :       inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
   25571             :       {
   25572       60611 :          expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
   25573             : 
   25574       60611 :          switch (function->param_count)
   25575             :          {
   25576         231 :             case  0 : func_node = parse_function_call_0  (function,function_name); break;
   25577        5250 :             case  1 : func_node = parse_function_call< 1>(function,function_name); break;
   25578       40616 :             case  2 : func_node = parse_function_call< 2>(function,function_name); break;
   25579        1626 :             case  3 : func_node = parse_function_call< 3>(function,function_name); break;
   25580        1727 :             case  4 : func_node = parse_function_call< 4>(function,function_name); break;
   25581        1725 :             case  5 : func_node = parse_function_call< 5>(function,function_name); break;
   25582        1316 :             case  6 : func_node = parse_function_call< 6>(function,function_name); break;
   25583        1015 :             case  7 : func_node = parse_function_call< 7>(function,function_name); break;
   25584        1015 :             case  8 : func_node = parse_function_call< 8>(function,function_name); break;
   25585        1015 :             case  9 : func_node = parse_function_call< 9>(function,function_name); break;
   25586        1015 :             case 10 : func_node = parse_function_call<10>(function,function_name); break;
   25587        1015 :             case 11 : func_node = parse_function_call<11>(function,function_name); break;
   25588        1015 :             case 12 : func_node = parse_function_call<12>(function,function_name); break;
   25589        1015 :             case 13 : func_node = parse_function_call<13>(function,function_name); break;
   25590        1015 :             case 14 : func_node = parse_function_call<14>(function,function_name); break;
   25591           0 :             case 15 : func_node = parse_function_call<15>(function,function_name); break;
   25592           0 :             case 16 : func_node = parse_function_call<16>(function,function_name); break;
   25593           0 :             case 17 : func_node = parse_function_call<17>(function,function_name); break;
   25594           0 :             case 18 : func_node = parse_function_call<18>(function,function_name); break;
   25595           0 :             case 19 : func_node = parse_function_call<19>(function,function_name); break;
   25596           0 :             case 20 : func_node = parse_function_call<20>(function,function_name); break;
   25597           0 :             default : {
   25598           0 :                          set_error(make_error(
   25599             :                            parser_error::e_syntax,
   25600           0 :                            current_token(),
   25601             :                            "ERR019 - Invalid number of parameters for function: '" + function_name + "'",
   25602             :                            exprtk_error_location));
   25603             : 
   25604           0 :                          return error_node();
   25605             :                       }
   25606             :          }
   25607             : 
   25608       60611 :          if (func_node)
   25609       60611 :             return func_node;
   25610             :          else
   25611             :          {
   25612           0 :             set_error(make_error(
   25613             :                parser_error::e_syntax,
   25614           0 :                current_token(),
   25615             :                "ERR020 - Failed to generate call to function: '" + function_name + "'",
   25616             :                exprtk_error_location));
   25617             : 
   25618           0 :             return error_node();
   25619             :          }
   25620             :       }
   25621             : 
   25622             :       template <std::size_t NumberofParameters>
   25623       60380 :       inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
   25624             :       {
   25625             :          #ifdef _MSC_VER
   25626             :             #pragma warning(push)
   25627             :             #pragma warning(disable: 4127)
   25628             :          #endif
   25629             :          if (0 == NumberofParameters)
   25630             :          {
   25631             :             set_error(make_error(
   25632             :                parser_error::e_syntax,
   25633             :                current_token(),
   25634             :                "ERR021 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
   25635             :                exprtk_error_location));
   25636             : 
   25637             :             return error_node();
   25638             :          }
   25639             :          #ifdef _MSC_VER
   25640             :             #pragma warning(pop)
   25641             :          #endif
   25642             : 
   25643             :          expression_node_ptr branch[NumberofParameters];
   25644       60380 :          expression_node_ptr result  = error_node();
   25645             : 
   25646       60380 :          std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
   25647             : 
   25648       60380 :          scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
   25649             : 
   25650       60380 :          next_token();
   25651             : 
   25652       60380 :          if (!token_is(token_t::e_lbracket))
   25653             :          {
   25654           0 :             set_error(make_error(
   25655             :                parser_error::e_syntax,
   25656           0 :                current_token(),
   25657             :                "ERR022 - Expecting argument list for function: '" + function_name + "'",
   25658             :                exprtk_error_location));
   25659             : 
   25660           0 :             return error_node();
   25661             :          }
   25662             : 
   25663      260429 :          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
   25664             :          {
   25665      200049 :             branch[i] = parse_expression();
   25666             : 
   25667      200049 :             if (0 == branch[i])
   25668             :             {
   25669           0 :                set_error(make_error(
   25670             :                   parser_error::e_syntax,
   25671           0 :                   current_token(),
   25672             :                   "ERR023 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
   25673             :                   exprtk_error_location));
   25674             : 
   25675           0 :                return error_node();
   25676             :             }
   25677      200049 :             else if (i < static_cast<int>(NumberofParameters - 1))
   25678             :             {
   25679      139669 :                if (!token_is(token_t::e_comma))
   25680             :                {
   25681           0 :                   set_error(make_error(
   25682             :                      parser_error::e_syntax,
   25683           0 :                      current_token(),
   25684             :                      "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
   25685             :                      exprtk_error_location));
   25686             : 
   25687           0 :                   return error_node();
   25688             :                }
   25689             :             }
   25690             :          }
   25691             : 
   25692       60380 :          if (!token_is(token_t::e_rbracket))
   25693             :          {
   25694           0 :             set_error(make_error(
   25695             :                parser_error::e_syntax,
   25696           0 :                current_token(),
   25697             :                "ERR025 - Invalid number of arguments for function: '" + function_name + "'",
   25698             :                exprtk_error_location));
   25699             : 
   25700           0 :             return error_node();
   25701             :          }
   25702             :          else
   25703       60380 :             result = expression_generator_.function(function,branch);
   25704             : 
   25705       60380 :          sd.delete_ptr = (0 == result);
   25706             : 
   25707       60380 :          return result;
   25708       60380 :       }
   25709             : 
   25710         231 :       inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
   25711             :       {
   25712         231 :          expression_node_ptr result = expression_generator_.function(function);
   25713             : 
   25714         231 :          state_.side_effect_present = function->has_side_effects();
   25715             : 
   25716         231 :          next_token();
   25717             : 
   25718         231 :          if (
   25719         347 :                token_is(token_t::e_lbracket) &&
   25720         347 :               !token_is(token_t::e_rbracket)
   25721             :             )
   25722             :          {
   25723           0 :             set_error(make_error(
   25724             :                parser_error::e_syntax,
   25725           0 :                current_token(),
   25726             :                "ERR026 - Expecting '()' to proceed call to function: '" + function_name + "'",
   25727             :                exprtk_error_location));
   25728             : 
   25729           0 :             free_node(node_allocator_,result);
   25730             : 
   25731           0 :             return error_node();
   25732             :          }
   25733             :          else
   25734         231 :             return result;
   25735             :       }
   25736             : 
   25737             :       template <std::size_t MaxNumberofParameters>
   25738      359349 :       inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
   25739             :       {
   25740      359349 :          std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
   25741             : 
   25742      359349 :          scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
   25743             : 
   25744      359349 :          next_token();
   25745             : 
   25746      359349 :          if (!token_is(token_t::e_lbracket))
   25747             :          {
   25748           0 :             set_error(make_error(
   25749             :                parser_error::e_syntax,
   25750           0 :                current_token(),
   25751             :                "ERR027 - Expected a '(' at start of function call to '" + function_name  +
   25752           0 :                "', instead got: '" + current_token().value + "'",
   25753             :                exprtk_error_location));
   25754             : 
   25755           0 :             return 0;
   25756             :          }
   25757             : 
   25758      359349 :          if (token_is(token_t::e_rbracket, e_hold))
   25759             :          {
   25760           0 :             set_error(make_error(
   25761             :                parser_error::e_syntax,
   25762           0 :                current_token(),
   25763             :                "ERR028 - Expected at least one input parameter for function call '" + function_name + "'",
   25764             :                exprtk_error_location));
   25765             : 
   25766           0 :             return 0;
   25767             :          }
   25768             : 
   25769      359349 :          std::size_t param_index = 0;
   25770             : 
   25771      626882 :          for (; param_index < MaxNumberofParameters; ++param_index)
   25772             :          {
   25773      626882 :             param_list[param_index] = parse_expression();
   25774             : 
   25775      626882 :             if (0 == param_list[param_index])
   25776       21919 :                return 0;
   25777      604963 :             else if (token_is(token_t::e_rbracket))
   25778             :             {
   25779      337424 :                sd.delete_ptr = false;
   25780      337424 :                break;
   25781             :             }
   25782      267539 :             else if (token_is(token_t::e_comma))
   25783      267533 :                continue;
   25784             :             else
   25785             :             {
   25786          18 :                set_error(make_error(
   25787             :                   parser_error::e_syntax,
   25788           6 :                   current_token(),
   25789           6 :                   "ERR029 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
   25790             :                   exprtk_error_location));
   25791             : 
   25792           6 :                return 0;
   25793             :             }
   25794             :          }
   25795             : 
   25796      337424 :          if (sd.delete_ptr)
   25797             :          {
   25798           0 :             set_error(make_error(
   25799             :                parser_error::e_syntax,
   25800           0 :                current_token(),
   25801             :                "ERR030 - Invalid number of input parameters passed to function '" + function_name  + "'",
   25802             :                exprtk_error_location));
   25803             : 
   25804           0 :             return 0;
   25805             :          }
   25806             : 
   25807      337424 :          return (param_index + 1);
   25808      359349 :       }
   25809             : 
   25810      359349 :       inline expression_node_ptr parse_base_operation()
   25811             :       {
   25812             :          typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
   25813             : 
   25814      359349 :          const std::string operation_name   = current_token().value;
   25815      359349 :          const token_t     diagnostic_token = current_token();
   25816             : 
   25817      359349 :          map_range_t itr_range = base_ops_map_.equal_range(operation_name);
   25818             : 
   25819      359349 :          if (0 == std::distance(itr_range.first,itr_range.second))
   25820             :          {
   25821           0 :             set_error(make_error(
   25822             :                parser_error::e_syntax,
   25823             :                diagnostic_token,
   25824             :                "ERR031 - No entry found for base operation: " + operation_name,
   25825             :                exprtk_error_location));
   25826             : 
   25827           0 :             return error_node();
   25828             :          }
   25829             : 
   25830             :          static const std::size_t MaxNumberofParameters = 4;
   25831      359349 :          expression_node_ptr param_list[MaxNumberofParameters] = {0};
   25832             : 
   25833      359349 :          const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
   25834             : 
   25835      359349 :          if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
   25836             :          {
   25837      337424 :             for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
   25838             :             {
   25839      337424 :                const details::base_operation_t& operation = itr->second;
   25840             : 
   25841      337424 :                if (operation.num_params == parameter_count)
   25842             :                {
   25843      337424 :                   switch (parameter_count)
   25844             :                   {
   25845             :                      #define base_opr_case(N)                                         \
   25846             :                      case N : {                                                       \
   25847             :                                  expression_node_ptr pl##N[N] = {0};                  \
   25848             :                                  std::copy(param_list, param_list + N, pl##N);        \
   25849             :                                  lodge_symbol(operation_name, e_st_function);         \
   25850             :                                  return expression_generator_(operation.type, pl##N); \
   25851             :                               }                                                       \
   25852             : 
   25853       70362 :                      base_opr_case(1)
   25854      266591 :                      base_opr_case(2)
   25855         471 :                      base_opr_case(3)
   25856           0 :                      base_opr_case(4)
   25857             :                      #undef base_opr_case
   25858             :                   }
   25859             :                }
   25860             :             }
   25861             :          }
   25862             : 
   25863      109625 :          for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
   25864             :          {
   25865       87700 :             free_node(node_allocator_, param_list[i]);
   25866             :          }
   25867             : 
   25868       21925 :          set_error(make_error(
   25869             :             parser_error::e_syntax,
   25870             :             diagnostic_token,
   25871             :             "ERR032 - Invalid number of input parameters for call to function: '" + operation_name + "'",
   25872             :             exprtk_error_location));
   25873             : 
   25874       21925 :          return error_node();
   25875      359349 :       }
   25876             : 
   25877        1356 :       inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
   25878             :       {
   25879             :          // Parse: [if][(][condition][,][consequent][,][alternative][)]
   25880             : 
   25881        1356 :          expression_node_ptr consequent  = error_node();
   25882        1356 :          expression_node_ptr alternative = error_node();
   25883             : 
   25884        1356 :          bool result = true;
   25885             : 
   25886        1356 :          if (!token_is(token_t::e_comma))
   25887             :          {
   25888           0 :             set_error(make_error(
   25889             :                parser_error::e_syntax,
   25890           0 :                current_token(),
   25891             :                "ERR033 - Expected ',' between if-statement condition and consequent",
   25892             :                exprtk_error_location));
   25893             : 
   25894           0 :             result = false;
   25895             :          }
   25896        1356 :          else if (0 == (consequent = parse_expression()))
   25897             :          {
   25898           0 :             set_error(make_error(
   25899             :                parser_error::e_syntax,
   25900           0 :                current_token(),
   25901             :                "ERR034 - Failed to parse consequent for if-statement",
   25902             :                exprtk_error_location));
   25903             : 
   25904           0 :             result = false;
   25905             :          }
   25906        1356 :          else if (!token_is(token_t::e_comma))
   25907             :          {
   25908           0 :             set_error(make_error(
   25909             :                parser_error::e_syntax,
   25910           0 :                current_token(),
   25911             :                "ERR035 - Expected ',' between if-statement consequent and alternative",
   25912             :                exprtk_error_location));
   25913             : 
   25914           0 :             result = false;
   25915             :          }
   25916        1356 :          else if (0 == (alternative = parse_expression()))
   25917             :          {
   25918           0 :             set_error(make_error(
   25919             :                parser_error::e_syntax,
   25920           0 :                current_token(),
   25921             :                "ERR036 - Failed to parse alternative for if-statement",
   25922             :                exprtk_error_location));
   25923             : 
   25924           0 :             result = false;
   25925             :          }
   25926        1356 :          else if (!token_is(token_t::e_rbracket))
   25927             :          {
   25928           0 :             set_error(make_error(
   25929             :                parser_error::e_syntax,
   25930           0 :                current_token(),
   25931             :                "ERR037 - Expected ')' at the end of if-statement",
   25932             :                exprtk_error_location));
   25933             : 
   25934           0 :             result = false;
   25935             :          }
   25936             : 
   25937             :          #ifndef exprtk_disable_string_capabilities
   25938        1356 :          if (result)
   25939             :          {
   25940        1356 :             const bool consq_is_str = is_generally_string_node(consequent );
   25941        1356 :             const bool alter_is_str = is_generally_string_node(alternative);
   25942             : 
   25943        1356 :             if (consq_is_str || alter_is_str)
   25944             :             {
   25945           0 :                if (consq_is_str && alter_is_str)
   25946             :                {
   25947           0 :                   expression_node_ptr result_node =
   25948             :                      expression_generator_
   25949           0 :                         .conditional_string(condition, consequent, alternative);
   25950             : 
   25951           0 :                   if (result_node && result_node->valid())
   25952             :                   {
   25953           0 :                      return result_node;
   25954             :                   }
   25955             : 
   25956           0 :                   set_error(make_error(
   25957             :                      parser_error::e_synthesis,
   25958           0 :                      current_token(),
   25959             :                      "ERR038 - Failed to synthesize node: conditional_string",
   25960             :                      exprtk_error_location));
   25961             : 
   25962           0 :                   free_node(node_allocator_, result_node);
   25963           0 :                   return error_node();
   25964             :                }
   25965             : 
   25966           0 :                set_error(make_error(
   25967             :                   parser_error::e_syntax,
   25968           0 :                   current_token(),
   25969             :                   "ERR039 - Return types of if-statement differ: string/non-string",
   25970             :                   exprtk_error_location));
   25971             : 
   25972           0 :                result = false;
   25973             :             }
   25974             :          }
   25975             :          #endif
   25976             : 
   25977        1356 :          if (result)
   25978             :          {
   25979        1356 :             const bool consq_is_vec = is_ivector_node(consequent );
   25980        1356 :             const bool alter_is_vec = is_ivector_node(alternative);
   25981             : 
   25982        1356 :             if (consq_is_vec || alter_is_vec)
   25983             :             {
   25984         800 :                if (consq_is_vec && alter_is_vec)
   25985             :                {
   25986             :                   return expression_generator_
   25987         800 :                            .conditional_vector(condition, consequent, alternative);
   25988             :                }
   25989             : 
   25990           0 :                set_error(make_error(
   25991             :                   parser_error::e_syntax,
   25992           0 :                   current_token(),
   25993             :                   "ERR040 - Return types of if-statement differ: vector/non-vector",
   25994             :                   exprtk_error_location));
   25995             : 
   25996           0 :                result = false;
   25997             :             }
   25998             :          }
   25999             : 
   26000         556 :          if (!result)
   26001             :          {
   26002           0 :             free_node(node_allocator_, condition  );
   26003           0 :             free_node(node_allocator_, consequent );
   26004           0 :             free_node(node_allocator_, alternative);
   26005             : 
   26006           0 :             return error_node();
   26007             :          }
   26008             :          else
   26009             :             return expression_generator_
   26010         556 :                       .conditional(condition, consequent, alternative);
   26011             :       }
   26012             : 
   26013        4434 :       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
   26014             :       {
   26015        4434 :          expression_node_ptr consequent  = error_node();
   26016        4434 :          expression_node_ptr alternative = error_node();
   26017             : 
   26018        4434 :          bool result = true;
   26019             : 
   26020        4434 :          if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
   26021             :          {
   26022        5888 :             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
   26023             :             {
   26024           0 :                set_error(make_error(
   26025             :                   parser_error::e_syntax,
   26026           0 :                   current_token(),
   26027             :                   "ERR041 - Failed to parse body of consequent for if-statement",
   26028             :                   exprtk_error_location));
   26029             : 
   26030           0 :                result = false;
   26031             :             }
   26032        2944 :             else if
   26033             :             (
   26034        5914 :               !settings_.commutative_check_enabled()           &&
   26035        2983 :               !token_is("else",prsrhlpr_t::e_hold)             &&
   26036          10 :               !token_is_loop(prsrhlpr_t::e_hold)               &&
   26037          10 :               !token_is_arithmetic_opr(prsrhlpr_t::e_hold)     &&
   26038          10 :               !token_is_right_bracket (prsrhlpr_t::e_hold)     &&
   26039          10 :               !token_is_ineq_opr      (prsrhlpr_t::e_hold)     &&
   26040        2967 :               !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
   26041        2954 :               !token_is(token_t::e_eof)
   26042             :             )
   26043             :             {
   26044          32 :                set_error(make_error(
   26045             :                   parser_error::e_syntax,
   26046           8 :                   current_token(),
   26047             :                   "ERR042 - Expected ';' at the end of the consequent for if-statement (1)",
   26048             :                   exprtk_error_location));
   26049             : 
   26050           8 :                result = false;
   26051             :             }
   26052             :          }
   26053             :          else
   26054             :          {
   26055        1490 :             if (
   26056        2978 :                  settings_.commutative_check_enabled() &&
   26057        2978 :                  token_is(token_t::e_mul,prsrhlpr_t::e_hold)
   26058             :                )
   26059             :             {
   26060        1362 :                next_token();
   26061             :             }
   26062             : 
   26063        1490 :             if (0 != (consequent = parse_expression()))
   26064             :             {
   26065        1490 :                if (!token_is(token_t::e_eof))
   26066             :                {
   26067           8 :                   set_error(make_error(
   26068             :                      parser_error::e_syntax,
   26069           2 :                      current_token(),
   26070             :                      "ERR043 - Expected ';' at the end of the consequent for if-statement (2)",
   26071             :                      exprtk_error_location));
   26072             : 
   26073           2 :                   result = false;
   26074             :                }
   26075             :             }
   26076             :             else
   26077             :             {
   26078           0 :                set_error(make_error(
   26079             :                   parser_error::e_syntax,
   26080           0 :                   current_token(),
   26081             :                   "ERR044 - Failed to parse body of consequent for if-statement",
   26082             :                   exprtk_error_location));
   26083             : 
   26084           0 :                result = false;
   26085             :             }
   26086             :          }
   26087             : 
   26088        4434 :          if (result)
   26089             :          {
   26090        8848 :             if (details::imatch(current_token().value,"else"))
   26091             :             {
   26092        2972 :                next_token();
   26093             : 
   26094        2972 :                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
   26095             :                {
   26096        1810 :                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
   26097             :                   {
   26098           0 :                      set_error(make_error(
   26099             :                         parser_error::e_syntax,
   26100           0 :                         current_token(),
   26101             :                         "ERR045 - Failed to parse body of the 'else' for if-statement",
   26102             :                         exprtk_error_location));
   26103             : 
   26104           0 :                      result = false;
   26105             :                   }
   26106             :                }
   26107        4134 :                else if (details::imatch(current_token().value,"if"))
   26108             :                {
   26109         563 :                   if (0 == (alternative = parse_conditional_statement()))
   26110             :                   {
   26111          12 :                      set_error(make_error(
   26112             :                         parser_error::e_syntax,
   26113           3 :                         current_token(),
   26114             :                         "ERR046 - Failed to parse body of if-else statement",
   26115             :                         exprtk_error_location));
   26116             : 
   26117           3 :                      result = false;
   26118             :                   }
   26119             :                }
   26120        1504 :                else if (0 != (alternative = parse_expression()))
   26121             :                {
   26122        1504 :                   if (
   26123        3008 :                        !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
   26124        3008 :                        !token_is(token_t::e_eof)
   26125             :                      )
   26126             :                   {
   26127           0 :                      set_error(make_error(
   26128             :                         parser_error::e_syntax,
   26129           0 :                         current_token(),
   26130             :                         "ERR047 - Expected ';' at the end of the 'else-if' for the if-statement",
   26131             :                         exprtk_error_location));
   26132             : 
   26133           0 :                      result = false;
   26134             :                   }
   26135             :                }
   26136             :                else
   26137             :                {
   26138           0 :                   set_error(make_error(
   26139             :                      parser_error::e_syntax,
   26140           0 :                      current_token(),
   26141             :                      "ERR048 - Failed to parse body of the 'else' for if-statement",
   26142             :                      exprtk_error_location));
   26143             : 
   26144           0 :                   result = false;
   26145             :                }
   26146             :             }
   26147             :          }
   26148             : 
   26149             :          #ifndef exprtk_disable_string_capabilities
   26150        4434 :          if (result)
   26151             :          {
   26152        4421 :             const bool consq_is_str = is_generally_string_node(consequent );
   26153        4421 :             const bool alter_is_str = is_generally_string_node(alternative);
   26154             : 
   26155        4421 :             if (consq_is_str || alter_is_str)
   26156             :             {
   26157          45 :                if (consq_is_str && alter_is_str)
   26158             :                {
   26159             :                   return expression_generator_
   26160          45 :                            .conditional_string(condition, consequent, alternative);
   26161             :                }
   26162             : 
   26163           0 :                set_error(make_error(
   26164             :                   parser_error::e_syntax,
   26165           0 :                   current_token(),
   26166             :                   "ERR049 - Return types of if-statement differ: string/non-string",
   26167             :                   exprtk_error_location));
   26168             : 
   26169           0 :                result = false;
   26170             :             }
   26171             :          }
   26172             :          #endif
   26173             : 
   26174        4389 :          if (result)
   26175             :          {
   26176        4376 :             const bool consq_is_vec = is_ivector_node(consequent );
   26177        4376 :             const bool alter_is_vec = is_ivector_node(alternative);
   26178             : 
   26179        4376 :             if (consq_is_vec || alter_is_vec)
   26180             :             {
   26181         813 :                if (consq_is_vec && alter_is_vec)
   26182             :                {
   26183             :                   return expression_generator_
   26184         813 :                            .conditional_vector(condition, consequent, alternative);
   26185             :                }
   26186             : 
   26187           0 :                set_error(make_error(
   26188             :                   parser_error::e_syntax,
   26189           0 :                   current_token(),
   26190             :                   "ERR050 - Return types of if-statement differ: vector/non-vector",
   26191             :                   exprtk_error_location));
   26192             : 
   26193           0 :                result = false;
   26194             :             }
   26195             :          }
   26196             : 
   26197        3576 :          if (!result)
   26198             :          {
   26199          13 :             free_node(node_allocator_, condition  );
   26200          13 :             free_node(node_allocator_, consequent );
   26201          13 :             free_node(node_allocator_, alternative);
   26202             : 
   26203          13 :             return error_node();
   26204             :          }
   26205             :          else
   26206             :             return expression_generator_
   26207        3563 :                       .conditional(condition, consequent, alternative);
   26208             :       }
   26209             : 
   26210        5790 :       inline expression_node_ptr parse_conditional_statement()
   26211             :       {
   26212        5790 :          expression_node_ptr condition = error_node();
   26213             : 
   26214        5790 :          next_token();
   26215             : 
   26216        5790 :          if (!token_is(token_t::e_lbracket))
   26217             :          {
   26218           0 :             set_error(make_error(
   26219             :                parser_error::e_syntax,
   26220           0 :                current_token(),
   26221           0 :                "ERR051 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
   26222             :                exprtk_error_location));
   26223             : 
   26224           0 :             return error_node();
   26225             :          }
   26226        5790 :          else if (0 == (condition = parse_expression()))
   26227             :          {
   26228           0 :             set_error(make_error(
   26229             :                parser_error::e_syntax,
   26230           0 :                current_token(),
   26231             :                "ERR052 - Failed to parse condition for if-statement",
   26232             :                exprtk_error_location));
   26233             : 
   26234           0 :             return error_node();
   26235             :          }
   26236        5790 :          else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
   26237             :          {
   26238             :             // if (x,y,z)
   26239        1356 :             return parse_conditional_statement_01(condition);
   26240             :          }
   26241        4434 :          else if (token_is(token_t::e_rbracket))
   26242             :          {
   26243             :             /*
   26244             :                00. if (x) y;
   26245             :                01. if (x) y; else z;
   26246             :                02. if (x) y; else {z0; ... zn;}
   26247             :                03. if (x) y; else if (z) w;
   26248             :                04. if (x) y; else if (z) w; else u;
   26249             :                05. if (x) y; else if (z) w; else {u0; ... un;}
   26250             :                06. if (x) y; else if (z) {w0; ... wn;}
   26251             :                07. if (x) {y0; ... yn;}
   26252             :                08. if (x) {y0; ... yn;} else z;
   26253             :                09. if (x) {y0; ... yn;} else {z0; ... zn;};
   26254             :                10. if (x) {y0; ... yn;} else if (z) w;
   26255             :                11. if (x) {y0; ... yn;} else if (z) w; else u;
   26256             :                12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
   26257             :                13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
   26258             :             */
   26259        4434 :             return parse_conditional_statement_02(condition);
   26260             :          }
   26261             : 
   26262           0 :          set_error(make_error(
   26263             :             parser_error::e_syntax,
   26264           0 :             current_token(),
   26265             :             "ERR053 - Invalid if-statement",
   26266             :             exprtk_error_location));
   26267             : 
   26268           0 :          free_node(node_allocator_,condition);
   26269             : 
   26270           0 :          return error_node();
   26271             :       }
   26272             : 
   26273        2811 :       inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
   26274             :       {
   26275             :          // Parse: [condition][?][consequent][:][alternative]
   26276        2811 :          expression_node_ptr consequent  = error_node();
   26277        2811 :          expression_node_ptr alternative = error_node();
   26278             : 
   26279        2811 :          bool result = true;
   26280             : 
   26281        2811 :          if (0 == condition)
   26282             :          {
   26283           0 :             set_error(make_error(
   26284             :                parser_error::e_syntax,
   26285           0 :                current_token(),
   26286             :                "ERR054 - Encountered invalid condition branch for ternary if-statement",
   26287             :                exprtk_error_location));
   26288             : 
   26289           0 :             return error_node();
   26290             :          }
   26291        2811 :          else if (!token_is(token_t::e_ternary))
   26292             :          {
   26293           0 :             set_error(make_error(
   26294             :                parser_error::e_syntax,
   26295           0 :                current_token(),
   26296             :                "ERR055 - Expected '?' after condition of ternary if-statement",
   26297             :                exprtk_error_location));
   26298             : 
   26299           0 :             result = false;
   26300             :          }
   26301        2811 :          else if (0 == (consequent = parse_expression()))
   26302             :          {
   26303          56 :             set_error(make_error(
   26304             :                parser_error::e_syntax,
   26305          14 :                current_token(),
   26306             :                "ERR056 - Failed to parse consequent for ternary if-statement",
   26307             :                exprtk_error_location));
   26308             : 
   26309          14 :             result = false;
   26310             :          }
   26311        2797 :          else if (!token_is(token_t::e_colon))
   26312             :          {
   26313          64 :             set_error(make_error(
   26314             :                parser_error::e_syntax,
   26315          16 :                current_token(),
   26316             :                "ERR057 - Expected ':' between ternary if-statement consequent and alternative",
   26317             :                exprtk_error_location));
   26318             : 
   26319          16 :             result = false;
   26320             :          }
   26321        2781 :          else if (0 == (alternative = parse_expression()))
   26322             :          {
   26323           0 :             set_error(make_error(
   26324             :                parser_error::e_syntax,
   26325           0 :                current_token(),
   26326             :                "ERR058 - Failed to parse alternative for ternary if-statement",
   26327             :                exprtk_error_location));
   26328             : 
   26329           0 :             result = false;
   26330             :          }
   26331             : 
   26332             :          #ifndef exprtk_disable_string_capabilities
   26333        2811 :          if (result)
   26334             :          {
   26335        2781 :             const bool consq_is_str = is_generally_string_node(consequent );
   26336        2781 :             const bool alter_is_str = is_generally_string_node(alternative);
   26337             : 
   26338        2781 :             if (consq_is_str || alter_is_str)
   26339             :             {
   26340        1106 :                if (consq_is_str && alter_is_str)
   26341             :                {
   26342             :                   return expression_generator_
   26343        1106 :                            .conditional_string(condition, consequent, alternative);
   26344             :                }
   26345             : 
   26346           0 :                set_error(make_error(
   26347             :                   parser_error::e_syntax,
   26348           0 :                   current_token(),
   26349             :                   "ERR059 - Return types of ternary differ: string/non-string",
   26350             :                   exprtk_error_location));
   26351             : 
   26352           0 :                result = false;
   26353             :             }
   26354             :          }
   26355             :          #endif
   26356             : 
   26357        1705 :          if (result)
   26358             :          {
   26359        1675 :             const bool consq_is_vec = is_ivector_node(consequent );
   26360        1675 :             const bool alter_is_vec = is_ivector_node(alternative);
   26361             : 
   26362        1675 :             if (consq_is_vec || alter_is_vec)
   26363             :             {
   26364         160 :                if (consq_is_vec && alter_is_vec)
   26365             :                {
   26366             :                   return expression_generator_
   26367         160 :                            .conditional_vector(condition, consequent, alternative);
   26368             :                }
   26369             : 
   26370           0 :                set_error(make_error(
   26371             :                   parser_error::e_syntax,
   26372           0 :                   current_token(),
   26373             :                   "ERR060 - Return types of ternary differ: vector/non-vector",
   26374             :                   exprtk_error_location));
   26375             : 
   26376           0 :                result = false;
   26377             :             }
   26378             :          }
   26379             : 
   26380        1545 :          if (!result)
   26381             :          {
   26382          30 :             free_node(node_allocator_, condition  );
   26383          30 :             free_node(node_allocator_, consequent );
   26384          30 :             free_node(node_allocator_, alternative);
   26385             : 
   26386          30 :             return error_node();
   26387             :          }
   26388             :          else
   26389             :             return expression_generator_
   26390        1515 :                       .conditional(condition, consequent, alternative);
   26391             :       }
   26392             : 
   26393         728 :       inline expression_node_ptr parse_not_statement()
   26394             :       {
   26395        2184 :          if (settings_.logic_disabled("not"))
   26396             :          {
   26397           0 :             set_error(make_error(
   26398             :                parser_error::e_syntax,
   26399           0 :                current_token(),
   26400             :                "ERR061 - Invalid or disabled logic operation 'not'",
   26401             :                exprtk_error_location));
   26402             : 
   26403           0 :             return error_node();
   26404             :          }
   26405             : 
   26406         728 :          return parse_base_operation();
   26407             :       }
   26408             : 
   26409        2827 :       void handle_brkcnt_scope_exit()
   26410             :       {
   26411        2827 :          assert(!brkcnt_list_.empty());
   26412        2827 :          brkcnt_list_.pop_front();
   26413        2827 :       }
   26414             : 
   26415          22 :       inline expression_node_ptr parse_while_loop()
   26416             :       {
   26417             :          // Parse: [while][(][test expr][)][{][expression][}]
   26418          22 :          expression_node_ptr condition   = error_node();
   26419          22 :          expression_node_ptr branch      = error_node();
   26420          22 :          expression_node_ptr result_node = error_node();
   26421             : 
   26422          22 :          bool result = true;
   26423             : 
   26424          22 :          next_token();
   26425             : 
   26426          22 :          if (!token_is(token_t::e_lbracket))
   26427             :          {
   26428           0 :             set_error(make_error(
   26429             :                parser_error::e_syntax,
   26430           0 :                current_token(),
   26431             :                "ERR062 - Expected '(' at start of while-loop condition statement",
   26432             :                exprtk_error_location));
   26433             : 
   26434           0 :             return error_node();
   26435             :          }
   26436          22 :          else if (0 == (condition = parse_expression()))
   26437             :          {
   26438           0 :             set_error(make_error(
   26439             :                parser_error::e_syntax,
   26440           0 :                current_token(),
   26441             :                "ERR063 - Failed to parse condition for while-loop",
   26442             :                exprtk_error_location));
   26443             : 
   26444           0 :             return error_node();
   26445             :          }
   26446          22 :          else if (!token_is(token_t::e_rbracket))
   26447             :          {
   26448           0 :             set_error(make_error(
   26449             :                parser_error::e_syntax,
   26450           0 :                current_token(),
   26451             :                "ERR064 - Expected ')' at end of while-loop condition statement",
   26452             :                exprtk_error_location));
   26453             : 
   26454           0 :             result = false;
   26455             :          }
   26456             : 
   26457          22 :          brkcnt_list_.push_front(false);
   26458             : 
   26459          22 :          if (result)
   26460             :          {
   26461          22 :             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
   26462             : 
   26463          44 :             if (0 == (branch = parse_multi_sequence("while-loop", true)))
   26464             :             {
   26465           0 :                set_error(make_error(
   26466             :                   parser_error::e_syntax,
   26467           0 :                   current_token(),
   26468             :                   "ERR065 - Failed to parse body of while-loop"));
   26469           0 :                result = false;
   26470             :             }
   26471          22 :             else if (0 == (result_node = expression_generator_.while_loop(condition,
   26472             :                                                                           branch,
   26473          22 :                                                                           brkcnt_list_.front())))
   26474             :             {
   26475           0 :                set_error(make_error(
   26476             :                   parser_error::e_syntax,
   26477           0 :                   current_token(),
   26478             :                   "ERR066 - Failed to synthesize while-loop",
   26479             :                   exprtk_error_location));
   26480             : 
   26481           0 :                result = false;
   26482             :             }
   26483          22 :          }
   26484             : 
   26485          22 :          handle_brkcnt_scope_exit();
   26486             : 
   26487          22 :          if (!result)
   26488             :          {
   26489           0 :             free_node(node_allocator_, branch     );
   26490           0 :             free_node(node_allocator_, condition  );
   26491           0 :             free_node(node_allocator_, result_node);
   26492             : 
   26493           0 :             return error_node();
   26494             :          }
   26495             : 
   26496          22 :          if (result_node && result_node->valid())
   26497             :          {
   26498          22 :             return result_node;
   26499             :          }
   26500             : 
   26501           0 :          set_error(make_error(
   26502             :             parser_error::e_synthesis,
   26503           0 :             current_token(),
   26504             :             "ERR067 - Failed to synthesize 'valid' while-loop",
   26505             :             exprtk_error_location));
   26506             : 
   26507           0 :          free_node(node_allocator_, result_node);
   26508             : 
   26509           0 :          return error_node();
   26510             :       }
   26511             : 
   26512          92 :       inline expression_node_ptr parse_repeat_until_loop()
   26513             :       {
   26514             :          // Parse: [repeat][{][expression][}][until][(][test expr][)]
   26515          92 :          expression_node_ptr condition = error_node();
   26516          92 :          expression_node_ptr branch    = error_node();
   26517          92 :          next_token();
   26518             : 
   26519          92 :          std::vector<expression_node_ptr> arg_list;
   26520          92 :          std::vector<bool> side_effect_list;
   26521             : 
   26522          92 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   26523             : 
   26524          92 :          brkcnt_list_.push_front(false);
   26525             : 
   26526         184 :          if (details::imatch(current_token().value,"until"))
   26527             :          {
   26528           0 :             next_token();
   26529           0 :             branch = node_allocator_.allocate<details::null_node<T> >();
   26530             :          }
   26531             :          else
   26532             :          {
   26533          92 :             const token_t::token_type separator = token_t::e_eof;
   26534             : 
   26535          92 :             scope_handler sh(*this);
   26536             : 
   26537          92 :             scoped_bool_or_restorer sbr(state_.side_effect_present);
   26538             : 
   26539          92 :             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
   26540             : 
   26541         101 :             for ( ; ; )
   26542             :             {
   26543         193 :                state_.side_effect_present = false;
   26544             : 
   26545         193 :                expression_node_ptr arg = parse_expression();
   26546             : 
   26547         193 :                if (0 == arg)
   26548          10 :                   return error_node();
   26549             :                else
   26550             :                {
   26551         183 :                   arg_list.push_back(arg);
   26552         183 :                   side_effect_list.push_back(state_.side_effect_present);
   26553             :                }
   26554             : 
   26555         366 :                if (details::imatch(current_token().value,"until"))
   26556             :                {
   26557          42 :                   next_token();
   26558          42 :                   break;
   26559             :                }
   26560             : 
   26561         196 :                const bool is_next_until = peek_token_is(token_t::e_symbol) &&
   26562         251 :                                           peek_token_is("until");
   26563             : 
   26564         141 :                if (!token_is(separator) && is_next_until)
   26565             :                {
   26566           0 :                   set_error(make_error(
   26567             :                      parser_error::e_syntax,
   26568           0 :                      current_token(),
   26569             :                      "ERR068 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop",
   26570             :                      exprtk_error_location));
   26571             : 
   26572           0 :                   return error_node();
   26573             :                }
   26574             : 
   26575         282 :                if (details::imatch(current_token().value,"until"))
   26576             :                {
   26577          40 :                   next_token();
   26578          40 :                   break;
   26579             :                }
   26580             :             }
   26581             : 
   26582          82 :             branch = simplify(arg_list,side_effect_list);
   26583             : 
   26584          82 :             sdd.delete_ptr = (0 == branch);
   26585             : 
   26586          82 :             if (sdd.delete_ptr)
   26587             :             {
   26588           0 :                set_error(make_error(
   26589             :                   parser_error::e_syntax,
   26590           0 :                   current_token(),
   26591             :                   "ERR069 - Failed to parse body of repeat until loop",
   26592             :                   exprtk_error_location));
   26593             : 
   26594           0 :                return error_node();
   26595             :             }
   26596         112 :          }
   26597             : 
   26598          82 :          if (!token_is(token_t::e_lbracket))
   26599             :          {
   26600           0 :             set_error(make_error(
   26601             :                parser_error::e_syntax,
   26602           0 :                current_token(),
   26603             :                "ERR070 - Expected '(' before condition statement of repeat until loop",
   26604             :                exprtk_error_location));
   26605             : 
   26606           0 :             free_node(node_allocator_,branch);
   26607           0 :             return error_node();
   26608             :          }
   26609          82 :          else if (0 == (condition = parse_expression()))
   26610             :          {
   26611           0 :             set_error(make_error(
   26612             :                parser_error::e_syntax,
   26613           0 :                current_token(),
   26614             :                "ERR071 - Failed to parse condition for repeat until loop",
   26615             :                exprtk_error_location));
   26616             : 
   26617           0 :             free_node(node_allocator_,branch);
   26618           0 :             return error_node();
   26619             :          }
   26620          82 :          else if (!token_is(token_t::e_rbracket))
   26621             :          {
   26622           0 :             set_error(make_error(
   26623             :                parser_error::e_syntax,
   26624           0 :                current_token(),
   26625             :                "ERR072 - Expected ')' after condition of repeat until loop",
   26626             :                exprtk_error_location));
   26627             : 
   26628           0 :             free_node(node_allocator_, branch   );
   26629           0 :             free_node(node_allocator_, condition);
   26630             : 
   26631           0 :             return error_node();
   26632             :          }
   26633             : 
   26634          82 :          expression_node_ptr result_node =
   26635             :             expression_generator_
   26636          82 :                .repeat_until_loop(
   26637             :                   condition,
   26638             :                   branch,
   26639          82 :                   brkcnt_list_.front());
   26640             : 
   26641          82 :          if (0 == result_node)
   26642             :          {
   26643           0 :             set_error(make_error(
   26644             :                parser_error::e_syntax,
   26645           0 :                current_token(),
   26646             :                "ERR073 - Failed to synthesize repeat until loop",
   26647             :                exprtk_error_location));
   26648             : 
   26649           0 :             free_node(node_allocator_,condition);
   26650             : 
   26651           0 :             return error_node();
   26652             :          }
   26653             : 
   26654          82 :          handle_brkcnt_scope_exit();
   26655             : 
   26656          82 :          if (result_node && result_node->valid())
   26657             :          {
   26658          82 :             return result_node;
   26659             :          }
   26660             : 
   26661           0 :          set_error(make_error(
   26662             :             parser_error::e_synthesis,
   26663           0 :             current_token(),
   26664             :             "ERR074 - Failed to synthesize 'valid' repeat until loop",
   26665             :             exprtk_error_location));
   26666             : 
   26667           0 :          free_node(node_allocator_, result_node);
   26668             : 
   26669           0 :          return error_node();
   26670          92 :       }
   26671             : 
   26672        2735 :       inline expression_node_ptr parse_for_loop()
   26673             :       {
   26674        2735 :          expression_node_ptr initialiser = error_node();
   26675        2735 :          expression_node_ptr condition   = error_node();
   26676        2735 :          expression_node_ptr incrementor = error_node();
   26677        2735 :          expression_node_ptr loop_body   = error_node();
   26678             : 
   26679        2735 :          scope_element* se = 0;
   26680        2735 :          bool result       = true;
   26681             : 
   26682        2735 :          next_token();
   26683             : 
   26684        2735 :          scope_handler sh(*this);
   26685             : 
   26686        2735 :          if (!token_is(token_t::e_lbracket))
   26687             :          {
   26688           0 :             set_error(make_error(
   26689             :                parser_error::e_syntax,
   26690           0 :                current_token(),
   26691             :                "ERR075 - Expected '(' at start of for-loop",
   26692             :                exprtk_error_location));
   26693             : 
   26694           0 :             return error_node();
   26695             :          }
   26696             : 
   26697        2735 :          if (!token_is(token_t::e_eof))
   26698             :          {
   26699        2735 :             if (
   26700        2745 :                  !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
   26701        2755 :                  details::imatch(current_token().value,"var")
   26702             :                )
   26703             :             {
   26704           0 :                next_token();
   26705             : 
   26706           0 :                if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
   26707             :                {
   26708           0 :                   set_error(make_error(
   26709             :                      parser_error::e_syntax,
   26710           0 :                      current_token(),
   26711             :                      "ERR076 - Expected a variable at the start of initialiser section of for-loop",
   26712             :                      exprtk_error_location));
   26713             : 
   26714           0 :                   return error_node();
   26715             :                }
   26716           0 :                else if (!peek_token_is(token_t::e_assign))
   26717             :                {
   26718           0 :                   set_error(make_error(
   26719             :                      parser_error::e_syntax,
   26720           0 :                      current_token(),
   26721             :                      "ERR077 - Expected variable assignment of initialiser section of for-loop",
   26722             :                      exprtk_error_location));
   26723             : 
   26724           0 :                   return error_node();
   26725             :                }
   26726             : 
   26727           0 :                const std::string loop_counter_symbol = current_token().value;
   26728             : 
   26729           0 :                se = &sem_.get_element(loop_counter_symbol);
   26730             : 
   26731           0 :                if ((se->name == loop_counter_symbol) && se->active)
   26732             :                {
   26733           0 :                   set_error(make_error(
   26734             :                      parser_error::e_syntax,
   26735           0 :                      current_token(),
   26736             :                      "ERR078 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
   26737             :                      exprtk_error_location));
   26738             : 
   26739           0 :                   return error_node();
   26740             :                }
   26741           0 :                else if (!symtab_store_.is_variable(loop_counter_symbol))
   26742             :                {
   26743           0 :                   if (
   26744           0 :                        !se->active &&
   26745           0 :                        (se->name == loop_counter_symbol) &&
   26746           0 :                        (se->type == scope_element::e_variable)
   26747             :                      )
   26748             :                   {
   26749           0 :                      se->active = true;
   26750           0 :                      se->ref_count++;
   26751             :                   }
   26752             :                   else
   26753             :                   {
   26754           0 :                      scope_element nse;
   26755           0 :                      nse.name      = loop_counter_symbol;
   26756           0 :                      nse.active    = true;
   26757           0 :                      nse.ref_count = 1;
   26758           0 :                      nse.type      = scope_element::e_variable;
   26759           0 :                      nse.depth     = state_.scope_depth;
   26760           0 :                      nse.data      = new T(T(0));
   26761           0 :                      nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
   26762             : 
   26763           0 :                      if (!sem_.add_element(nse))
   26764             :                      {
   26765           0 :                         set_error(make_error(
   26766             :                            parser_error::e_syntax,
   26767           0 :                            current_token(),
   26768             :                            "ERR079 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
   26769             :                            exprtk_error_location));
   26770             : 
   26771           0 :                         sem_.free_element(nse);
   26772             : 
   26773           0 :                         result = false;
   26774             :                      }
   26775             :                      else
   26776             :                      {
   26777             :                         exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str()));
   26778             : 
   26779           0 :                         state_.activate_side_effect("parse_for_loop()");
   26780             :                      }
   26781           0 :                   }
   26782             :                }
   26783           0 :             }
   26784             : 
   26785        2735 :             if (0 == (initialiser = parse_expression()))
   26786             :             {
   26787          40 :                set_error(make_error(
   26788             :                   parser_error::e_syntax,
   26789          10 :                   current_token(),
   26790             :                   "ERR080 - Failed to parse initialiser of for-loop",
   26791             :                   exprtk_error_location));
   26792             : 
   26793          10 :                result = false;
   26794             :             }
   26795        2725 :             else if (!token_is(token_t::e_eof))
   26796             :             {
   26797           0 :                set_error(make_error(
   26798             :                   parser_error::e_syntax,
   26799           0 :                   current_token(),
   26800             :                   "ERR081 - Expected ';' after initialiser of for-loop",
   26801             :                   exprtk_error_location));
   26802             : 
   26803           0 :                result = false;
   26804             :             }
   26805             :          }
   26806             : 
   26807        2735 :          if (!token_is(token_t::e_eof))
   26808             :          {
   26809        2735 :             if (0 == (condition = parse_expression()))
   26810             :             {
   26811          48 :                set_error(make_error(
   26812             :                   parser_error::e_syntax,
   26813          12 :                   current_token(),
   26814             :                   "ERR082 - Failed to parse condition of for-loop",
   26815             :                   exprtk_error_location));
   26816             : 
   26817          12 :                result = false;
   26818             :             }
   26819        2723 :             else if (!token_is(token_t::e_eof))
   26820             :             {
   26821           0 :                set_error(make_error(
   26822             :                   parser_error::e_syntax,
   26823           0 :                   current_token(),
   26824             :                   "ERR083 - Expected ';' after condition section of for-loop",
   26825             :                   exprtk_error_location));
   26826             : 
   26827           0 :                result = false;
   26828             :             }
   26829             :          }
   26830             : 
   26831        2735 :          if (!token_is(token_t::e_rbracket))
   26832             :          {
   26833        2605 :             if (0 == (incrementor = parse_expression()))
   26834             :             {
   26835           8 :                set_error(make_error(
   26836             :                   parser_error::e_syntax,
   26837           2 :                   current_token(),
   26838             :                   "ERR084 - Failed to parse incrementor of for-loop",
   26839             :                   exprtk_error_location));
   26840             : 
   26841           2 :                result = false;
   26842             :             }
   26843        2603 :             else if (!token_is(token_t::e_rbracket))
   26844             :             {
   26845           0 :                set_error(make_error(
   26846             :                   parser_error::e_syntax,
   26847           0 :                   current_token(),
   26848             :                   "ERR085 - Expected ')' after incrementor section of for-loop",
   26849             :                   exprtk_error_location));
   26850             : 
   26851           0 :                result = false;
   26852             :             }
   26853             :          }
   26854             : 
   26855        2735 :          if (result)
   26856             :          {
   26857        2723 :             brkcnt_list_.push_front(false);
   26858             : 
   26859        2723 :             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
   26860             : 
   26861        5446 :             if (0 == (loop_body = parse_multi_sequence("for-loop", true)))
   26862             :             {
   26863           0 :                set_error(make_error(
   26864             :                   parser_error::e_syntax,
   26865           0 :                   current_token(),
   26866             :                   "ERR086 - Failed to parse body of for-loop",
   26867             :                   exprtk_error_location));
   26868             : 
   26869           0 :                result = false;
   26870             :             }
   26871        2723 :          }
   26872             : 
   26873        2735 :          if (!result)
   26874             :          {
   26875          12 :             if (se)
   26876             :             {
   26877           0 :                se->ref_count--;
   26878             :             }
   26879             : 
   26880          12 :             free_node(node_allocator_, initialiser);
   26881          12 :             free_node(node_allocator_, condition  );
   26882          12 :             free_node(node_allocator_, incrementor);
   26883          12 :             free_node(node_allocator_, loop_body  );
   26884          12 :             return error_node();
   26885             :          }
   26886             : 
   26887        2723 :          expression_node_ptr result_node =
   26888        2723 :             expression_generator_.for_loop(initialiser,
   26889             :                                            condition,
   26890             :                                            incrementor,
   26891             :                                            loop_body,
   26892        2723 :                                            brkcnt_list_.front());
   26893        2723 :          handle_brkcnt_scope_exit();
   26894             : 
   26895        2723 :          if (result_node && result_node->valid())
   26896             :          {
   26897        2723 :             return result_node;
   26898             :          }
   26899             : 
   26900           0 :          set_error(make_error(
   26901             :             parser_error::e_synthesis,
   26902           0 :             current_token(),
   26903             :             "ERR087 - Failed to synthesize 'valid' for-loop",
   26904             :             exprtk_error_location));
   26905             : 
   26906           0 :          free_node(node_allocator_, result_node);
   26907             : 
   26908           0 :          return error_node();
   26909        2735 :       }
   26910             : 
   26911        1195 :       inline expression_node_ptr parse_switch_statement()
   26912             :       {
   26913        1195 :          std::vector<expression_node_ptr> arg_list;
   26914        1195 :          expression_node_ptr result = error_node();
   26915             : 
   26916        2390 :          if (!details::imatch(current_token().value,"switch"))
   26917             :          {
   26918           0 :             set_error(make_error(
   26919             :                parser_error::e_syntax,
   26920           0 :                current_token(),
   26921             :                "ERR088 - Expected keyword 'switch'",
   26922             :                exprtk_error_location));
   26923             : 
   26924           0 :             return error_node();
   26925             :          }
   26926             : 
   26927        1195 :          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
   26928             : 
   26929        1195 :          next_token();
   26930             : 
   26931        1195 :          if (!token_is(token_t::e_lcrlbracket))
   26932             :          {
   26933           0 :             set_error(make_error(
   26934             :                parser_error::e_syntax,
   26935           0 :                current_token(),
   26936             :                "ERR089 - Expected '{' for call to switch statement",
   26937             :                exprtk_error_location));
   26938             : 
   26939           0 :             return error_node();
   26940             :          }
   26941             : 
   26942        1195 :          expression_node_ptr default_statement = error_node();
   26943             : 
   26944        1195 :          scoped_expression_delete defstmt_delete((*this), default_statement);
   26945             : 
   26946        2730 :          for ( ; ; )
   26947             :          {
   26948       11775 :             if (details::imatch("case",current_token().value))
   26949             :             {
   26950        1535 :                next_token();
   26951             : 
   26952        1535 :                expression_node_ptr condition = parse_expression();
   26953             : 
   26954        1535 :                if (0 == condition)
   26955           0 :                   return error_node();
   26956        1535 :                else if (!token_is(token_t::e_colon))
   26957             :                {
   26958           0 :                   set_error(make_error(
   26959             :                      parser_error::e_syntax,
   26960           0 :                      current_token(),
   26961             :                      "ERR090 - Expected ':' for case of switch statement",
   26962             :                      exprtk_error_location));
   26963             : 
   26964           0 :                   free_node(node_allocator_, condition);
   26965             : 
   26966           0 :                   return error_node();
   26967             :                }
   26968             : 
   26969        1535 :                expression_node_ptr consequent =
   26970        1535 :                   (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
   26971        1535 :                   parse_multi_sequence("switch-consequent") :
   26972        1345 :                   parse_expression();
   26973             : 
   26974        1535 :                if (0 == consequent)
   26975             :                {
   26976           0 :                   free_node(node_allocator_, condition);
   26977             : 
   26978           0 :                   return error_node();
   26979             :                }
   26980        1535 :                else if (!token_is(token_t::e_eof))
   26981             :                {
   26982           0 :                   set_error(make_error(
   26983             :                      parser_error::e_syntax,
   26984           0 :                      current_token(),
   26985             :                      "ERR091 - Expected ';' at end of case for switch statement",
   26986             :                      exprtk_error_location));
   26987             : 
   26988           0 :                   free_node(node_allocator_, condition );
   26989           0 :                   free_node(node_allocator_, consequent);
   26990             : 
   26991           0 :                   return error_node();
   26992             :                }
   26993             : 
   26994             :                // Can we optimise away the case statement?
   26995        1535 :                if (is_constant_node(condition) && is_false(condition))
   26996             :                {
   26997          80 :                   free_node(node_allocator_, condition );
   26998          80 :                   free_node(node_allocator_, consequent);
   26999             :                }
   27000             :                else
   27001             :                {
   27002        1455 :                   arg_list.push_back(condition );
   27003        1455 :                   arg_list.push_back(consequent);
   27004             :                }
   27005             : 
   27006             :             }
   27007        7170 :             else if (details::imatch("default",current_token().value))
   27008             :             {
   27009        1195 :                if (0 != default_statement)
   27010             :                {
   27011           0 :                   set_error(make_error(
   27012             :                      parser_error::e_syntax,
   27013           0 :                      current_token(),
   27014             :                      "ERR092 - Multiple default cases for switch statement",
   27015             :                      exprtk_error_location));
   27016             : 
   27017           0 :                   return error_node();
   27018             :                }
   27019             : 
   27020        1195 :                next_token();
   27021             : 
   27022        1195 :                if (!token_is(token_t::e_colon))
   27023             :                {
   27024           0 :                   set_error(make_error(
   27025             :                      parser_error::e_syntax,
   27026           0 :                      current_token(),
   27027             :                      "ERR093 - Expected ':' for default of switch statement",
   27028             :                      exprtk_error_location));
   27029             : 
   27030           0 :                   return error_node();
   27031             :                }
   27032             : 
   27033        1195 :                default_statement =
   27034        1195 :                   (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
   27035        1195 :                   parse_multi_sequence("switch-default"):
   27036        1194 :                   parse_expression();
   27037             : 
   27038        1195 :                if (0 == default_statement)
   27039           0 :                   return error_node();
   27040        1195 :                else if (!token_is(token_t::e_eof))
   27041             :                {
   27042           0 :                   set_error(make_error(
   27043             :                      parser_error::e_syntax,
   27044           0 :                      current_token(),
   27045             :                      "ERR094 - Expected ';' at end of default for switch statement",
   27046             :                      exprtk_error_location));
   27047             : 
   27048           0 :                   return error_node();
   27049             :                }
   27050             :             }
   27051        1195 :             else if (token_is(token_t::e_rcrlbracket))
   27052        1195 :                break;
   27053             :             else
   27054             :             {
   27055           0 :                set_error(make_error(
   27056             :                   parser_error::e_syntax,
   27057           0 :                   current_token(),
   27058             :                   "ERR095 - Expected '}' at end of switch statement",
   27059             :                   exprtk_error_location));
   27060             : 
   27061           0 :                return error_node();
   27062             :             }
   27063             :          }
   27064             : 
   27065        1195 :          const bool default_statement_present = (0 != default_statement);
   27066             : 
   27067        1195 :          if (default_statement_present)
   27068             :          {
   27069        1195 :             arg_list.push_back(default_statement);
   27070             :          }
   27071             :          else
   27072             :          {
   27073           0 :             arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN()));
   27074             :          }
   27075             : 
   27076        1195 :          result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
   27077             : 
   27078        1195 :          svd.delete_ptr = (0 == result);
   27079        1195 :          defstmt_delete.delete_ptr = (0 == result);
   27080             : 
   27081        1195 :          return result;
   27082        1195 :       }
   27083             : 
   27084         190 :       inline expression_node_ptr parse_multi_switch_statement()
   27085             :       {
   27086         190 :          std::vector<expression_node_ptr> arg_list;
   27087             : 
   27088         380 :          if (!details::imatch(current_token().value,"[*]"))
   27089             :          {
   27090           0 :             set_error(make_error(
   27091             :                parser_error::e_syntax,
   27092           0 :                current_token(),
   27093             :                "ERR096 - Expected token '[*]'",
   27094             :                exprtk_error_location));
   27095             : 
   27096           0 :             return error_node();
   27097             :          }
   27098             : 
   27099         190 :          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
   27100             : 
   27101         190 :          next_token();
   27102             : 
   27103         190 :          if (!token_is(token_t::e_lcrlbracket))
   27104             :          {
   27105           0 :             set_error(make_error(
   27106             :                parser_error::e_syntax,
   27107           0 :                current_token(),
   27108             :                "ERR097 - Expected '{' for call to [*] statement",
   27109             :                exprtk_error_location));
   27110             : 
   27111           0 :             return error_node();
   27112             :          }
   27113             : 
   27114         210 :          for ( ; ; )
   27115             :          {
   27116        1200 :             if (!details::imatch("case",current_token().value))
   27117             :             {
   27118           0 :                set_error(make_error(
   27119             :                   parser_error::e_syntax,
   27120           0 :                   current_token(),
   27121             :                   "ERR098 - Expected a 'case' statement for multi-switch",
   27122             :                   exprtk_error_location));
   27123             : 
   27124           0 :                return error_node();
   27125             :             }
   27126             : 
   27127         400 :             next_token();
   27128             : 
   27129         400 :             expression_node_ptr condition = parse_expression();
   27130             : 
   27131         400 :             if (0 == condition)
   27132           0 :                return error_node();
   27133             : 
   27134         400 :             if (!token_is(token_t::e_colon))
   27135             :             {
   27136           0 :                set_error(make_error(
   27137             :                   parser_error::e_syntax,
   27138           0 :                   current_token(),
   27139             :                   "ERR099 - Expected ':' for case of [*] statement",
   27140             :                   exprtk_error_location));
   27141             : 
   27142           0 :                return error_node();
   27143             :             }
   27144             : 
   27145         400 :             expression_node_ptr consequent =
   27146         400 :                (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
   27147         400 :                parse_multi_sequence("multi-switch-consequent") :
   27148         400 :                parse_expression();
   27149             : 
   27150         400 :             if (0 == consequent)
   27151           0 :                return error_node();
   27152             : 
   27153         400 :             if (!token_is(token_t::e_eof))
   27154             :             {
   27155           0 :                set_error(make_error(
   27156             :                   parser_error::e_syntax,
   27157           0 :                   current_token(),
   27158             :                   "ERR100 - Expected ';' at end of case for [*] statement",
   27159             :                   exprtk_error_location));
   27160             : 
   27161           0 :                return error_node();
   27162             :             }
   27163             : 
   27164             :             // Can we optimise away the case statement?
   27165         400 :             if (is_constant_node(condition) && is_false(condition))
   27166             :             {
   27167           0 :                free_node(node_allocator_, condition );
   27168           0 :                free_node(node_allocator_, consequent);
   27169             :             }
   27170             :             else
   27171             :             {
   27172         400 :                arg_list.push_back(condition );
   27173         400 :                arg_list.push_back(consequent);
   27174             :             }
   27175             : 
   27176         400 :             if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
   27177             :             {
   27178         190 :                break;
   27179             :             }
   27180             :          }
   27181             : 
   27182         190 :          if (!token_is(token_t::e_rcrlbracket))
   27183             :          {
   27184           0 :             set_error(make_error(
   27185             :                parser_error::e_syntax,
   27186           0 :                current_token(),
   27187             :                "ERR101 - Expected '}' at end of [*] statement",
   27188             :                exprtk_error_location));
   27189             : 
   27190           0 :             return error_node();
   27191             :          }
   27192             : 
   27193         190 :          const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
   27194             : 
   27195         190 :          svd.delete_ptr = (0 == result);
   27196             : 
   27197         190 :          return result;
   27198         190 :       }
   27199             : 
   27200       22327 :       inline expression_node_ptr parse_vararg_function()
   27201             :       {
   27202       22327 :          std::vector<expression_node_ptr> arg_list;
   27203             : 
   27204       22327 :          details::operator_type opt_type = details::e_default;
   27205       22327 :          const std::string symbol = current_token().value;
   27206             : 
   27207       44654 :          if (details::imatch(symbol,"~"))
   27208             :          {
   27209       14067 :             next_token();
   27210       28134 :             return parse_multi_sequence();
   27211             :          }
   27212       16520 :          else if (details::imatch(symbol,"[*]"))
   27213             :          {
   27214         190 :             return parse_multi_switch_statement();
   27215             :          }
   27216       16140 :          else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
   27217       15464 :          else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
   27218       14952 :          else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
   27219       14194 :          else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
   27220        5370 :          else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
   27221        4856 :          else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
   27222        4408 :          else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
   27223             :          else
   27224             :          {
   27225           0 :             set_error(make_error(
   27226             :                parser_error::e_syntax,
   27227           0 :                current_token(),
   27228             :                "ERR102 - Unsupported built-in vararg function: " + symbol,
   27229             :                exprtk_error_location));
   27230             : 
   27231           0 :             return error_node();
   27232             :          }
   27233             : 
   27234        8070 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   27235             : 
   27236        8070 :          lodge_symbol(symbol, e_st_function);
   27237             : 
   27238        8070 :          next_token();
   27239             : 
   27240        8070 :          if (!token_is(token_t::e_lbracket))
   27241             :          {
   27242           0 :             set_error(make_error(
   27243             :                parser_error::e_syntax,
   27244           0 :                current_token(),
   27245             :                "ERR103 - Expected '(' for call to vararg function: " + symbol,
   27246             :                exprtk_error_location));
   27247             : 
   27248           0 :             return error_node();
   27249             :          }
   27250             : 
   27251        8070 :          if (token_is(token_t::e_rbracket))
   27252             :          {
   27253           0 :             set_error(make_error(
   27254             :                parser_error::e_syntax,
   27255           0 :                current_token(),
   27256             :                "ERR104 - vararg function: " + symbol +
   27257             :                " requires at least one input parameter",
   27258             :                exprtk_error_location));
   27259             : 
   27260           0 :             return error_node();
   27261             :          }
   27262             : 
   27263        8024 :          for ( ; ; )
   27264             :          {
   27265       16094 :             expression_node_ptr arg = parse_expression();
   27266             : 
   27267       16094 :             if (0 == arg)
   27268           2 :                return error_node();
   27269             :             else
   27270       16092 :                arg_list.push_back(arg);
   27271             : 
   27272       16092 :             if (token_is(token_t::e_rbracket))
   27273        8068 :                break;
   27274        8024 :             else if (!token_is(token_t::e_comma))
   27275             :             {
   27276           0 :                set_error(make_error(
   27277             :                   parser_error::e_syntax,
   27278           0 :                   current_token(),
   27279             :                   "ERR105 - Expected ',' for call to vararg function: " + symbol,
   27280             :                   exprtk_error_location));
   27281             : 
   27282           0 :                return error_node();
   27283             :             }
   27284             :          }
   27285             : 
   27286        8068 :          const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
   27287             : 
   27288        8068 :          sdd.delete_ptr = (0 == result);
   27289        8068 :          return result;
   27290       22327 :       }
   27291             : 
   27292             :       #ifndef exprtk_disable_string_capabilities
   27293        4852 :       inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
   27294             :       {
   27295        4852 :          if (!token_is(token_t::e_lsqrbracket))
   27296             :          {
   27297           0 :             set_error(make_error(
   27298             :                parser_error::e_syntax,
   27299           0 :                current_token(),
   27300             :                "ERR106 - Expected '[' as start of string range definition",
   27301             :                exprtk_error_location));
   27302             : 
   27303           0 :             free_node(node_allocator_,expression);
   27304             : 
   27305           0 :             return error_node();
   27306             :          }
   27307        4852 :          else if (token_is(token_t::e_rsqrbracket))
   27308             :          {
   27309         750 :             return node_allocator_.allocate<details::string_size_node<T> >(expression);
   27310             :          }
   27311             : 
   27312        4102 :          range_t rp;
   27313             : 
   27314        4102 :          if (!parse_range(rp,true))
   27315             :          {
   27316           0 :             free_node(node_allocator_,expression);
   27317             : 
   27318           0 :             return error_node();
   27319             :          }
   27320             : 
   27321        4102 :          expression_node_ptr result = expression_generator_(expression,rp);
   27322             : 
   27323        4102 :          if (0 == result)
   27324             :          {
   27325           0 :             set_error(make_error(
   27326             :                parser_error::e_syntax,
   27327           0 :                current_token(),
   27328             :                "ERR107 - Failed to generate string range node",
   27329             :                exprtk_error_location));
   27330             : 
   27331           0 :             free_node(node_allocator_,expression);
   27332           0 :             rp.free();
   27333             :          }
   27334             : 
   27335        4102 :          rp.clear();
   27336             : 
   27337        4102 :          if (result && result->valid())
   27338             :          {
   27339        4102 :             return result;
   27340             :          }
   27341             : 
   27342           0 :          set_error(make_error(
   27343             :             parser_error::e_synthesis,
   27344           0 :             current_token(),
   27345             :             "ERR108 - Failed to synthesize node: string_range_node",
   27346             :             exprtk_error_location));
   27347             : 
   27348           0 :          free_node(node_allocator_, result);
   27349           0 :          rp.free();
   27350           0 :          return error_node();
   27351             :       }
   27352             :       #else
   27353             :       inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
   27354             :       {
   27355             :          return error_node();
   27356             :       }
   27357             :       #endif
   27358             : 
   27359    13784857 :       inline bool parse_pending_string_rangesize(expression_node_ptr& expression)
   27360             :       {
   27361             :          // Allow no more than 100 range calls, eg: s[][][]...[][]
   27362    13784857 :          const std::size_t max_rangesize_parses = 100;
   27363             : 
   27364    13784857 :          std::size_t i = 0;
   27365             : 
   27366    13784857 :          while
   27367             :             (
   27368    27546610 :               (0 != expression)                     &&
   27369    27513802 :               (i++ < max_rangesize_parses)          &&
   27370    13756901 :               error_list_.empty()                   &&
   27371    27805115 :               is_generally_string_node(expression)  &&
   27372    14048214 :               token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
   27373             :             )
   27374             :          {
   27375        4852 :             expression = parse_string_range_statement(expression);
   27376             :          }
   27377             : 
   27378    13784857 :          return (i > 1);
   27379             :       }
   27380             : 
   27381     1715579 :       inline void parse_pending_vector_index_operator(expression_node_ptr& expression)
   27382             :       {
   27383     1715579 :          if
   27384             :             (
   27385     1715579 :               (0 != expression)           &&
   27386     3431158 :               error_list_.empty()         &&
   27387     1715579 :               is_ivector_node(expression)
   27388             :             )
   27389             :          {
   27390        6581 :             if (
   27391        6581 :                  settings_.commutative_check_enabled()       &&
   27392        7481 :                  token_is(token_t::e_mul,prsrhlpr_t::e_hold) &&
   27393        7481 :                  peek_token_is(token_t::e_lsqrbracket)
   27394             :                )
   27395             :             {
   27396         660 :                token_is(token_t::e_mul);
   27397         660 :                token_is(token_t::e_lsqrbracket);
   27398             :             }
   27399        5921 :             else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
   27400             :             {
   27401           0 :                token_is(token_t::e_lsqrbracket);
   27402             :             }
   27403        5921 :             else if (
   27404        6210 :                       token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) &&
   27405        6210 :                       peek_token_is(token_t::e_lsqrbracket)
   27406             :                     )
   27407             :             {
   27408           0 :                token_is(token_t::e_rbracket   );
   27409           0 :                token_is(token_t::e_lsqrbracket);
   27410             :             }
   27411             :             else
   27412        5921 :                return;
   27413             : 
   27414         660 :             details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression);
   27415             : 
   27416         660 :             if (vi)
   27417             :             {
   27418         660 :                details::vector_holder<T>& vec = vi->vec()->vec_holder();
   27419         660 :                const std::string vector_name  = sem_.get_vector_name(vec.data());
   27420         660 :                expression_node_ptr index      = parse_vector_index(vector_name);
   27421             : 
   27422         660 :                if (index)
   27423             :                {
   27424         660 :                   expression = synthesize_vector_element(vector_name, &vec, expression, index);
   27425         660 :                   return;
   27426             :                }
   27427         660 :             }
   27428             : 
   27429           0 :             free_node(node_allocator_,expression);
   27430           0 :             expression = error_node();
   27431             :          }
   27432             :       }
   27433             : 
   27434             :       template <typename Allocator1,
   27435             :                 typename Allocator2,
   27436             :                 template <typename, typename> class Sequence>
   27437      380093 :       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
   27438             :                                           Sequence<bool,Allocator2>& side_effect_list,
   27439             :                                           const bool specialise_on_final_type = false)
   27440             :       {
   27441      380093 :          if (expression_list.empty())
   27442           0 :             return error_node();
   27443      380093 :          else if (1 == expression_list.size())
   27444      336105 :             return expression_list[0];
   27445             : 
   27446       43988 :          Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
   27447             : 
   27448       43988 :          bool return_node_present = false;
   27449             : 
   27450      142960 :          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
   27451             :          {
   27452       99309 :             if (is_variable_node(expression_list[i]))
   27453           0 :                continue;
   27454       99309 :             else if (
   27455       99309 :                       is_return_node  (expression_list[i]) ||
   27456      198281 :                       is_break_node   (expression_list[i]) ||
   27457       98972 :                       is_continue_node(expression_list[i])
   27458             :                     )
   27459             :             {
   27460         337 :                tmp_expression_list.push_back(expression_list[i]);
   27461             : 
   27462             :                // Remove all subexpressions after first short-circuit
   27463             :                // node has been encountered.
   27464             : 
   27465        1264 :                for (std::size_t j = i + 1; j < expression_list.size(); ++j)
   27466             :                {
   27467         927 :                   free_node(node_allocator_,expression_list[j]);
   27468             :                }
   27469             : 
   27470         337 :                return_node_present = true;
   27471             : 
   27472         337 :                break;
   27473             :             }
   27474      109922 :             else if (
   27475       98972 :                       is_constant_node(expression_list[i]) ||
   27476      192549 :                       is_null_node    (expression_list[i]) ||
   27477      192549 :                       !side_effect_list[i]
   27478             :                     )
   27479             :             {
   27480       10950 :                free_node(node_allocator_,expression_list[i]);
   27481       10950 :                continue;
   27482             :             }
   27483             :             else
   27484       88022 :                tmp_expression_list.push_back(expression_list[i]);
   27485             :          }
   27486             : 
   27487       43988 :          if (!return_node_present)
   27488             :          {
   27489       43651 :             tmp_expression_list.push_back(expression_list.back());
   27490             :          }
   27491             : 
   27492       43988 :          expression_list.swap(tmp_expression_list);
   27493             : 
   27494       43988 :          if (tmp_expression_list.size() > expression_list.size())
   27495             :          {
   27496             :             exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
   27497             :                           static_cast<int>(tmp_expression_list.size()),
   27498             :                           static_cast<int>(expression_list    .size())));
   27499             :          }
   27500             : 
   27501       43988 :          if (
   27502       43651 :               return_node_present     ||
   27503       87639 :               side_effect_list.back() ||
   27504       36435 :               (expression_list.size() > 1)
   27505             :             )
   27506      127497 :             state_.activate_side_effect("simplify()");
   27507             : 
   27508       43988 :          if (1 == expression_list.size())
   27509        2440 :             return expression_list[0];
   27510       41548 :          else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
   27511          85 :             return expression_generator_.vararg_function(details::e_smulti,expression_list);
   27512             :          else
   27513       41463 :             return expression_generator_.vararg_function(details::e_multi,expression_list);
   27514       43988 :       }
   27515             : 
   27516       20852 :       inline expression_node_ptr parse_multi_sequence(const std::string& source = "",
   27517             :                                                       const bool enforce_crlbrackets = false)
   27518             :       {
   27519       20852 :          token_t::token_type open_bracket  = token_t::e_lcrlbracket;
   27520       20852 :          token_t::token_type close_bracket = token_t::e_rcrlbracket;
   27521       20852 :          token_t::token_type separator     = token_t::e_eof;
   27522             : 
   27523       20852 :          if (!token_is(open_bracket))
   27524             :          {
   27525         322 :             if (!enforce_crlbrackets && token_is(token_t::e_lbracket))
   27526             :             {
   27527         322 :                open_bracket  = token_t::e_lbracket;
   27528         322 :                close_bracket = token_t::e_rbracket;
   27529         322 :                separator     = token_t::e_comma;
   27530             :             }
   27531             :             else
   27532             :             {
   27533           0 :                set_error(make_error(
   27534             :                   parser_error::e_syntax,
   27535           0 :                   current_token(),
   27536             :                   "ERR109 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" +
   27537           0 :                   ((!source.empty()) ? std::string(" section of " + source): ""),
   27538             :                   exprtk_error_location));
   27539             : 
   27540           0 :                return error_node();
   27541             :             }
   27542             :          }
   27543       20530 :          else if (token_is(close_bracket))
   27544             :          {
   27545           0 :             return node_allocator_.allocate<details::null_node<T> >();
   27546             :          }
   27547             : 
   27548       20852 :          std::vector<expression_node_ptr> arg_list;
   27549       20852 :          std::vector<bool> side_effect_list;
   27550             : 
   27551       20852 :          expression_node_ptr result = error_node();
   27552             : 
   27553       20852 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   27554             : 
   27555       20852 :          scope_handler sh(*this);
   27556             : 
   27557       20852 :          scoped_bool_or_restorer sbr(state_.side_effect_present);
   27558             : 
   27559       24257 :          for ( ; ; )
   27560             :          {
   27561       45109 :             state_.side_effect_present = false;
   27562             : 
   27563       45109 :             expression_node_ptr arg = parse_expression();
   27564             : 
   27565       45109 :             if (0 == arg)
   27566           0 :                return error_node();
   27567             :             else
   27568             :             {
   27569       45109 :                arg_list.push_back(arg);
   27570       45109 :                side_effect_list.push_back(state_.side_effect_present);
   27571             :             }
   27572             : 
   27573       45109 :             if (token_is(close_bracket))
   27574       17054 :                break;
   27575             : 
   27576       28055 :             const bool is_next_close = peek_token_is(close_bracket);
   27577             : 
   27578       28055 :             if (!token_is(separator) && is_next_close)
   27579             :             {
   27580           0 :                set_error(make_error(
   27581             :                   parser_error::e_syntax,
   27582           0 :                   current_token(),
   27583             :                   "ERR110 - Expected '" + details::to_str(separator) + "' for call to multi-sequence section of " + source,
   27584             :                   exprtk_error_location));
   27585             : 
   27586           0 :                return error_node();
   27587             :             }
   27588             : 
   27589       28055 :             if (token_is(close_bracket))
   27590        3798 :                break;
   27591             :          }
   27592             : 
   27593       20852 :          result = simplify(arg_list, side_effect_list, source.empty());
   27594             : 
   27595       20852 :          sdd.delete_ptr = (0 == result);
   27596       20852 :          return result;
   27597       20852 :       }
   27598             : 
   27599       32056 :       inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
   27600             :       {
   27601             :          // Examples of valid ranges:
   27602             :          // 1. [1:5]     -> [1,5)
   27603             :          // 2. [ :5]     -> [0,5)
   27604             :          // 3. [1: ]     -> [1,end)
   27605             :          // 4. [x:y]     -> [x,y) where x <= y
   27606             :          // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2
   27607             :          // 6. [ :y]     -> [0,y) where 0 <= y
   27608             :          // 7. [x: ]     -> [x,end) where x <= end
   27609             : 
   27610       32056 :          rp.clear();
   27611             : 
   27612       32056 :          if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
   27613             :          {
   27614           0 :             set_error(make_error(
   27615             :                parser_error::e_syntax,
   27616           0 :                current_token(),
   27617             :                "ERR111 - Expected '[' for start of range",
   27618             :                exprtk_error_location));
   27619             : 
   27620           0 :             return false;
   27621             :          }
   27622             : 
   27623       32056 :          if (token_is(token_t::e_colon))
   27624             :          {
   27625       10180 :             rp.n0_c.first  = true;
   27626       10180 :             rp.n0_c.second = 0;
   27627       10180 :             rp.cache.first = 0;
   27628             :          }
   27629             :          else
   27630             :          {
   27631       21876 :             expression_node_ptr r0 = parse_expression();
   27632             : 
   27633       21876 :             if (0 == r0)
   27634             :             {
   27635           0 :                set_error(make_error(
   27636             :                   parser_error::e_syntax,
   27637           0 :                   current_token(),
   27638             :                   "ERR112 - Failed parse begin section of range",
   27639             :                   exprtk_error_location));
   27640             : 
   27641           0 :                return false;
   27642             :             }
   27643       21876 :             else if (is_constant_node(r0))
   27644             :             {
   27645       16670 :                const T r0_value = r0->value();
   27646             : 
   27647       16670 :                if (r0_value >= T(0))
   27648             :                {
   27649       16670 :                   rp.n0_c.first  = true;
   27650       16670 :                   rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
   27651       16670 :                   rp.cache.first = rp.n0_c.second;
   27652             :                }
   27653             : 
   27654       16670 :                free_node(node_allocator_,r0);
   27655             : 
   27656       16670 :                if (r0_value < T(0))
   27657             :                {
   27658           0 :                   set_error(make_error(
   27659             :                      parser_error::e_syntax,
   27660           0 :                      current_token(),
   27661             :                      "ERR113 - Range lower bound less than zero! Constraint: r0 >= 0",
   27662             :                      exprtk_error_location));
   27663             : 
   27664           0 :                   return false;
   27665             :                }
   27666             :             }
   27667             :             else
   27668             :             {
   27669        5206 :                rp.n0_e.first  = true;
   27670        5206 :                rp.n0_e.second = r0;
   27671             :             }
   27672             : 
   27673       21876 :             if (!token_is(token_t::e_colon))
   27674             :             {
   27675           0 :                set_error(make_error(
   27676             :                   parser_error::e_syntax,
   27677           0 :                   current_token(),
   27678             :                   "ERR114 - Expected ':' for break  in range",
   27679             :                   exprtk_error_location));
   27680             : 
   27681           0 :                rp.free();
   27682             : 
   27683           0 :                return false;
   27684             :             }
   27685             :          }
   27686             : 
   27687       32056 :          if (token_is(token_t::e_rsqrbracket))
   27688             :          {
   27689       11415 :             rp.n1_c.first  = true;
   27690       11415 :             rp.n1_c.second = std::numeric_limits<std::size_t>::max();
   27691             :          }
   27692             :          else
   27693             :          {
   27694       20641 :             expression_node_ptr r1 = parse_expression();
   27695             : 
   27696       20641 :             if (0 == r1)
   27697             :             {
   27698           0 :                set_error(make_error(
   27699             :                   parser_error::e_syntax,
   27700           0 :                   current_token(),
   27701             :                   "ERR115 - Failed parse end section of range",
   27702             :                   exprtk_error_location));
   27703             : 
   27704           0 :                rp.free();
   27705             : 
   27706           0 :                return false;
   27707             :             }
   27708       20641 :             else if (is_constant_node(r1))
   27709             :             {
   27710       13585 :                const T r1_value = r1->value();
   27711             : 
   27712       13585 :                if (r1_value >= T(0))
   27713             :                {
   27714       13585 :                   rp.n1_c.first   = true;
   27715       13585 :                   rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
   27716       13585 :                   rp.cache.second = rp.n1_c.second;
   27717             :                }
   27718             : 
   27719       13585 :                free_node(node_allocator_,r1);
   27720             : 
   27721       13585 :                if (r1_value < T(0))
   27722             :                {
   27723           0 :                   set_error(make_error(
   27724             :                      parser_error::e_syntax,
   27725           0 :                      current_token(),
   27726             :                      "ERR116 - Range upper bound less than zero! Constraint: r1 >= 0",
   27727             :                      exprtk_error_location));
   27728             : 
   27729           0 :                   rp.free();
   27730             : 
   27731           0 :                   return false;
   27732             :                }
   27733             :             }
   27734             :             else
   27735             :             {
   27736        7056 :                rp.n1_e.first  = true;
   27737        7056 :                rp.n1_e.second = r1;
   27738             :             }
   27739             : 
   27740       20641 :             if (!token_is(token_t::e_rsqrbracket))
   27741             :             {
   27742           0 :                set_error(make_error(
   27743             :                   parser_error::e_syntax,
   27744           0 :                   current_token(),
   27745             :                   "ERR117 - Expected ']' for start of range",
   27746             :                   exprtk_error_location));
   27747             : 
   27748           0 :                rp.free();
   27749             : 
   27750           0 :                return false;
   27751             :             }
   27752             :          }
   27753             : 
   27754       32056 :          if (rp.const_range())
   27755             :          {
   27756       21748 :             std::size_t r0 = 0;
   27757       21748 :             std::size_t r1 = 0;
   27758             : 
   27759       21748 :             bool rp_result = false;
   27760             : 
   27761             :             try
   27762             :             {
   27763       21748 :                rp_result = rp(r0, r1);
   27764             :             }
   27765           0 :             catch (std::runtime_error&)
   27766             :             {}
   27767             : 
   27768       21748 :             if (!rp_result || (r0 > r1))
   27769             :             {
   27770           0 :                set_error(make_error(
   27771             :                   parser_error::e_syntax,
   27772           0 :                   current_token(),
   27773             :                   "ERR118 - Invalid range, Constraint: r0 <= r1",
   27774             :                   exprtk_error_location));
   27775             : 
   27776           0 :                return false;
   27777             :             }
   27778             :          }
   27779             : 
   27780       32056 :          return true;
   27781             :       }
   27782             : 
   27783     2427545 :       inline void lodge_symbol(const std::string& symbol,
   27784             :                                const symbol_type st)
   27785             :       {
   27786     2427545 :          dec_.add_symbol(symbol,st);
   27787     2427545 :       }
   27788             : 
   27789             :       #ifndef exprtk_disable_string_capabilities
   27790       68710 :       inline expression_node_ptr parse_string()
   27791             :       {
   27792       68710 :          const std::string symbol = current_token().value;
   27793             : 
   27794             :          typedef details::stringvar_node<T>* strvar_node_t;
   27795             : 
   27796       68710 :          expression_node_ptr result   = error_node();
   27797       68710 :          strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
   27798             : 
   27799       68710 :          scope_element& se = sem_.get_active_element(symbol);
   27800             : 
   27801       68710 :          if (scope_element::e_string == se.type)
   27802             :          {
   27803       19235 :             se.active = true;
   27804       19235 :             result    = se.str_node;
   27805       19235 :             lodge_symbol(symbol, e_st_local_string);
   27806             :          }
   27807             :          else
   27808             :          {
   27809             :             typedef typename symtab_store::string_context str_ctxt_t;
   27810       49475 :             str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol);
   27811             : 
   27812       49475 :             if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol))
   27813             :             {
   27814           0 :                set_error(make_error(
   27815             :                   parser_error::e_syntax,
   27816           0 :                   current_token(),
   27817             :                   "ERR119 - Unknown string symbol",
   27818             :                   exprtk_error_location));
   27819             : 
   27820           0 :                return error_node();
   27821             :             }
   27822             : 
   27823       49475 :             assert(str_ctx.str_var != 0);
   27824       49475 :             assert(str_ctx.symbol_table != 0);
   27825             : 
   27826       49475 :             result = str_ctx.str_var;
   27827             : 
   27828       49475 :             if (symtab_store_.is_constant_string(symbol))
   27829             :             {
   27830           0 :                const_str_node = static_cast<strvar_node_t>(result);
   27831           0 :                result = expression_generator_(const_str_node->str());
   27832             :             }
   27833       49475 :             else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability())
   27834             :             {
   27835          48 :                lodge_immutable_symbol(
   27836          24 :                   current_token(),
   27837          24 :                   make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size()));
   27838             :             }
   27839             : 
   27840       49475 :             lodge_symbol(symbol, e_st_string);
   27841             :          }
   27842             : 
   27843       68710 :          if (peek_token_is(token_t::e_lsqrbracket))
   27844             :          {
   27845       26201 :             next_token();
   27846             : 
   27847       26201 :             if (peek_token_is(token_t::e_rsqrbracket))
   27848             :             {
   27849        3800 :                next_token();
   27850        3800 :                next_token();
   27851             : 
   27852        3800 :                if (const_str_node)
   27853             :                {
   27854           0 :                   free_node(node_allocator_,result);
   27855             : 
   27856           0 :                   return expression_generator_(T(const_str_node->size()));
   27857             :                }
   27858             :                else
   27859             :                   return node_allocator_.allocate<details::stringvar_size_node<T> >
   27860        3800 :                             (static_cast<details::stringvar_node<T>*>(result)->ref());
   27861             :             }
   27862             : 
   27863       22401 :             range_t rp;
   27864             : 
   27865       22401 :             if (!parse_range(rp))
   27866             :             {
   27867           0 :                free_node(node_allocator_,result);
   27868             : 
   27869           0 :                return error_node();
   27870             :             }
   27871       22401 :             else if (const_str_node)
   27872             :             {
   27873           0 :                free_node(node_allocator_,result);
   27874           0 :                result = expression_generator_(const_str_node->ref(),rp);
   27875             :             }
   27876             :             else
   27877       22401 :                result = expression_generator_(static_cast<details::stringvar_node<T>*>
   27878             :                            (result)->ref(), rp);
   27879             : 
   27880       22401 :             if (result)
   27881       22401 :                rp.clear();
   27882             :          }
   27883             :          else
   27884       42509 :             next_token();
   27885             : 
   27886       64910 :          return result;
   27887       68710 :       }
   27888             :       #else
   27889             :       inline expression_node_ptr parse_string()
   27890             :       {
   27891             :          return error_node();
   27892             :       }
   27893             :       #endif
   27894             : 
   27895             :       #ifndef exprtk_disable_string_capabilities
   27896       52875 :       inline expression_node_ptr parse_const_string()
   27897             :       {
   27898       52875 :          const std::string   const_str = current_token().value;
   27899       52875 :          expression_node_ptr result    = expression_generator_(const_str);
   27900             : 
   27901       52875 :          if (peek_token_is(token_t::e_lsqrbracket))
   27902             :          {
   27903        6203 :             next_token();
   27904             : 
   27905        6203 :             if (peek_token_is(token_t::e_rsqrbracket))
   27906             :             {
   27907         650 :                next_token();
   27908         650 :                next_token();
   27909             : 
   27910         650 :                free_node(node_allocator_,result);
   27911             : 
   27912         650 :                return expression_generator_(T(const_str.size()));
   27913             :             }
   27914             : 
   27915        5553 :             range_t rp;
   27916             : 
   27917        5553 :             if (!parse_range(rp))
   27918             :             {
   27919           0 :                free_node(node_allocator_,result);
   27920           0 :                rp.free();
   27921             : 
   27922           0 :                return error_node();
   27923             :             }
   27924             : 
   27925        5553 :             free_node(node_allocator_,result);
   27926             : 
   27927        5553 :             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
   27928             :             {
   27929        1750 :                rp.n1_c.second  = const_str.size() - 1;
   27930        1750 :                rp.cache.second = rp.n1_c.second;
   27931             :             }
   27932             : 
   27933        5553 :             if (
   27934       11106 :                  (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
   27935        5553 :                  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
   27936             :                )
   27937             :             {
   27938           0 :                set_error(make_error(
   27939             :                   parser_error::e_syntax,
   27940           0 :                   current_token(),
   27941             :                   "ERR120 - Overflow in range for string: '" + const_str + "'[" +
   27942           0 :                   (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
   27943           0 :                   (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
   27944             :                   exprtk_error_location));
   27945             : 
   27946           0 :                rp.free();
   27947             : 
   27948           0 :                return error_node();
   27949             :             }
   27950             : 
   27951        5553 :             result = expression_generator_(const_str,rp);
   27952             : 
   27953        5553 :             if (result)
   27954        5553 :                rp.clear();
   27955             :          }
   27956             :          else
   27957       46672 :             next_token();
   27958             : 
   27959       52225 :          return result;
   27960       52875 :       }
   27961             :       #else
   27962             :       inline expression_node_ptr parse_const_string()
   27963             :       {
   27964             :          return error_node();
   27965             :       }
   27966             :       #endif
   27967             : 
   27968       19542 :       inline expression_node_ptr parse_vector_index(const std::string& vector_name = "")
   27969             :       {
   27970       19542 :          expression_node_ptr index_expr = error_node();
   27971             : 
   27972       19542 :          if (0 == (index_expr = parse_expression()))
   27973             :          {
   27974           0 :             set_error(make_error(
   27975             :                parser_error::e_syntax,
   27976           0 :                current_token(),
   27977             :                "ERR121 - Failed to parse index for vector: '" + vector_name + "'",
   27978             :                exprtk_error_location));
   27979             : 
   27980           0 :             return error_node();
   27981             :          }
   27982       19542 :          else if (!token_is(token_t::e_rsqrbracket))
   27983             :          {
   27984           0 :             set_error(make_error(
   27985             :                parser_error::e_syntax,
   27986           0 :                current_token(),
   27987             :                "ERR122 - Expected ']' for index of vector: '" + vector_name + "'",
   27988             :                exprtk_error_location));
   27989             : 
   27990           0 :             free_node(node_allocator_,index_expr);
   27991             : 
   27992           0 :             return error_node();
   27993             :          }
   27994             : 
   27995       19542 :          return index_expr;
   27996             :       }
   27997             : 
   27998       52977 :       inline expression_node_ptr parse_vector()
   27999             :       {
   28000       52977 :          const std::string vector_name = current_token().value;
   28001             : 
   28002       52977 :          vector_holder_ptr vec = vector_holder_ptr(0);
   28003             : 
   28004       52977 :          const scope_element& se = sem_.get_active_element(vector_name);
   28005             : 
   28006       52977 :          if (
   28007       52977 :               !details::imatch(se.name, vector_name) ||
   28008       99085 :               (se.depth > state_.scope_depth)   ||
   28009       46108 :               (scope_element::e_vector != se.type)
   28010             :             )
   28011             :          {
   28012             :             typedef typename symtab_store::vector_context vec_ctxt_t;
   28013        6869 :             vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name);
   28014             : 
   28015        6869 :             if (0 == vec_ctx.vector_holder)
   28016             :             {
   28017           0 :                set_error(make_error(
   28018             :                   parser_error::e_syntax,
   28019           0 :                   current_token(),
   28020             :                   "ERR123 - Symbol '" + vector_name + " not a vector",
   28021             :                   exprtk_error_location));
   28022             : 
   28023           0 :                return error_node();
   28024             :             }
   28025             : 
   28026        6869 :             assert(0 != vec_ctx.vector_holder);
   28027        6869 :             assert(0 != vec_ctx.symbol_table );
   28028             : 
   28029        6869 :             vec = vec_ctx.vector_holder;
   28030             : 
   28031        6869 :             if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability())
   28032             :             {
   28033          26 :                lodge_immutable_symbol(
   28034          13 :                   current_token(),
   28035          13 :                   make_memory_range(vec->data(), vec->size()));
   28036             :             }
   28037             :          }
   28038             :          else
   28039             :          {
   28040       46108 :             vec = se.vec_node;
   28041             :          }
   28042             : 
   28043       52977 :          assert(0 != vec);
   28044             : 
   28045       52977 :          next_token();
   28046             : 
   28047       52977 :          if (!token_is(token_t::e_lsqrbracket))
   28048             :          {
   28049       30740 :             return node_allocator_.allocate<vector_node_t>(vec);
   28050             :          }
   28051       22237 :          else if (token_is(token_t::e_rsqrbracket))
   28052             :          {
   28053        3355 :             return (vec->rebaseable()) ?
   28054         188 :                node_allocator_.allocate<vector_size_node_t>(vec) :
   28055        3355 :                expression_generator_(T(vec->size()));
   28056             :          }
   28057             : 
   28058       18882 :          expression_node_ptr index_expr = parse_vector_index(vector_name);
   28059             : 
   28060       18882 :          if (index_expr)
   28061             :          {
   28062       18882 :             expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec);
   28063             : 
   28064       18882 :             return synthesize_vector_element(vector_name, vec, vec_node, index_expr);
   28065             :          }
   28066             : 
   28067           0 :          return error_node();
   28068       52977 :       }
   28069             : 
   28070       19542 :       inline expression_node_ptr synthesize_vector_element(const std::string& vector_name,
   28071             :                                                            vector_holder_ptr vec,
   28072             :                                                            expression_node_ptr vec_node,
   28073             :                                                            expression_node_ptr index_expr)
   28074             :       {
   28075             :          // Perform compile-time range check
   28076       19542 :          if (details::is_constant_node(index_expr))
   28077             :          {
   28078       14723 :             const std::size_t index    = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
   28079       14723 :             const std::size_t vec_size = vec->size();
   28080             : 
   28081       14723 :             if (index >= vec_size)
   28082             :             {
   28083           0 :                set_error(make_error(
   28084             :                   parser_error::e_syntax,
   28085           0 :                   current_token(),
   28086             :                   "ERR124 - Index of " + details::to_str(index) + " out of range for "
   28087             :                   "vector '" + vector_name + "' of size " + details::to_str(vec_size),
   28088             :                   exprtk_error_location));
   28089             : 
   28090           0 :                free_node(node_allocator_, vec_node  );
   28091           0 :                free_node(node_allocator_, index_expr);
   28092             : 
   28093           0 :                return error_node();
   28094             :             }
   28095             :          }
   28096             : 
   28097       19542 :          return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr);
   28098             :       }
   28099             : 
   28100          49 :       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
   28101             :       {
   28102          49 :          std::vector<expression_node_ptr> arg_list;
   28103             : 
   28104          49 :          expression_node_ptr result = error_node();
   28105             : 
   28106          49 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   28107             : 
   28108          49 :          next_token();
   28109             : 
   28110          49 :          if (token_is(token_t::e_lbracket))
   28111             :          {
   28112          48 :             if (token_is(token_t::e_rbracket))
   28113             :             {
   28114           1 :                if (!vararg_function->allow_zero_parameters())
   28115             :                {
   28116           0 :                   set_error(make_error(
   28117             :                      parser_error::e_syntax,
   28118           0 :                      current_token(),
   28119             :                      "ERR125 - Zero parameter call to vararg function: "
   28120             :                      + vararg_function_name + " not allowed",
   28121             :                      exprtk_error_location));
   28122             : 
   28123           0 :                   return error_node();
   28124             :                }
   28125             :             }
   28126             :             else
   28127             :             {
   28128          70 :                for ( ; ; )
   28129             :                {
   28130         117 :                   expression_node_ptr arg = parse_expression();
   28131             : 
   28132         117 :                   if (0 == arg)
   28133           0 :                      return error_node();
   28134             :                   else
   28135         117 :                      arg_list.push_back(arg);
   28136             : 
   28137         117 :                   if (token_is(token_t::e_rbracket))
   28138          47 :                      break;
   28139          70 :                   else if (!token_is(token_t::e_comma))
   28140             :                   {
   28141           0 :                      set_error(make_error(
   28142             :                         parser_error::e_syntax,
   28143           0 :                         current_token(),
   28144             :                         "ERR126 - Expected ',' for call to vararg function: "
   28145             :                         + vararg_function_name,
   28146             :                         exprtk_error_location));
   28147             : 
   28148           0 :                      return error_node();
   28149             :                   }
   28150             :                }
   28151             :             }
   28152             :          }
   28153           1 :          else if (!vararg_function->allow_zero_parameters())
   28154             :          {
   28155           0 :             set_error(make_error(
   28156             :                parser_error::e_syntax,
   28157           0 :                current_token(),
   28158             :                "ERR127 - Zero parameter call to vararg function: "
   28159             :                + vararg_function_name + " not allowed",
   28160             :                exprtk_error_location));
   28161             : 
   28162           0 :             return error_node();
   28163             :          }
   28164             : 
   28165          49 :          if (arg_list.size() < vararg_function->min_num_args())
   28166             :          {
   28167           0 :             set_error(make_error(
   28168             :                parser_error::e_syntax,
   28169           0 :                current_token(),
   28170             :                "ERR128 - Invalid number of parameters to call to vararg function: "
   28171             :                + vararg_function_name + ", require at least "
   28172           0 :                + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
   28173             :                exprtk_error_location));
   28174             : 
   28175           0 :             return error_node();
   28176             :          }
   28177          49 :          else if (arg_list.size() > vararg_function->max_num_args())
   28178             :          {
   28179           0 :             set_error(make_error(
   28180             :                parser_error::e_syntax,
   28181           0 :                current_token(),
   28182             :                "ERR129 - Invalid number of parameters to call to vararg function: "
   28183             :                + vararg_function_name + ", require no more than "
   28184           0 :                + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
   28185             :                exprtk_error_location));
   28186             : 
   28187           0 :             return error_node();
   28188             :          }
   28189             : 
   28190          49 :          result = expression_generator_.vararg_function_call(vararg_function,arg_list);
   28191             : 
   28192          49 :          sdd.delete_ptr = (0 == result);
   28193             : 
   28194          49 :          return result;
   28195          49 :       }
   28196             : 
   28197             :       class type_checker
   28198             :       {
   28199             :       public:
   28200             : 
   28201             :          enum return_type_t
   28202             :          {
   28203             :             e_overload = ' ',
   28204             :             e_numeric  = 'T',
   28205             :             e_string   = 'S'
   28206             :          };
   28207             : 
   28208             :          struct function_prototype_t
   28209             :          {
   28210             :              return_type_t return_type;
   28211             :              std::string   param_seq;
   28212             :          };
   28213             : 
   28214             :          typedef parser<T> parser_t;
   28215             :          typedef std::vector<function_prototype_t> function_definition_list_t;
   28216             : 
   28217        3608 :          type_checker(parser_t& p,
   28218             :                       const std::string& func_name,
   28219             :                       const std::string& func_prototypes,
   28220             :                       const return_type_t default_return_type)
   28221        3608 :          : invalid_state_(true)
   28222        3608 :          , parser_(p)
   28223        3608 :          , function_name_(func_name)
   28224        3608 :          , default_return_type_(default_return_type)
   28225             :          {
   28226        3608 :             parse_function_prototypes(func_prototypes);
   28227        3608 :          }
   28228             : 
   28229        3608 :          bool verify(const std::string& param_seq, std::size_t& pseq_index)
   28230             :          {
   28231        3608 :             if (function_definition_list_.empty())
   28232          10 :                return true;
   28233             : 
   28234        3598 :             std::vector<std::pair<std::size_t,char> > error_list;
   28235             : 
   28236        5662 :             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
   28237             :             {
   28238        5662 :                details::char_t diff_value = 0;
   28239        5662 :                std::size_t     diff_index = 0;
   28240             : 
   28241        5662 :                const bool result = details::sequence_match(function_definition_list_[i].param_seq,
   28242             :                                                            param_seq,
   28243             :                                                            diff_index, diff_value);
   28244             : 
   28245        5662 :               if (result)
   28246             :               {
   28247        3598 :                  pseq_index = i;
   28248        3598 :                  return true;
   28249             :               }
   28250             :               else
   28251        2064 :                  error_list.push_back(std::make_pair(diff_index, diff_value));
   28252             :             }
   28253             : 
   28254           0 :             if (1 == error_list.size())
   28255             :             {
   28256           0 :                parser_.set_error(make_error(
   28257             :                   parser_error::e_syntax,
   28258           0 :                   parser_.current_token(),
   28259           0 :                   "ERR130 - Failed parameter type check for function '" + function_name_ + "', "
   28260           0 :                   "Expected '" + function_definition_list_[0].param_seq +
   28261             :                   "' call set: '" + param_seq + "'",
   28262             :                   exprtk_error_location));
   28263             :             }
   28264             :             else
   28265             :             {
   28266             :                // find first with largest diff_index;
   28267           0 :                std::size_t max_diff_index = 0;
   28268             : 
   28269           0 :                for (std::size_t i = 1; i < error_list.size(); ++i)
   28270             :                {
   28271           0 :                   if (error_list[i].first > error_list[max_diff_index].first)
   28272             :                   {
   28273           0 :                      max_diff_index = i;
   28274             :                   }
   28275             :                }
   28276             : 
   28277           0 :                parser_.set_error(make_error(
   28278             :                   parser_error::e_syntax,
   28279           0 :                   parser_.current_token(),
   28280           0 :                   "ERR131 - Failed parameter type check for function '" + function_name_ + "', "
   28281           0 :                   "Best match: '" + function_definition_list_[max_diff_index].param_seq +
   28282             :                   "' call set: '" + param_seq + "'",
   28283             :                   exprtk_error_location));
   28284             :             }
   28285             : 
   28286           0 :             return false;
   28287        3598 :          }
   28288             : 
   28289        3716 :          std::size_t paramseq_count() const
   28290             :          {
   28291        3716 :             return function_definition_list_.size();
   28292             :          }
   28293             : 
   28294             :          std::string paramseq(const std::size_t& index) const
   28295             :          {
   28296             :             return function_definition_list_[index].param_seq;
   28297             :          }
   28298             : 
   28299         108 :          return_type_t return_type(const std::size_t& index) const
   28300             :          {
   28301         108 :             return function_definition_list_[index].return_type;
   28302             :          }
   28303             : 
   28304        3500 :          bool invalid() const
   28305             :          {
   28306        3500 :             return !invalid_state_;
   28307             :          }
   28308             : 
   28309           8 :          bool allow_zero_parameters() const
   28310             :          {
   28311             : 
   28312           8 :             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
   28313             :             {
   28314           8 :                if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
   28315             :                {
   28316           8 :                   return true;
   28317             :                }
   28318             :             }
   28319             : 
   28320           0 :             return false;
   28321             :          }
   28322             : 
   28323             :       private:
   28324             : 
   28325        3598 :          std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
   28326             :          {
   28327        3598 :              std::string::const_iterator current_begin = param_seq.begin();
   28328        3598 :              std::string::const_iterator iter          = param_seq.begin();
   28329             : 
   28330        3598 :              std::vector<std::string> result;
   28331             : 
   28332       38882 :              while (iter != param_seq.end())
   28333             :              {
   28334       35284 :                  if (*iter == delimiter)
   28335             :                  {
   28336        5872 :                      result.push_back(std::string(current_begin, iter));
   28337        5872 :                      current_begin = ++iter;
   28338             :                  }
   28339             :                  else
   28340       29412 :                      ++iter;
   28341             :              }
   28342             : 
   28343        3598 :              if (current_begin != iter)
   28344             :              {
   28345        7196 :                  result.push_back(std::string(current_begin, iter));
   28346             :              }
   28347             : 
   28348        7196 :              return result;
   28349           0 :          }
   28350             : 
   28351        9470 :          inline bool is_valid_token(std::string param_seq,
   28352             :                                     function_prototype_t& funcproto) const
   28353             :          {
   28354             :             // Determine return type
   28355        9470 :             funcproto.return_type = default_return_type_;
   28356             : 
   28357        9470 :             if (param_seq.size() > 2)
   28358             :             {
   28359        6129 :                if (':' == param_seq[1])
   28360             :                {
   28361             :                   // Note: Only overloaded igeneric functions can have return
   28362             :                   // type definitions.
   28363        1296 :                   if (type_checker::e_overload != default_return_type_)
   28364           0 :                      return false;
   28365             : 
   28366        1296 :                   switch (param_seq[0])
   28367             :                   {
   28368         648 :                      case 'T' : funcproto.return_type = type_checker::e_numeric;
   28369         648 :                                 break;
   28370             : 
   28371         648 :                      case 'S' : funcproto.return_type = type_checker::e_string;
   28372         648 :                                 break;
   28373             : 
   28374           0 :                      default  : return false;
   28375             :                   }
   28376             : 
   28377        1296 :                   param_seq.erase(0,2);
   28378             :                }
   28379             :             }
   28380             : 
   28381        9470 :             if (
   28382       18940 :                  (std::string::npos != param_seq.find("?*")) ||
   28383        9470 :                  (std::string::npos != param_seq.find("**"))
   28384             :                )
   28385             :             {
   28386           0 :                return false;
   28387             :             }
   28388        9470 :             else if (
   28389        9499 :                       (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
   28390          29 :                       ("Z" == param_seq)
   28391             :                     )
   28392             :             {
   28393        9470 :                funcproto.param_seq = param_seq;
   28394        9470 :                return true;
   28395             :             }
   28396             : 
   28397           0 :             return false;
   28398             :          }
   28399             : 
   28400        3608 :          void parse_function_prototypes(const std::string& func_prototypes)
   28401             :          {
   28402        3608 :             if (func_prototypes.empty())
   28403          10 :                return;
   28404             : 
   28405        3598 :             std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
   28406             : 
   28407             :             typedef std::map<std::string,std::size_t> param_seq_map_t;
   28408        3598 :             param_seq_map_t param_seq_map;
   28409             : 
   28410       22538 :             for (std::size_t i = 0; i < param_seq_list.size(); ++i)
   28411             :             {
   28412        9470 :                function_prototype_t func_proto;
   28413             : 
   28414        9470 :                if (!is_valid_token(param_seq_list[i], func_proto))
   28415             :                {
   28416           0 :                   invalid_state_ = false;
   28417             : 
   28418           0 :                   parser_.set_error(make_error(
   28419             :                      parser_error::e_syntax,
   28420           0 :                      parser_.current_token(),
   28421           0 :                      "ERR132 - Invalid parameter sequence of '" + param_seq_list[i] +
   28422           0 :                      "' for function: " + function_name_,
   28423             :                      exprtk_error_location));
   28424           0 :                   return;
   28425             :                }
   28426             : 
   28427        9470 :                param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
   28428             : 
   28429        9470 :                if (param_seq_map.end() != seq_itr)
   28430             :                {
   28431           0 :                   invalid_state_ = false;
   28432             : 
   28433           0 :                   parser_.set_error(make_error(
   28434             :                      parser_error::e_syntax,
   28435           0 :                      parser_.current_token(),
   28436           0 :                      "ERR133 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
   28437           0 :                      "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
   28438             :                      "pseq_idx[" + details::to_str(i) + "] " +
   28439           0 :                      "param seq: " + param_seq_list[i],
   28440             :                      exprtk_error_location));
   28441           0 :                   return;
   28442             :                }
   28443             : 
   28444        9470 :                function_definition_list_.push_back(func_proto);
   28445             :             }
   28446        3598 :          }
   28447             : 
   28448             :          type_checker(const type_checker&) exprtk_delete;
   28449             :          type_checker& operator=(const type_checker&) exprtk_delete;
   28450             : 
   28451             :          bool invalid_state_;
   28452             :          parser_t& parser_;
   28453             :          std::string function_name_;
   28454             :          const return_type_t default_return_type_;
   28455             :          function_definition_list_t function_definition_list_;
   28456             :       };
   28457             : 
   28458        3500 :       inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
   28459             :       {
   28460        3500 :          std::vector<expression_node_ptr> arg_list;
   28461             : 
   28462        3500 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   28463             : 
   28464        3500 :          next_token();
   28465             : 
   28466        3500 :          std::string param_type_list;
   28467             : 
   28468        3500 :          type_checker tc(
   28469             :             (*this),
   28470             :             function_name,
   28471        3500 :             function->parameter_sequence,
   28472             :             type_checker::e_string);
   28473             : 
   28474        3500 :          if (tc.invalid())
   28475             :          {
   28476           0 :             set_error(make_error(
   28477             :                parser_error::e_syntax,
   28478           0 :                current_token(),
   28479             :                "ERR134 - Type checker instantiation failure for generic function: " + function_name,
   28480             :                exprtk_error_location));
   28481             : 
   28482           0 :             return error_node();
   28483             :          }
   28484             : 
   28485        3500 :          if (token_is(token_t::e_lbracket))
   28486             :          {
   28487        3493 :             if (token_is(token_t::e_rbracket))
   28488             :             {
   28489           8 :                if (
   28490          16 :                     !function->allow_zero_parameters() &&
   28491           8 :                     !tc       .allow_zero_parameters()
   28492             :                   )
   28493             :                {
   28494           0 :                   set_error(make_error(
   28495             :                      parser_error::e_syntax,
   28496           0 :                      current_token(),
   28497             :                      "ERR135 - Zero parameter call to generic function: "
   28498             :                      + function_name + " not allowed",
   28499             :                      exprtk_error_location));
   28500             : 
   28501           0 :                   return error_node();
   28502             :                }
   28503             :             }
   28504             :             else
   28505             :             {
   28506        4381 :                for ( ; ; )
   28507             :                {
   28508        7866 :                   expression_node_ptr arg = parse_expression();
   28509             : 
   28510        7866 :                   if (0 == arg)
   28511           0 :                      return error_node();
   28512             : 
   28513        7866 :                   if (is_ivector_node(arg))
   28514        4324 :                      param_type_list += 'V';
   28515        3542 :                   else if (is_generally_string_node(arg))
   28516          94 :                      param_type_list += 'S';
   28517             :                   else // Everything else is assumed to be a scalar returning expression
   28518        3448 :                      param_type_list += 'T';
   28519             : 
   28520        7866 :                   arg_list.push_back(arg);
   28521             : 
   28522        7866 :                   if (token_is(token_t::e_rbracket))
   28523        3485 :                      break;
   28524        4381 :                   else if (!token_is(token_t::e_comma))
   28525             :                   {
   28526           0 :                      set_error(make_error(
   28527             :                         parser_error::e_syntax,
   28528           0 :                         current_token(),
   28529             :                         "ERR136 - Expected ',' for call to generic function: " + function_name,
   28530             :                         exprtk_error_location));
   28531             : 
   28532           0 :                      return error_node();
   28533             :                   }
   28534             :                }
   28535             :             }
   28536             :          }
   28537           7 :          else if (
   28538          14 :                    !function->parameter_sequence.empty() &&
   28539          14 :                    function->allow_zero_parameters    () &&
   28540           0 :                    !tc      .allow_zero_parameters    ()
   28541             :                  )
   28542             :          {
   28543           0 :             set_error(make_error(
   28544             :                parser_error::e_syntax,
   28545           0 :                current_token(),
   28546             :                "ERR137 - Zero parameter call to generic function: "
   28547             :                + function_name + " not allowed",
   28548             :                exprtk_error_location));
   28549             : 
   28550           0 :             return error_node();
   28551             :          }
   28552             : 
   28553        3500 :          std::size_t param_seq_index = 0;
   28554             : 
   28555        3500 :          if (
   28556        7000 :               state_.type_check_enabled &&
   28557        3500 :               !tc.verify(param_type_list, param_seq_index)
   28558             :             )
   28559             :          {
   28560           0 :             set_error(make_error(
   28561             :                parser_error::e_syntax,
   28562           0 :                current_token(),
   28563             :                "ERR138 - Invalid input parameter sequence for call to generic function: " + function_name,
   28564             :                exprtk_error_location));
   28565             : 
   28566           0 :             return error_node();
   28567             :          }
   28568             : 
   28569        3500 :          expression_node_ptr result = error_node();
   28570             : 
   28571        3500 :          result = (tc.paramseq_count() <= 1) ?
   28572             :                   expression_generator_
   28573          57 :                        .generic_function_call(function, arg_list) :
   28574             :                   expression_generator_
   28575        3443 :                        .generic_function_call(function, arg_list, param_seq_index);
   28576             : 
   28577        3500 :          sdd.delete_ptr = (0 == result);
   28578             : 
   28579        3500 :          return result;
   28580        3500 :       }
   28581             : 
   28582         108 :       inline bool parse_igeneric_function_params(std::string& param_type_list,
   28583             :                                                  std::vector<expression_node_ptr>& arg_list,
   28584             :                                                  const std::string& function_name,
   28585             :                                                  igeneric_function<T>* function,
   28586             :                                                  const type_checker& tc)
   28587             :       {
   28588         108 :          if (token_is(token_t::e_lbracket))
   28589             :          {
   28590         108 :             if (token_is(token_t::e_rbracket))
   28591             :             {
   28592           0 :                if (
   28593           0 :                     !function->allow_zero_parameters() &&
   28594           0 :                     !tc       .allow_zero_parameters()
   28595             :                   )
   28596             :                {
   28597           0 :                   set_error(make_error(
   28598             :                      parser_error::e_syntax,
   28599           0 :                      current_token(),
   28600             :                      "ERR139 - Zero parameter call to generic function: "
   28601             :                      + function_name + " not allowed",
   28602             :                      exprtk_error_location));
   28603             : 
   28604           0 :                   return false;
   28605             :                }
   28606             :             }
   28607             :             else
   28608             :             {
   28609         144 :                for ( ; ; )
   28610             :                {
   28611         252 :                   expression_node_ptr arg = parse_expression();
   28612             : 
   28613         252 :                   if (0 == arg)
   28614           0 :                      return false;
   28615             : 
   28616         252 :                   if (is_ivector_node(arg))
   28617           0 :                      param_type_list += 'V';
   28618         252 :                   else if (is_generally_string_node(arg))
   28619         144 :                      param_type_list += 'S';
   28620             :                   else // Everything else is a scalar returning expression
   28621         108 :                      param_type_list += 'T';
   28622             : 
   28623         252 :                   arg_list.push_back(arg);
   28624             : 
   28625         252 :                   if (token_is(token_t::e_rbracket))
   28626         108 :                      break;
   28627         144 :                   else if (!token_is(token_t::e_comma))
   28628             :                   {
   28629           0 :                      set_error(make_error(
   28630             :                         parser_error::e_syntax,
   28631           0 :                         current_token(),
   28632             :                         "ERR140 - Expected ',' for call to string function: " + function_name,
   28633             :                         exprtk_error_location));
   28634             : 
   28635           0 :                      return false;
   28636             :                   }
   28637             :                }
   28638             :             }
   28639             : 
   28640         108 :             return true;
   28641             :          }
   28642             :          else
   28643           0 :             return false;
   28644             :       }
   28645             : 
   28646             :       #ifndef exprtk_disable_string_capabilities
   28647          36 :       inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
   28648             :       {
   28649             :          // Move pass the function name
   28650          36 :          next_token();
   28651             : 
   28652          36 :          std::string param_type_list;
   28653             : 
   28654          36 :          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
   28655             : 
   28656          36 :          if (
   28657          72 :               (!function->parameter_sequence.empty()) &&
   28658          36 :               (0 == tc.paramseq_count())
   28659             :             )
   28660             :          {
   28661           0 :             return error_node();
   28662             :          }
   28663             : 
   28664          36 :          std::vector<expression_node_ptr> arg_list;
   28665          36 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   28666             : 
   28667          36 :          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
   28668             :          {
   28669           0 :             return error_node();
   28670             :          }
   28671             : 
   28672          36 :          std::size_t param_seq_index = 0;
   28673             : 
   28674          36 :          if (!tc.verify(param_type_list, param_seq_index))
   28675             :          {
   28676           0 :             set_error(make_error(
   28677             :                parser_error::e_syntax,
   28678           0 :                current_token(),
   28679             :                "ERR141 - Invalid input parameter sequence for call to string function: " + function_name,
   28680             :                exprtk_error_location));
   28681             : 
   28682           0 :             return error_node();
   28683             :          }
   28684             : 
   28685          36 :          expression_node_ptr result = error_node();
   28686             : 
   28687          36 :          result = (tc.paramseq_count() <= 1) ?
   28688             :                   expression_generator_
   28689           0 :                        .string_function_call(function, arg_list) :
   28690             :                   expression_generator_
   28691          36 :                        .string_function_call(function, arg_list, param_seq_index);
   28692             : 
   28693          36 :          sdd.delete_ptr = (0 == result);
   28694             : 
   28695          36 :          return result;
   28696          36 :       }
   28697             : 
   28698          72 :       inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
   28699             :       {
   28700             :          // Move pass the function name
   28701          72 :          next_token();
   28702             : 
   28703          72 :          std::string param_type_list;
   28704             : 
   28705          72 :          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
   28706             : 
   28707          72 :          if (
   28708         144 :               (!function->parameter_sequence.empty()) &&
   28709          72 :               (0 == tc.paramseq_count())
   28710             :             )
   28711             :          {
   28712           0 :             return error_node();
   28713             :          }
   28714             : 
   28715          72 :          std::vector<expression_node_ptr> arg_list;
   28716          72 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   28717             : 
   28718          72 :          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
   28719             :          {
   28720           0 :             return error_node();
   28721             :          }
   28722             : 
   28723          72 :          std::size_t param_seq_index = 0;
   28724             : 
   28725          72 :          if (!tc.verify(param_type_list, param_seq_index))
   28726             :          {
   28727           0 :             set_error(make_error(
   28728             :                parser_error::e_syntax,
   28729           0 :                current_token(),
   28730             :                "ERR142 - Invalid input parameter sequence for call to overloaded function: " + function_name,
   28731             :                exprtk_error_location));
   28732             : 
   28733           0 :             return error_node();
   28734             :          }
   28735             : 
   28736          72 :          expression_node_ptr result = error_node();
   28737             : 
   28738          72 :          if (type_checker::e_numeric == tc.return_type(param_seq_index))
   28739             :          {
   28740          36 :             if (tc.paramseq_count() <= 1)
   28741             :                result = expression_generator_
   28742           0 :                           .generic_function_call(function, arg_list);
   28743             :             else
   28744             :                result = expression_generator_
   28745          36 :                           .generic_function_call(function, arg_list, param_seq_index);
   28746             :          }
   28747          36 :          else if (type_checker::e_string == tc.return_type(param_seq_index))
   28748             :          {
   28749          36 :             if (tc.paramseq_count() <= 1)
   28750             :                result = expression_generator_
   28751           0 :                           .string_function_call(function, arg_list);
   28752             :             else
   28753             :                result = expression_generator_
   28754          36 :                           .string_function_call(function, arg_list, param_seq_index);
   28755             :          }
   28756             :          else
   28757             :          {
   28758           0 :             set_error(make_error(
   28759             :                parser_error::e_syntax,
   28760           0 :                current_token(),
   28761             :                "ERR143 - Invalid return type for call to overloaded function: " + function_name,
   28762             :                exprtk_error_location));
   28763             :          }
   28764             : 
   28765          72 :          sdd.delete_ptr = (0 == result);
   28766          72 :          return result;
   28767          72 :       }
   28768             :       #endif
   28769             : 
   28770             :       template <typename Type, std::size_t NumberOfParameters>
   28771             :       struct parse_special_function_impl
   28772             :       {
   28773        4245 :          static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
   28774             :          {
   28775             :             expression_node_ptr branch[NumberOfParameters];
   28776        4245 :             expression_node_ptr result = error_node();
   28777             : 
   28778        4245 :             std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0));
   28779             : 
   28780        4245 :             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
   28781             : 
   28782        4245 :             p.next_token();
   28783             : 
   28784        4245 :             if (!p.token_is(token_t::e_lbracket))
   28785             :             {
   28786           0 :                p.set_error(make_error(
   28787             :                   parser_error::e_syntax,
   28788           0 :                   p.current_token(),
   28789             :                   "ERR144 - Expected '(' for special function '" + sf_name + "'",
   28790             :                   exprtk_error_location));
   28791             : 
   28792           0 :                return error_node();
   28793             :             }
   28794             : 
   28795       19305 :             for (std::size_t i = 0; i < NumberOfParameters; ++i)
   28796             :             {
   28797       15060 :                branch[i] = p.parse_expression();
   28798             : 
   28799       15060 :                if (0 == branch[i])
   28800             :                {
   28801           0 :                   return p.error_node();
   28802             :                }
   28803       15060 :                else if (i < (NumberOfParameters - 1))
   28804             :                {
   28805       10815 :                   if (!p.token_is(token_t::e_comma))
   28806             :                   {
   28807           0 :                      p.set_error(make_error(
   28808             :                         parser_error::e_syntax,
   28809           0 :                         p.current_token(),
   28810             :                         "ERR145 - Expected ',' before next parameter of special function '" + sf_name + "'",
   28811             :                         exprtk_error_location));
   28812             : 
   28813           0 :                      return p.error_node();
   28814             :                   }
   28815             :                }
   28816             :             }
   28817             : 
   28818        4245 :             if (!p.token_is(token_t::e_rbracket))
   28819             :             {
   28820           0 :                p.set_error(make_error(
   28821             :                   parser_error::e_syntax,
   28822           0 :                   p.current_token(),
   28823             :                   "ERR146 - Invalid number of parameters for special function '" + sf_name + "'",
   28824             :                   exprtk_error_location));
   28825             : 
   28826           0 :                return p.error_node();
   28827             :             }
   28828             :             else
   28829        4245 :                result = p.expression_generator_.special_function(opt_type,branch);
   28830             : 
   28831        4245 :             sd.delete_ptr = (0 == result);
   28832             : 
   28833        4245 :             return result;
   28834        4245 :          }
   28835             :       };
   28836             : 
   28837        4245 :       inline expression_node_ptr parse_special_function()
   28838             :       {
   28839        4245 :          const std::string sf_name = current_token().value;
   28840             : 
   28841             :          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
   28842        4245 :          if (
   28843        8490 :               !details::is_digit(sf_name[2]) ||
   28844        4245 :               !details::is_digit(sf_name[3])
   28845             :             )
   28846             :          {
   28847           0 :             set_error(make_error(
   28848             :                parser_error::e_token,
   28849           0 :                current_token(),
   28850             :                "ERR147 - Invalid special function[1]: " + sf_name,
   28851             :                exprtk_error_location));
   28852             : 
   28853           0 :             return error_node();
   28854             :          }
   28855             : 
   28856        4245 :          const int id = (sf_name[2] - '0') * 10 +
   28857        4245 :                         (sf_name[3] - '0');
   28858             : 
   28859        4245 :          if (id >= details::e_sffinal)
   28860             :          {
   28861           0 :             set_error(make_error(
   28862             :                parser_error::e_token,
   28863           0 :                current_token(),
   28864             :                "ERR148 - Invalid special function[2]: " + sf_name,
   28865             :                exprtk_error_location));
   28866             : 
   28867           0 :             return error_node();
   28868             :          }
   28869             : 
   28870        4245 :          const int sf_3_to_4                   = details::e_sf48;
   28871        4245 :          const details::operator_type opt_type = details::operator_type(id + 1000);
   28872        4245 :          const std::size_t NumberOfParameters  = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
   28873             : 
   28874        4245 :          switch (NumberOfParameters)
   28875             :          {
   28876        1920 :             case 3  : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
   28877        2325 :             case 4  : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
   28878           0 :             default : return error_node();
   28879             :          }
   28880        4245 :       }
   28881             : 
   28882         275 :       inline expression_node_ptr parse_null_statement()
   28883             :       {
   28884         275 :          next_token();
   28885         275 :          return node_allocator_.allocate<details::null_node<T> >();
   28886             :       }
   28887             : 
   28888             :       #ifndef exprtk_disable_break_continue
   28889         483 :       inline expression_node_ptr parse_break_statement()
   28890             :       {
   28891         483 :          if (state_.parsing_break_stmt)
   28892             :          {
   28893           0 :             set_error(make_error(
   28894             :                parser_error::e_syntax,
   28895           0 :                current_token(),
   28896             :                "ERR149 - Invoking 'break' within a break call is not allowed",
   28897             :                exprtk_error_location));
   28898             : 
   28899           0 :             return error_node();
   28900             :          }
   28901         483 :          else if (0 == state_.parsing_loop_stmt_count)
   28902             :          {
   28903           0 :             set_error(make_error(
   28904             :                parser_error::e_syntax,
   28905           0 :                current_token(),
   28906             :                "ERR150 - Invalid use of 'break', allowed only in the scope of a loop",
   28907             :                exprtk_error_location));
   28908             : 
   28909           0 :             return error_node();
   28910             :          }
   28911             : 
   28912         483 :          scoped_bool_negator sbn(state_.parsing_break_stmt);
   28913             : 
   28914         483 :          if (!brkcnt_list_.empty())
   28915             :          {
   28916         483 :             next_token();
   28917             : 
   28918         483 :             brkcnt_list_.front() = true;
   28919             : 
   28920         483 :             expression_node_ptr return_expr = error_node();
   28921             : 
   28922         483 :             if (token_is(token_t::e_lsqrbracket))
   28923             :             {
   28924         402 :                if (0 == (return_expr = parse_expression()))
   28925             :                {
   28926           0 :                   set_error(make_error(
   28927             :                      parser_error::e_syntax,
   28928           0 :                      current_token(),
   28929             :                      "ERR151 - Failed to parse return expression for 'break' statement",
   28930             :                      exprtk_error_location));
   28931             : 
   28932           0 :                   return error_node();
   28933             :                }
   28934         402 :                else if (!token_is(token_t::e_rsqrbracket))
   28935             :                {
   28936           0 :                   set_error(make_error(
   28937             :                      parser_error::e_syntax,
   28938           0 :                      current_token(),
   28939             :                      "ERR152 - Expected ']' at the completion of break's return expression",
   28940             :                      exprtk_error_location));
   28941             : 
   28942           0 :                   free_node(node_allocator_,return_expr);
   28943             : 
   28944           0 :                   return error_node();
   28945             :                }
   28946             :             }
   28947             : 
   28948         966 :             state_.activate_side_effect("parse_break_statement()");
   28949             : 
   28950         483 :             return node_allocator_.allocate<details::break_node<T> >(return_expr);
   28951             :          }
   28952             :          else
   28953             :          {
   28954           0 :             set_error(make_error(
   28955             :                parser_error::e_syntax,
   28956           0 :                current_token(),
   28957             :                "ERR153 - Invalid use of 'break', allowed only in the scope of a loop",
   28958             :                exprtk_error_location));
   28959             :          }
   28960             : 
   28961           0 :          return error_node();
   28962         483 :       }
   28963             : 
   28964         460 :       inline expression_node_ptr parse_continue_statement()
   28965             :       {
   28966         460 :          if (0 == state_.parsing_loop_stmt_count)
   28967             :          {
   28968           0 :             set_error(make_error(
   28969             :                parser_error::e_syntax,
   28970           0 :                current_token(),
   28971             :                "ERR154 - Invalid use of 'continue', allowed only in the scope of a loop",
   28972             :                exprtk_error_location));
   28973             : 
   28974           0 :             return error_node();
   28975             :          }
   28976             :          else
   28977             :          {
   28978         460 :             next_token();
   28979             : 
   28980         460 :             brkcnt_list_.front() = true;
   28981         920 :             state_.activate_side_effect("parse_continue_statement()");
   28982             : 
   28983         460 :             return node_allocator_.allocate<details::continue_node<T> >();
   28984             :          }
   28985             :       }
   28986             :       #endif
   28987             : 
   28988       24277 :       inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
   28989             :       {
   28990       24277 :          expression_node_ptr size_expression_node = error_node();
   28991             : 
   28992       24277 :          if (!token_is(token_t::e_lsqrbracket))
   28993             :          {
   28994           0 :             set_error(make_error(
   28995             :                parser_error::e_syntax,
   28996           0 :                current_token(),
   28997             :                "ERR155 - Expected '[' as part of vector size definition",
   28998             :                exprtk_error_location));
   28999             : 
   29000           0 :             return error_node();
   29001             :          }
   29002       24277 :          else if (0 == (size_expression_node = parse_expression()))
   29003             :          {
   29004           0 :             set_error(make_error(
   29005             :                parser_error::e_syntax,
   29006           0 :                current_token(),
   29007             :                "ERR156 - Failed to determine size of vector '" + vec_name + "'",
   29008             :                exprtk_error_location));
   29009             : 
   29010           0 :             return error_node();
   29011             :          }
   29012       24277 :          else if (!is_constant_node(size_expression_node))
   29013             :          {
   29014           0 :             const bool is_rebaseble_vector =
   29015           0 :                (size_expression_node->type() == details::expression_node<T>::e_vecsize) &&
   29016           0 :                static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable();
   29017             : 
   29018           0 :             free_node(node_allocator_,size_expression_node);
   29019             : 
   29020           0 :             const std::string error_msg = (is_rebaseble_vector) ?
   29021             :                                           std::string("Rebasable/Resizable vector cannot be used to define the size of vector") :
   29022             :                                           std::string("Expected a constant literal number as size of vector");
   29023           0 :             set_error(make_error(
   29024             :                parser_error::e_syntax,
   29025           0 :                current_token(),
   29026             :                "ERR157 - " + error_msg + " '" + vec_name + "'",
   29027             :                exprtk_error_location));
   29028             : 
   29029           0 :             return error_node();
   29030           0 :          }
   29031             : 
   29032       24277 :          const T vector_size = size_expression_node->value();
   29033             : 
   29034       24277 :          free_node(node_allocator_,size_expression_node);
   29035             : 
   29036       24277 :          const std::size_t max_vector_size = settings_.max_local_vector_size();
   29037             : 
   29038       24277 :          if (
   29039       24277 :               (vector_size <= T(0)) ||
   29040           0 :               std::not_equal_to<T>()
   29041       48554 :               (T(0),vector_size - details::numeric::trunc(vector_size)) ||
   29042       24277 :               (static_cast<std::size_t>(vector_size) > max_vector_size)
   29043             :             )
   29044             :          {
   29045           0 :             set_error(make_error(
   29046             :                parser_error::e_syntax,
   29047           0 :                current_token(),
   29048             :                "ERR158 - Invalid vector size. Must be an integer in the "
   29049             :                "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " +
   29050             :                details::to_str(details::numeric::to_int32(vector_size)),
   29051             :                exprtk_error_location));
   29052             : 
   29053           0 :             return error_node();
   29054             :          }
   29055             : 
   29056       24277 :          typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
   29057             : 
   29058       24277 :          const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
   29059             : 
   29060       24277 :          scope_element& se = sem_.get_element(vec_name);
   29061             : 
   29062       24277 :          if (se.name == vec_name)
   29063             :          {
   29064        1440 :             if (se.active)
   29065             :             {
   29066           0 :                set_error(make_error(
   29067             :                   parser_error::e_syntax,
   29068           0 :                   current_token(),
   29069             :                   "ERR159 - Illegal redefinition of local vector: '" + vec_name + "'",
   29070             :                   exprtk_error_location));
   29071             : 
   29072           0 :                return error_node();
   29073             :             }
   29074        1440 :             else if (
   29075        1440 :                       (se.size == vec_size) &&
   29076        1000 :                       (scope_element::e_vector == se.type)
   29077             :                     )
   29078             :             {
   29079        1000 :                vec_holder = se.vec_node;
   29080        1000 :                se.active  = true;
   29081        1000 :                se.depth   = state_.scope_depth;
   29082        1000 :                se.ref_count++;
   29083             :             }
   29084             :          }
   29085             : 
   29086       24277 :          if (0 == vec_holder)
   29087             :          {
   29088       23277 :             scope_element nse;
   29089       23277 :             nse.name      = vec_name;
   29090       23277 :             nse.active    = true;
   29091       23277 :             nse.ref_count = 1;
   29092       23277 :             nse.type      = scope_element::e_vector;
   29093       23277 :             nse.depth     = state_.scope_depth;
   29094       23277 :             nse.size      = vec_size;
   29095       23277 :             nse.data      = new T[vec_size];
   29096       23277 :             nse.vec_node  = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
   29097             : 
   29098       23277 :             std::memset(nse.data, 0x00, vec_size * sizeof(T));
   29099             : 
   29100       23277 :             if (!sem_.add_element(nse))
   29101             :             {
   29102           0 :                set_error(make_error(
   29103             :                   parser_error::e_syntax,
   29104           0 :                   current_token(),
   29105             :                   "ERR160 - Failed to add new local vector '" + vec_name + "' to SEM",
   29106             :                   exprtk_error_location));
   29107             : 
   29108           0 :                sem_.free_element(nse);
   29109             : 
   29110           0 :                return error_node();
   29111             :             }
   29112             : 
   29113       23277 :             vec_holder = nse.vec_node;
   29114             : 
   29115             :             exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
   29116             :                           nse.name.c_str(),
   29117             :                           static_cast<int>(nse.size)));
   29118       23277 :          }
   29119             : 
   29120       48554 :          state_.activate_side_effect("parse_define_vector_statement()");
   29121             : 
   29122       24277 :          lodge_symbol(vec_name, e_st_local_vector);
   29123             : 
   29124       24277 :          std::vector<expression_node_ptr> vec_initilizer_list;
   29125             : 
   29126       24277 :          scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
   29127             : 
   29128       24277 :          bool single_value_initialiser = false;
   29129       24277 :          bool range_value_initialiser  = false;
   29130       24277 :          bool vec_to_vec_initialiser   = false;
   29131       24277 :          bool null_initialisation      = false;
   29132             : 
   29133       24277 :          if (!token_is(token_t::e_rsqrbracket))
   29134             :          {
   29135           0 :             set_error(make_error(
   29136             :                parser_error::e_syntax,
   29137           0 :                current_token(),
   29138             :                "ERR161 - Expected ']' as part of vector size definition",
   29139             :                exprtk_error_location));
   29140             : 
   29141           0 :             return error_node();
   29142             :          }
   29143       24277 :          else if (!token_is(token_t::e_eof))
   29144             :          {
   29145       24189 :             if (!token_is(token_t::e_assign))
   29146             :             {
   29147           0 :                set_error(make_error(
   29148             :                   parser_error::e_syntax,
   29149           0 :                   current_token(),
   29150             :                   "ERR162 - Expected ':=' as part of vector definition",
   29151             :                   exprtk_error_location));
   29152             : 
   29153           0 :                return error_node();
   29154             :             }
   29155       24189 :             else if (token_is(token_t::e_lsqrbracket))
   29156             :             {
   29157        7293 :                expression_node_ptr initialiser_component = parse_expression();
   29158             : 
   29159        7293 :                if (0 == initialiser_component)
   29160             :                {
   29161           0 :                   set_error(make_error(
   29162             :                      parser_error::e_syntax,
   29163           0 :                      current_token(),
   29164             :                      "ERR163 - Failed to parse first component of vector initialiser for vector: " + vec_name,
   29165             :                      exprtk_error_location));
   29166             : 
   29167           0 :                   return error_node();
   29168             :                }
   29169             : 
   29170        7293 :                vec_initilizer_list.push_back(initialiser_component);
   29171             : 
   29172        7293 :                if (token_is(token_t::e_colon))
   29173             :                {
   29174         215 :                   initialiser_component = parse_expression();
   29175             : 
   29176         215 :                   if (0 == initialiser_component)
   29177             :                   {
   29178           0 :                      set_error(make_error(
   29179             :                         parser_error::e_syntax,
   29180           0 :                         current_token(),
   29181             :                         "ERR164 - Failed to parse second component of vector initialiser for vector: " + vec_name,
   29182             :                         exprtk_error_location));
   29183             : 
   29184           0 :                      return error_node();
   29185             :                   }
   29186             : 
   29187         215 :                   vec_initilizer_list.push_back(initialiser_component);
   29188             :                }
   29189             : 
   29190        7293 :                if (!token_is(token_t::e_rsqrbracket))
   29191             :                {
   29192           0 :                   set_error(make_error(
   29193             :                      parser_error::e_syntax,
   29194           0 :                      current_token(),
   29195             :                      "ERR165 - Expected ']' to close single value vector initialiser",
   29196             :                      exprtk_error_location));
   29197             : 
   29198           0 :                   return error_node();
   29199             :                }
   29200             : 
   29201        7293 :                switch (vec_initilizer_list.size())
   29202             :                {
   29203        7078 :                   case 1 : single_value_initialiser = true; break;
   29204         215 :                   case 2 : range_value_initialiser  = true; break;
   29205             :                }
   29206             :             }
   29207       16896 :             else if (!token_is(token_t::e_lcrlbracket))
   29208             :             {
   29209         370 :                expression_node_ptr initialiser = error_node();
   29210             : 
   29211             :                // Is this a vector to vector assignment and initialisation?
   29212         370 :                if (token_t::e_symbol == current_token().type)
   29213             :                {
   29214             :                   // Is it a locally defined vector?
   29215         370 :                   const scope_element& lcl_se = sem_.get_active_element(current_token().value);
   29216             : 
   29217         370 :                   if (scope_element::e_vector == lcl_se.type)
   29218             :                   {
   29219         290 :                      if (0 != (initialiser = parse_expression()))
   29220         290 :                         vec_initilizer_list.push_back(initialiser);
   29221             :                      else
   29222           0 :                         return error_node();
   29223             :                   }
   29224             :                   // Are we dealing with a user defined vector?
   29225          80 :                   else if (symtab_store_.is_vector(current_token().value))
   29226             :                   {
   29227           0 :                      lodge_symbol(current_token().value, e_st_vector);
   29228             : 
   29229           0 :                      if (0 != (initialiser = parse_expression()))
   29230           0 :                         vec_initilizer_list.push_back(initialiser);
   29231             :                      else
   29232           0 :                         return error_node();
   29233             :                   }
   29234             :                   // Are we dealing with a null initialisation vector definition?
   29235         240 :                   else if (token_is(token_t::e_symbol,"null"))
   29236          80 :                      null_initialisation = true;
   29237             :                }
   29238             : 
   29239         370 :                if (!null_initialisation)
   29240             :                {
   29241         290 :                   if (0 == initialiser)
   29242             :                   {
   29243           0 :                      set_error(make_error(
   29244             :                         parser_error::e_syntax,
   29245           0 :                         current_token(),
   29246             :                         "ERR166 - Expected '{' as part of vector initialiser list",
   29247             :                         exprtk_error_location));
   29248             : 
   29249           0 :                      return error_node();
   29250             :                   }
   29251             :                   else
   29252         290 :                      vec_to_vec_initialiser = true;
   29253             :                }
   29254             :             }
   29255       16526 :             else if (!token_is(token_t::e_rcrlbracket))
   29256             :             {
   29257       43716 :                for ( ; ; )
   29258             :                {
   29259       59422 :                   expression_node_ptr initialiser = parse_expression();
   29260             : 
   29261       59422 :                   if (0 == initialiser)
   29262             :                   {
   29263           0 :                      set_error(make_error(
   29264             :                         parser_error::e_syntax,
   29265           0 :                         current_token(),
   29266             :                         "ERR167 - Expected '{' as part of vector initialiser list",
   29267             :                         exprtk_error_location));
   29268             : 
   29269           0 :                      return error_node();
   29270             :                   }
   29271             :                   else
   29272       59422 :                      vec_initilizer_list.push_back(initialiser);
   29273             : 
   29274       59422 :                   if (token_is(token_t::e_rcrlbracket))
   29275       15706 :                      break;
   29276             : 
   29277       43716 :                   const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
   29278             : 
   29279       43716 :                   if (!token_is(token_t::e_comma) && is_next_close)
   29280             :                   {
   29281           0 :                      set_error(make_error(
   29282             :                         parser_error::e_syntax,
   29283           0 :                         current_token(),
   29284             :                         "ERR168 - Expected ',' between vector initialisers",
   29285             :                         exprtk_error_location));
   29286             : 
   29287           0 :                      return error_node();
   29288             :                   }
   29289             : 
   29290       43716 :                   if (token_is(token_t::e_rcrlbracket))
   29291           0 :                      break;
   29292             :                }
   29293             :             }
   29294             : 
   29295       24189 :             if (
   29296       24189 :                  !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
   29297       46058 :                  !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
   29298       46058 :                  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
   29299             :                )
   29300             :             {
   29301       21869 :                if (!token_is(token_t::e_eof))
   29302             :                {
   29303           0 :                   set_error(make_error(
   29304             :                      parser_error::e_syntax,
   29305           0 :                      current_token(),
   29306             :                      "ERR169 - Expected ';' at end of vector definition",
   29307             :                      exprtk_error_location));
   29308             : 
   29309           0 :                   return error_node();
   29310             :                }
   29311             :             }
   29312             : 
   29313       24189 :             if (
   29314       41300 :                  !single_value_initialiser &&
   29315       41085 :                  !range_value_initialiser  &&
   29316       16896 :                  (T(vec_initilizer_list.size()) > vector_size)
   29317             :                )
   29318             :             {
   29319           0 :                set_error(make_error(
   29320             :                   parser_error::e_syntax,
   29321           0 :                   current_token(),
   29322             :                   "ERR170 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
   29323             :                   exprtk_error_location));
   29324             : 
   29325           0 :                return error_node();
   29326             :             }
   29327             :          }
   29328             : 
   29329       24277 :          expression_node_ptr result = error_node();
   29330             : 
   29331       24277 :          if (
   29332       24277 :               (vec_initilizer_list.size() == 1) &&
   29333             :               single_value_initialiser
   29334             :             )
   29335             :          {
   29336        7078 :             if (details::is_constant_node(vec_initilizer_list[0]))
   29337             :             {
   29338             :               // vector_init_zero_value_node   var v[10] := [0]
   29339        6988 :                if (T(0) == vec_initilizer_list[0]->value())
   29340             :                {
   29341         839 :                   result = node_allocator_
   29342        2517 :                               .allocate<details::vector_init_zero_value_node<T> >(
   29343         839 :                                  (*vec_holder)[0],
   29344             :                                  vec_size,
   29345             :                                  vec_initilizer_list);
   29346             :                }
   29347             :                else
   29348             :                {
   29349             :                   // vector_init_single_constvalue_node   var v[10] := [123]
   29350        6149 :                   result = node_allocator_
   29351       18447 :                               .allocate<details::vector_init_single_constvalue_node<T> >(
   29352        6149 :                                  (*vec_holder)[0],
   29353             :                                  vec_size,
   29354             :                                  vec_initilizer_list);
   29355             :                }
   29356             :             }
   29357             :             else
   29358             :             {
   29359             :                // vector_init_single_value_node   var v[10] := [123 + (x / y)]
   29360          90 :                result = node_allocator_
   29361         270 :                            .allocate<details::vector_init_single_value_node<T> >(
   29362          90 :                               (*vec_holder)[0],
   29363             :                               vec_size,
   29364             :                               vec_initilizer_list);
   29365             :             }
   29366             :          }
   29367       17199 :          else if (
   29368       17199 :                    (vec_initilizer_list.size() == 2) &&
   29369             :                    range_value_initialiser
   29370             :                  )
   29371             :          {
   29372         215 :             bool base_const = details::is_constant_node(vec_initilizer_list[0]);
   29373         215 :             bool inc_const  = details::is_constant_node(vec_initilizer_list[1]);
   29374             : 
   29375         215 :             if (base_const && inc_const)
   29376             :             {
   29377             :                // vector_init_single_value_node   var v[10] := [1 : 3.5]
   29378         135 :                result = node_allocator_
   29379         405 :                            .allocate<details::vector_init_iota_constconst_node<T> >(
   29380         135 :                               (*vec_holder)[0],
   29381             :                               vec_size,
   29382             :                               vec_initilizer_list);
   29383             :             }
   29384          80 :             else if (base_const && !inc_const)
   29385             :             {
   29386             :                // vector_init_single_value_node   var v[10] := [1 : x + y]
   29387          40 :                result = node_allocator_
   29388         120 :                            .allocate<details::vector_init_iota_constnconst_node<T> >(
   29389          40 :                               (*vec_holder)[0],
   29390             :                               vec_size,
   29391             :                               vec_initilizer_list);
   29392             :             }
   29393          40 :             else if (!base_const && inc_const)
   29394             :             {
   29395             :                // vector_init_single_value_node   var v[10] := [x + y : 3]
   29396          20 :                result = node_allocator_
   29397          60 :                            .allocate<details::vector_init_iota_nconstconst_node<T> >(
   29398          20 :                               (*vec_holder)[0],
   29399             :                               vec_size,
   29400             :                               vec_initilizer_list);
   29401             :             }
   29402          20 :             else if (!base_const && !inc_const)
   29403             :             {
   29404             :                // vector_init_single_value_node   var v[10] := [x + y :  z / w]
   29405          20 :                result = node_allocator_
   29406          60 :                            .allocate<details::vector_init_iota_nconstnconst_node<T> >(
   29407          20 :                               (*vec_holder)[0],
   29408             :                               vec_size,
   29409             :                               vec_initilizer_list);
   29410             :             }
   29411             :          }
   29412       16984 :          else if (null_initialisation)
   29413          80 :             result = expression_generator_(T(0.0));
   29414       16904 :          else if (vec_to_vec_initialiser)
   29415             :          {
   29416         290 :             expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
   29417             : 
   29418         870 :             result = expression_generator_(
   29419         290 :                         details::e_assign,
   29420             :                         vec_node,
   29421         290 :                         vec_initilizer_list[0]);
   29422             :          }
   29423             :          else
   29424             :          {
   29425       16614 :             result = node_allocator_
   29426       49842 :                         .allocate<details::vector_initialisation_node<T> >(
   29427       16614 :                            (*vec_holder)[0],
   29428             :                            vec_size,
   29429             :                            vec_initilizer_list,
   29430             :                            single_value_initialiser);
   29431             :          }
   29432             : 
   29433       24277 :          svd.delete_ptr = false;
   29434             : 
   29435       24277 :          if (result && result->valid())
   29436             :          {
   29437       24277 :             return result;
   29438             :          }
   29439             : 
   29440           0 :          details::free_node(node_allocator_,result);
   29441             : 
   29442           0 :          set_error(make_error(
   29443             :             parser_error::e_synthesis,
   29444           0 :             current_token(),
   29445             :             "ERR171 - Failed to generate initialisation node for vector: " + vec_name,
   29446             :             exprtk_error_location));
   29447             : 
   29448           0 :          return error_node();
   29449       24277 :       }
   29450             : 
   29451             :       #ifndef exprtk_disable_string_capabilities
   29452        9820 :       inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
   29453             :       {
   29454        9820 :          stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
   29455             : 
   29456        9820 :          scope_element& se = sem_.get_element(str_name);
   29457             : 
   29458        9820 :          if (se.name == str_name)
   29459             :          {
   29460         120 :             if (se.active)
   29461             :             {
   29462           0 :                set_error(make_error(
   29463             :                   parser_error::e_syntax,
   29464           0 :                   current_token(),
   29465             :                   "ERR172 - Illegal redefinition of local variable: '" + str_name + "'",
   29466             :                   exprtk_error_location));
   29467             : 
   29468           0 :                free_node(node_allocator_,initialisation_expression);
   29469             : 
   29470           0 :                return error_node();
   29471             :             }
   29472         120 :             else if (scope_element::e_string == se.type)
   29473             :             {
   29474          80 :                str_node  = se.str_node;
   29475          80 :                se.active = true;
   29476          80 :                se.depth  = state_.scope_depth;
   29477          80 :                se.ref_count++;
   29478             :             }
   29479             :          }
   29480             : 
   29481        9820 :          if (0 == str_node)
   29482             :          {
   29483        9740 :             scope_element nse;
   29484        9740 :             nse.name      = str_name;
   29485        9740 :             nse.active    = true;
   29486        9740 :             nse.ref_count = 1;
   29487        9740 :             nse.type      = scope_element::e_string;
   29488        9740 :             nse.depth     = state_.scope_depth;
   29489        9740 :             nse.data      = new std::string;
   29490        9740 :             nse.str_node  = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data));
   29491             : 
   29492        9740 :             if (!sem_.add_element(nse))
   29493             :             {
   29494           0 :                set_error(make_error(
   29495             :                   parser_error::e_syntax,
   29496           0 :                   current_token(),
   29497             :                   "ERR173 - Failed to add new local string variable '" + str_name + "' to SEM",
   29498             :                   exprtk_error_location));
   29499             : 
   29500           0 :                free_node(node_allocator_,initialisation_expression);
   29501             : 
   29502           0 :                sem_.free_element(nse);
   29503             : 
   29504           0 :                return error_node();
   29505             :             }
   29506             : 
   29507        9740 :             str_node = nse.str_node;
   29508             : 
   29509             :             exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str()));
   29510        9740 :          }
   29511             : 
   29512        9820 :          lodge_symbol(str_name, e_st_local_string);
   29513             : 
   29514       19640 :          state_.activate_side_effect("parse_define_string_statement()");
   29515             : 
   29516        9820 :          expression_node_ptr branch[2] = {0};
   29517             : 
   29518        9820 :          branch[0] = str_node;
   29519        9820 :          branch[1] = initialisation_expression;
   29520             : 
   29521        9820 :          return expression_generator_(details::e_assign,branch);
   29522             :       }
   29523             :       #else
   29524             :       inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
   29525             :       {
   29526             :          return error_node();
   29527             :       }
   29528             :       #endif
   29529             : 
   29530       82250 :       inline bool local_variable_is_shadowed(const std::string& symbol)
   29531             :       {
   29532       82250 :          const scope_element& se = sem_.get_element(symbol);
   29533       82250 :          return (se.name == symbol) && se.active;
   29534             :       }
   29535             : 
   29536       79605 :       inline expression_node_ptr parse_define_var_statement()
   29537             :       {
   29538       79605 :          if (settings_.vardef_disabled())
   29539             :          {
   29540           0 :             set_error(make_error(
   29541             :                parser_error::e_syntax,
   29542           0 :                current_token(),
   29543             :                "ERR174 - Illegal variable definition",
   29544             :                exprtk_error_location));
   29545             : 
   29546           0 :             return error_node();
   29547             :          }
   29548      159210 :          else if (!details::imatch(current_token().value,"var"))
   29549             :          {
   29550           0 :             return error_node();
   29551             :          }
   29552             :          else
   29553       79605 :             next_token();
   29554             : 
   29555       79605 :          const std::string var_name = current_token().value;
   29556             : 
   29557       79605 :          expression_node_ptr initialisation_expression = error_node();
   29558             : 
   29559       79605 :          if (!token_is(token_t::e_symbol))
   29560             :          {
   29561           0 :             set_error(make_error(
   29562             :                parser_error::e_syntax,
   29563           0 :                current_token(),
   29564             :                "ERR175 - Expected a symbol for variable definition",
   29565             :                exprtk_error_location));
   29566             : 
   29567           0 :             return error_node();
   29568             :          }
   29569       79605 :          else if (details::is_reserved_symbol(var_name))
   29570             :          {
   29571           0 :             set_error(make_error(
   29572             :                parser_error::e_syntax,
   29573           0 :                current_token(),
   29574             :                "ERR176 - Illegal redefinition of reserved keyword: '" + var_name + "'",
   29575             :                exprtk_error_location));
   29576             : 
   29577           0 :             return error_node();
   29578             :          }
   29579       79605 :          else if (symtab_store_.symbol_exists(var_name))
   29580             :          {
   29581           0 :             set_error(make_error(
   29582             :                parser_error::e_syntax,
   29583           0 :                current_token(),
   29584             :                "ERR177 - Illegal redefinition of variable '" + var_name + "'",
   29585             :                exprtk_error_location));
   29586             : 
   29587           0 :             return error_node();
   29588             :          }
   29589       79605 :          else if (local_variable_is_shadowed(var_name))
   29590             :          {
   29591           0 :             set_error(make_error(
   29592             :                parser_error::e_syntax,
   29593           0 :                current_token(),
   29594             :                "ERR178 - Illegal redefinition of local variable: '" + var_name + "'",
   29595             :                exprtk_error_location));
   29596             : 
   29597           0 :             return error_node();
   29598             :          }
   29599       79605 :          else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
   29600             :          {
   29601       24277 :             return parse_define_vector_statement(var_name);
   29602             :          }
   29603       55328 :          else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
   29604             :          {
   29605        2140 :             return parse_uninitialised_var_statement(var_name);
   29606             :          }
   29607       53188 :          else if (token_is(token_t::e_assign))
   29608             :          {
   29609       53115 :             if (0 == (initialisation_expression = parse_expression()))
   29610             :             {
   29611           0 :                set_error(make_error(
   29612             :                   parser_error::e_syntax,
   29613           0 :                   current_token(),
   29614             :                   "ERR179 - Failed to parse initialisation expression",
   29615             :                   exprtk_error_location));
   29616             : 
   29617           0 :                return error_node();
   29618             :             }
   29619             :          }
   29620             : 
   29621       53188 :          if (
   29622       53188 :               !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
   29623      105246 :               !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
   29624      105246 :               !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
   29625             :             )
   29626             :          {
   29627       52058 :             if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
   29628             :             {
   29629           0 :                set_error(make_error(
   29630             :                   parser_error::e_syntax,
   29631           0 :                   current_token(),
   29632             :                   "ERR180 - Expected ';' after variable definition",
   29633             :                   exprtk_error_location));
   29634             : 
   29635           0 :                free_node(node_allocator_,initialisation_expression);
   29636             : 
   29637           0 :                return error_node();
   29638             :             }
   29639             :          }
   29640             : 
   29641       53188 :          if (
   29642      106303 :               (0 != initialisation_expression) &&
   29643       53115 :               details::is_generally_string_node(initialisation_expression)
   29644             :             )
   29645             :          {
   29646        9820 :             return parse_define_string_statement(var_name,initialisation_expression);
   29647             :          }
   29648             : 
   29649       43368 :          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
   29650             : 
   29651       43368 :          scope_element& se = sem_.get_element(var_name);
   29652             : 
   29653       43368 :          if (se.name == var_name)
   29654             :          {
   29655        1041 :             if (se.active)
   29656             :             {
   29657           0 :                set_error(make_error(
   29658             :                   parser_error::e_syntax,
   29659           0 :                   current_token(),
   29660             :                   "ERR181 - Illegal redefinition of local variable: '" + var_name + "'",
   29661             :                   exprtk_error_location));
   29662             : 
   29663           0 :                free_node(node_allocator_, initialisation_expression);
   29664             : 
   29665           0 :                return error_node();
   29666             :             }
   29667        1041 :             else if (scope_element::e_variable == se.type)
   29668             :             {
   29669         561 :                var_node  = se.var_node;
   29670         561 :                se.active = true;
   29671         561 :                se.depth  = state_.scope_depth;
   29672         561 :                se.ref_count++;
   29673             :             }
   29674             :          }
   29675             : 
   29676       43368 :          if (0 == var_node)
   29677             :          {
   29678       42807 :             scope_element nse;
   29679       42807 :             nse.name      = var_name;
   29680       42807 :             nse.active    = true;
   29681       42807 :             nse.ref_count = 1;
   29682       42807 :             nse.type      = scope_element::e_variable;
   29683       42807 :             nse.depth     = state_.scope_depth;
   29684       42807 :             nse.data      = new T(T(0));
   29685       42807 :             nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
   29686             : 
   29687       42807 :             if (!sem_.add_element(nse))
   29688             :             {
   29689           0 :                set_error(make_error(
   29690             :                   parser_error::e_syntax,
   29691           0 :                   current_token(),
   29692             :                   "ERR182 - Failed to add new local variable '" + var_name + "' to SEM",
   29693             :                   exprtk_error_location));
   29694             : 
   29695           0 :                free_node(node_allocator_, initialisation_expression);
   29696             : 
   29697           0 :                sem_.free_element(nse);
   29698             : 
   29699           0 :                return error_node();
   29700             :             }
   29701             : 
   29702       42807 :             var_node = nse.var_node;
   29703             : 
   29704             :             exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str()));
   29705       42807 :          }
   29706             : 
   29707       86736 :          state_.activate_side_effect("parse_define_var_statement()");
   29708             : 
   29709       43368 :          lodge_symbol(var_name, e_st_local_variable);
   29710             : 
   29711       43368 :          expression_node_ptr branch[2] = {0};
   29712             : 
   29713       43368 :          branch[0] = var_node;
   29714       43368 :          branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
   29715             : 
   29716       43368 :          return expression_generator_(details::e_assign,branch);
   29717       79605 :       }
   29718             : 
   29719        2645 :       inline expression_node_ptr parse_define_constvar_statement()
   29720             :       {
   29721        2645 :          if (settings_.vardef_disabled())
   29722             :          {
   29723           0 :             set_error(make_error(
   29724             :                parser_error::e_syntax,
   29725           0 :                current_token(),
   29726             :                "ERR183 - Illegal const variable definition",
   29727             :                exprtk_error_location));
   29728             : 
   29729           0 :             return error_node();
   29730             :          }
   29731        7935 :          else if (!token_is("const"))
   29732             :          {
   29733           0 :             set_error(make_error(
   29734             :                parser_error::e_syntax,
   29735           0 :                current_token(),
   29736             :                "ERR184 - Expected 'const' keyword for const-variable definition",
   29737             :                exprtk_error_location));
   29738             : 
   29739           0 :             return error_node();
   29740             :          }
   29741        7935 :          else if (!token_is("var"))
   29742             :          {
   29743           0 :             set_error(make_error(
   29744             :                parser_error::e_syntax,
   29745           0 :                current_token(),
   29746             :                "ERR185 - Expected 'var' keyword for const-variable definition",
   29747             :                exprtk_error_location));
   29748             : 
   29749           0 :             return error_node();
   29750             :          }
   29751             : 
   29752        2645 :          const std::string var_name = current_token().value;
   29753             : 
   29754        2645 :          expression_node_ptr initialisation_expression = error_node();
   29755             : 
   29756        2645 :          if (!token_is(token_t::e_symbol))
   29757             :          {
   29758           0 :             set_error(make_error(
   29759             :                parser_error::e_syntax,
   29760           0 :                current_token(),
   29761             :                "ERR186 - Expected a symbol for const-variable definition",
   29762             :                exprtk_error_location));
   29763             : 
   29764           0 :             return error_node();
   29765             :          }
   29766        2645 :          else if (details::is_reserved_symbol(var_name))
   29767             :          {
   29768           0 :             set_error(make_error(
   29769             :                parser_error::e_syntax,
   29770           0 :                current_token(),
   29771             :                "ERR187 - Illegal redefinition of reserved keyword: '" + var_name + "'",
   29772             :                exprtk_error_location));
   29773             : 
   29774           0 :             return error_node();
   29775             :          }
   29776        2645 :          else if (symtab_store_.symbol_exists(var_name))
   29777             :          {
   29778           0 :             set_error(make_error(
   29779             :                parser_error::e_syntax,
   29780           0 :                current_token(),
   29781             :                "ERR188 - Illegal redefinition of variable '" + var_name + "'",
   29782             :                exprtk_error_location));
   29783             : 
   29784           0 :             return error_node();
   29785             :          }
   29786        2645 :          else if (local_variable_is_shadowed(var_name))
   29787             :          {
   29788           0 :             set_error(make_error(
   29789             :                parser_error::e_syntax,
   29790           0 :                current_token(),
   29791             :                "ERR189 - Illegal redefinition of local variable: '" + var_name + "'",
   29792             :                exprtk_error_location));
   29793             : 
   29794           0 :             return error_node();
   29795             :          }
   29796        2645 :          else if (token_is(token_t::e_assign))
   29797             :          {
   29798        2645 :             if (0 == (initialisation_expression = parse_expression()))
   29799             :             {
   29800           0 :                set_error(make_error(
   29801             :                   parser_error::e_syntax,
   29802           0 :                   current_token(),
   29803             :                   "ERR190 - Failed to parse initialisation expression for const-variable: '" + var_name + "'",
   29804             :                   exprtk_error_location));
   29805             : 
   29806           0 :                return error_node();
   29807             :             }
   29808        2645 :             else if (!details::is_literal_node(initialisation_expression))
   29809             :             {
   29810           0 :                set_error(make_error(
   29811             :                   parser_error::e_syntax,
   29812           0 :                   current_token(),
   29813             :                   "ERR191 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal",
   29814             :                   exprtk_error_location));
   29815             : 
   29816           0 :                free_node(node_allocator_, initialisation_expression);
   29817             : 
   29818           0 :                return error_node();
   29819             :             }
   29820             :          }
   29821             : 
   29822        2645 :          const T init_value = initialisation_expression->value();
   29823             : 
   29824        2645 :          free_node(node_allocator_, initialisation_expression);
   29825             : 
   29826        2645 :          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
   29827             : 
   29828        2645 :          scope_element& se = sem_.get_element(var_name);
   29829             : 
   29830        2645 :          if (se.name == var_name)
   29831             :          {
   29832          10 :             if (se.active)
   29833             :             {
   29834           0 :                set_error(make_error(
   29835             :                   parser_error::e_syntax,
   29836           0 :                   current_token(),
   29837             :                   "ERR192 - Illegal redefinition of local variable: '" + var_name + "'",
   29838             :                   exprtk_error_location));
   29839             : 
   29840           0 :                return error_node();
   29841             :             }
   29842          10 :             else if (scope_element::e_literal == se.type)
   29843             :             {
   29844          10 :                var_node  = se.var_node;
   29845          10 :                se.active = true;
   29846          10 :                se.depth  = state_.scope_depth;
   29847          10 :                se.ref_count++;
   29848             :             }
   29849             :          }
   29850             : 
   29851        2645 :          if (0 == var_node)
   29852             :          {
   29853        2635 :             scope_element nse;
   29854        2635 :             nse.name      = var_name;
   29855        2635 :             nse.active    = true;
   29856        2635 :             nse.ref_count = 1;
   29857        2635 :             nse.type      = scope_element::e_literal;
   29858        2635 :             nse.depth     = state_.scope_depth;
   29859        2635 :             nse.data      = 0;
   29860        2635 :             nse.var_node  = node_allocator_.allocate<literal_node_t>(init_value);
   29861             : 
   29862        2635 :             if (!sem_.add_element(nse))
   29863             :             {
   29864           0 :                set_error(make_error(
   29865             :                   parser_error::e_syntax,
   29866           0 :                   current_token(),
   29867             :                   "ERR193 - Failed to add new local const-variable '" + var_name + "' to SEM",
   29868             :                   exprtk_error_location));
   29869             : 
   29870           0 :                sem_.free_element(nse);
   29871             : 
   29872           0 :                return error_node();
   29873             :             }
   29874             : 
   29875        2635 :             var_node = nse.var_node;
   29876             : 
   29877             :             exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str()));
   29878        2635 :          }
   29879             : 
   29880        5290 :          state_.activate_side_effect("parse_define_constvar_statement()");
   29881             : 
   29882        2645 :          lodge_symbol(var_name, e_st_local_variable);
   29883             : 
   29884        2645 :          return expression_generator_(var_node->value());
   29885        2645 :       }
   29886             : 
   29887        2140 :       inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
   29888             :       {
   29889        2140 :          if (
   29890        4280 :               !token_is(token_t::e_lcrlbracket) ||
   29891        4280 :               !token_is(token_t::e_rcrlbracket)
   29892             :             )
   29893             :          {
   29894           0 :             set_error(make_error(
   29895             :                parser_error::e_syntax,
   29896           0 :                current_token(),
   29897             :                "ERR194 - Expected a '{}' for uninitialised var definition",
   29898             :                exprtk_error_location));
   29899             : 
   29900           0 :             return error_node();
   29901             :          }
   29902        2140 :          else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
   29903             :          {
   29904           0 :             set_error(make_error(
   29905             :                parser_error::e_syntax,
   29906           0 :                current_token(),
   29907             :                "ERR195 - Expected ';' after uninitialised variable definition",
   29908             :                exprtk_error_location));
   29909             : 
   29910           0 :             return error_node();
   29911             :          }
   29912             : 
   29913        2140 :          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
   29914             : 
   29915        2140 :          scope_element& se = sem_.get_element(var_name);
   29916             : 
   29917        2140 :          if (se.name == var_name)
   29918             :          {
   29919           0 :             if (se.active)
   29920             :             {
   29921           0 :                set_error(make_error(
   29922             :                   parser_error::e_syntax,
   29923           0 :                   current_token(),
   29924             :                   "ERR196 - Illegal redefinition of local variable: '" + var_name + "'",
   29925             :                   exprtk_error_location));
   29926             : 
   29927           0 :                return error_node();
   29928             :             }
   29929           0 :             else if (scope_element::e_variable == se.type)
   29930             :             {
   29931           0 :                var_node  = se.var_node;
   29932           0 :                se.active = true;
   29933           0 :                se.ref_count++;
   29934             :             }
   29935             :          }
   29936             : 
   29937        2140 :          if (0 == var_node)
   29938             :          {
   29939        2140 :             scope_element nse;
   29940        2140 :             nse.name      = var_name;
   29941        2140 :             nse.active    = true;
   29942        2140 :             nse.ref_count = 1;
   29943        2140 :             nse.type      = scope_element::e_variable;
   29944        2140 :             nse.depth     = state_.scope_depth;
   29945        2140 :             nse.ip_index  = sem_.next_ip_index();
   29946        2140 :             nse.data      = new T(T(0));
   29947        2140 :             nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
   29948             : 
   29949        2140 :             if (!sem_.add_element(nse))
   29950             :             {
   29951           0 :                set_error(make_error(
   29952             :                   parser_error::e_syntax,
   29953           0 :                   current_token(),
   29954             :                   "ERR197 - Failed to add new local variable '" + var_name + "' to SEM",
   29955             :                   exprtk_error_location));
   29956             : 
   29957           0 :                sem_.free_element(nse);
   29958             : 
   29959           0 :                return error_node();
   29960             :             }
   29961             : 
   29962             :             exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
   29963             :                           nse.name.c_str()));
   29964        2140 :          }
   29965             : 
   29966        2140 :          lodge_symbol(var_name, e_st_local_variable);
   29967             : 
   29968        4280 :          state_.activate_side_effect("parse_uninitialised_var_statement()");
   29969             : 
   29970        2140 :          return expression_generator_(T(0));
   29971             :       }
   29972             : 
   29973         560 :       inline expression_node_ptr parse_swap_statement()
   29974             :       {
   29975        1120 :          if (!details::imatch(current_token().value,"swap"))
   29976             :          {
   29977           0 :             return error_node();
   29978             :          }
   29979             :          else
   29980         560 :             next_token();
   29981             : 
   29982         560 :          if (!token_is(token_t::e_lbracket))
   29983             :          {
   29984           0 :             set_error(make_error(
   29985             :                parser_error::e_syntax,
   29986           0 :                current_token(),
   29987             :                "ERR198 - Expected '(' at start of swap statement",
   29988             :                exprtk_error_location));
   29989             : 
   29990           0 :             return error_node();
   29991             :          }
   29992             : 
   29993         560 :          expression_node_ptr variable0 = error_node();
   29994         560 :          expression_node_ptr variable1 = error_node();
   29995             : 
   29996         560 :          bool variable0_generated = false;
   29997         560 :          bool variable1_generated = false;
   29998             : 
   29999         560 :          const std::string var0_name = current_token().value;
   30000             : 
   30001         560 :          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
   30002             :          {
   30003           0 :             set_error(make_error(
   30004             :                parser_error::e_syntax,
   30005           0 :                current_token(),
   30006             :                "ERR199 - Expected a symbol for variable or vector element definition",
   30007             :                exprtk_error_location));
   30008             : 
   30009           0 :             return error_node();
   30010             :          }
   30011         560 :          else if (peek_token_is(token_t::e_lsqrbracket))
   30012             :          {
   30013         360 :             if (0 == (variable0 = parse_vector()))
   30014             :             {
   30015           0 :                set_error(make_error(
   30016             :                   parser_error::e_syntax,
   30017           0 :                   current_token(),
   30018             :                   "ERR200 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
   30019             :                   exprtk_error_location));
   30020             : 
   30021           0 :                return error_node();
   30022             :             }
   30023             : 
   30024         360 :             variable0_generated = true;
   30025             :          }
   30026             :          else
   30027             :          {
   30028         200 :             if (symtab_store_.is_variable(var0_name))
   30029             :             {
   30030           0 :                variable0 = symtab_store_.get_variable(var0_name);
   30031             :             }
   30032             : 
   30033         200 :             const scope_element& se = sem_.get_element(var0_name);
   30034             : 
   30035         200 :             if (
   30036         200 :                  (se.active)            &&
   30037         400 :                  (se.name == var0_name) &&
   30038         200 :                  (scope_element::e_variable == se.type)
   30039             :                )
   30040             :             {
   30041         200 :                variable0 = se.var_node;
   30042             :             }
   30043             : 
   30044         200 :             lodge_symbol(var0_name, e_st_variable);
   30045             : 
   30046         200 :             if (0 == variable0)
   30047             :             {
   30048           0 :                set_error(make_error(
   30049             :                   parser_error::e_syntax,
   30050           0 :                   current_token(),
   30051             :                   "ERR201 - First parameter to swap is an invalid variable: '" + var0_name + "'",
   30052             :                   exprtk_error_location));
   30053             : 
   30054           0 :                return error_node();
   30055             :             }
   30056             :             else
   30057         200 :                next_token();
   30058             :          }
   30059             : 
   30060         560 :          if (!token_is(token_t::e_comma))
   30061             :          {
   30062           0 :             set_error(make_error(
   30063             :                parser_error::e_syntax,
   30064           0 :                current_token(),
   30065             :                "ERR202 - Expected ',' between parameters to swap",
   30066             :                exprtk_error_location));
   30067             : 
   30068           0 :             if (variable0_generated)
   30069             :             {
   30070           0 :                free_node(node_allocator_,variable0);
   30071             :             }
   30072             : 
   30073           0 :             return error_node();
   30074             :          }
   30075             : 
   30076         560 :          const std::string var1_name = current_token().value;
   30077             : 
   30078         560 :          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
   30079             :          {
   30080           0 :             set_error(make_error(
   30081             :                parser_error::e_syntax,
   30082           0 :                current_token(),
   30083             :                "ERR203 - Expected a symbol for variable or vector element definition",
   30084             :                exprtk_error_location));
   30085             : 
   30086           0 :             if (variable0_generated)
   30087             :             {
   30088           0 :                free_node(node_allocator_,variable0);
   30089             :             }
   30090             : 
   30091           0 :             return error_node();
   30092             :          }
   30093         560 :          else if (peek_token_is(token_t::e_lsqrbracket))
   30094             :          {
   30095         360 :             if (0 == (variable1 = parse_vector()))
   30096             :             {
   30097           0 :                set_error(make_error(
   30098             :                   parser_error::e_syntax,
   30099           0 :                   current_token(),
   30100             :                   "ERR204 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
   30101             :                   exprtk_error_location));
   30102             : 
   30103           0 :                if (variable0_generated)
   30104             :                {
   30105           0 :                   free_node(node_allocator_,variable0);
   30106             :                }
   30107             : 
   30108           0 :                return error_node();
   30109             :             }
   30110             : 
   30111         360 :             variable1_generated = true;
   30112             :          }
   30113             :          else
   30114             :          {
   30115         200 :             if (symtab_store_.is_variable(var1_name))
   30116             :             {
   30117           0 :                variable1 = symtab_store_.get_variable(var1_name);
   30118             :             }
   30119             : 
   30120         200 :             const scope_element& se = sem_.get_element(var1_name);
   30121             : 
   30122         200 :             if (
   30123         200 :                  (se.active) &&
   30124         400 :                  (se.name == var1_name) &&
   30125         200 :                  (scope_element::e_variable == se.type)
   30126             :                )
   30127             :             {
   30128         200 :                variable1 = se.var_node;
   30129             :             }
   30130             : 
   30131         200 :             lodge_symbol(var1_name, e_st_variable);
   30132             : 
   30133         200 :             if (0 == variable1)
   30134             :             {
   30135           0 :                set_error(make_error(
   30136             :                   parser_error::e_syntax,
   30137           0 :                   current_token(),
   30138             :                   "ERR205 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
   30139             :                   exprtk_error_location));
   30140             : 
   30141           0 :                if (variable0_generated)
   30142             :                {
   30143           0 :                   free_node(node_allocator_,variable0);
   30144             :                }
   30145             : 
   30146           0 :                return error_node();
   30147             :             }
   30148             :             else
   30149         200 :                next_token();
   30150             :          }
   30151             : 
   30152         560 :          if (!token_is(token_t::e_rbracket))
   30153             :          {
   30154           0 :             set_error(make_error(
   30155             :                parser_error::e_syntax,
   30156           0 :                current_token(),
   30157             :                "ERR206 - Expected ')' at end of swap statement",
   30158             :                exprtk_error_location));
   30159             : 
   30160           0 :             if (variable0_generated)
   30161             :             {
   30162           0 :                free_node(node_allocator_,variable0);
   30163             :             }
   30164             : 
   30165           0 :             if (variable1_generated)
   30166             :             {
   30167           0 :                free_node(node_allocator_,variable1);
   30168             :             }
   30169             : 
   30170           0 :             return error_node();
   30171             :          }
   30172             : 
   30173             :          typedef details::variable_node<T>* variable_node_ptr;
   30174             : 
   30175         560 :          variable_node_ptr v0 = variable_node_ptr(0);
   30176         560 :          variable_node_ptr v1 = variable_node_ptr(0);
   30177             : 
   30178         560 :          expression_node_ptr result = error_node();
   30179             : 
   30180         560 :          if (
   30181         880 :               (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
   30182         320 :               (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
   30183             :             )
   30184             :          {
   30185         240 :             result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
   30186             : 
   30187         240 :             if (variable0_generated)
   30188             :             {
   30189         120 :                free_node(node_allocator_,variable0);
   30190             :             }
   30191             : 
   30192         240 :             if (variable1_generated)
   30193             :             {
   30194         120 :                free_node(node_allocator_,variable1);
   30195             :             }
   30196             :          }
   30197             :          else
   30198             :             result = node_allocator_.allocate<details::swap_generic_node<T> >
   30199         320 :                         (variable0, variable1);
   30200             : 
   30201        1120 :          state_.activate_side_effect("parse_swap_statement()");
   30202             : 
   30203         560 :          return result;
   30204         560 :       }
   30205             : 
   30206             :       #ifndef exprtk_disable_return_statement
   30207         116 :       inline expression_node_ptr parse_return_statement()
   30208             :       {
   30209         116 :          if (state_.parsing_return_stmt)
   30210             :          {
   30211           0 :             set_error(make_error(
   30212             :                parser_error::e_syntax,
   30213           0 :                current_token(),
   30214             :                "ERR207 - Return call within a return call is not allowed",
   30215             :                exprtk_error_location));
   30216             : 
   30217           0 :             return error_node();
   30218             :          }
   30219             : 
   30220         116 :          scoped_bool_negator sbn(state_.parsing_return_stmt);
   30221             : 
   30222         116 :          std::vector<expression_node_ptr> arg_list;
   30223             : 
   30224         116 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   30225             : 
   30226         232 :          if (!details::imatch(current_token().value,"return"))
   30227             :          {
   30228           0 :             return error_node();
   30229             :          }
   30230             :          else
   30231         116 :             next_token();
   30232             : 
   30233         116 :          if (!token_is(token_t::e_lsqrbracket))
   30234             :          {
   30235           0 :             set_error(make_error(
   30236             :                parser_error::e_syntax,
   30237           0 :                current_token(),
   30238             :                "ERR208 - Expected '[' at start of return statement",
   30239             :                exprtk_error_location));
   30240             : 
   30241           0 :             return error_node();
   30242             :          }
   30243         116 :          else if (!token_is(token_t::e_rsqrbracket))
   30244             :          {
   30245          32 :             for ( ; ; )
   30246             :             {
   30247         147 :                expression_node_ptr arg = parse_expression();
   30248             : 
   30249         147 :                if (0 == arg)
   30250           0 :                   return error_node();
   30251             : 
   30252         147 :                arg_list.push_back(arg);
   30253             : 
   30254         147 :                if (token_is(token_t::e_rsqrbracket))
   30255         115 :                   break;
   30256          32 :                else if (!token_is(token_t::e_comma))
   30257             :                {
   30258           0 :                   set_error(make_error(
   30259             :                      parser_error::e_syntax,
   30260           0 :                      current_token(),
   30261             :                      "ERR209 - Expected ',' between values during call to return",
   30262             :                      exprtk_error_location));
   30263             : 
   30264           0 :                   return error_node();
   30265             :                }
   30266             :             }
   30267             :          }
   30268           1 :          else if (settings_.zero_return_disabled())
   30269             :          {
   30270           0 :             set_error(make_error(
   30271             :                parser_error::e_syntax,
   30272           0 :                current_token(),
   30273             :                "ERR210 - Zero parameter return statement not allowed",
   30274             :                exprtk_error_location));
   30275             : 
   30276           0 :             return error_node();
   30277             :          }
   30278             : 
   30279         116 :          const lexer::token prev_token = current_token();
   30280             : 
   30281         116 :          if (token_is(token_t::e_rsqrbracket))
   30282             :          {
   30283           0 :             if (!arg_list.empty())
   30284             :             {
   30285           0 :                set_error(make_error(
   30286             :                   parser_error::e_syntax,
   30287             :                   prev_token,
   30288             :                   "ERR211 - Invalid ']' found during return call",
   30289             :                   exprtk_error_location));
   30290             : 
   30291           0 :                return error_node();
   30292             :             }
   30293             :          }
   30294             : 
   30295         116 :          std::string ret_param_type_list;
   30296             : 
   30297         263 :          for (std::size_t i = 0; i < arg_list.size(); ++i)
   30298             :          {
   30299         147 :             if (0 == arg_list[i])
   30300           0 :                return error_node();
   30301         147 :             else if (is_ivector_node(arg_list[i]))
   30302           1 :                ret_param_type_list += 'V';
   30303         146 :             else if (is_generally_string_node(arg_list[i]))
   30304          16 :                ret_param_type_list += 'S';
   30305             :             else
   30306         130 :                ret_param_type_list += 'T';
   30307             :          }
   30308             : 
   30309         116 :          dec_.retparam_list_.push_back(ret_param_type_list);
   30310             : 
   30311         116 :          expression_node_ptr result = expression_generator_.return_call(arg_list);
   30312             : 
   30313         116 :          sdd.delete_ptr = (0 == result);
   30314             : 
   30315         116 :          state_.return_stmt_present = true;
   30316             : 
   30317         232 :          state_.activate_side_effect("parse_return_statement()");
   30318             : 
   30319         116 :          return result;
   30320         116 :       }
   30321             :       #else
   30322             :       inline expression_node_ptr parse_return_statement()
   30323             :       {
   30324             :          return error_node();
   30325             :       }
   30326             :       #endif
   30327             : 
   30328         108 :       inline expression_node_ptr parse_assert_statement()
   30329             :       {
   30330         108 :          assert(details::imatch(current_token().value, "assert"));
   30331             : 
   30332         108 :          if (state_.parsing_assert_stmt)
   30333             :          {
   30334           0 :             set_error(make_error(
   30335             :                parser_error::e_syntax,
   30336           0 :                current_token(),
   30337             :                "ERR212 - Assert statement within an assert statement is not allowed",
   30338             :                exprtk_error_location));
   30339             : 
   30340           0 :             return error_node();
   30341             :          }
   30342             : 
   30343         108 :          scoped_bool_negator sbn(state_.parsing_assert_stmt);
   30344             : 
   30345         108 :          next_token();
   30346             : 
   30347         108 :          std::vector<expression_node_ptr> assert_arg_list(3, error_node());
   30348         108 :          scoped_vec_delete<expression_node_t> sdd((*this), assert_arg_list);
   30349             : 
   30350         108 :          expression_node_ptr& assert_condition = assert_arg_list[0];
   30351         108 :          expression_node_ptr& assert_message   = assert_arg_list[1];
   30352         108 :          expression_node_ptr& assert_id        = assert_arg_list[2];
   30353             : 
   30354         108 :          if (!token_is(token_t::e_lbracket))
   30355             :          {
   30356           0 :             set_error(make_error(
   30357             :                parser_error::e_syntax,
   30358           0 :                current_token(),
   30359             :                "ERR213 - Expected '(' at start of assert statement",
   30360             :                exprtk_error_location));
   30361             : 
   30362           0 :             return error_node();
   30363             :          }
   30364             : 
   30365         108 :          const token_t start_token = current_token();
   30366             : 
   30367             :          // Parse the assert condition
   30368         108 :          if (0 == (assert_condition = parse_expression()))
   30369             :          {
   30370           0 :             set_error(make_error(
   30371             :                parser_error::e_syntax,
   30372           0 :                current_token(),
   30373             :                "ERR214 - Failed to parse condition for assert statement",
   30374             :                exprtk_error_location));
   30375             : 
   30376           0 :             return error_node();
   30377             :          }
   30378             : 
   30379         108 :          const token_t end_token = current_token();
   30380             : 
   30381         108 :          if (!token_is(token_t::e_rbracket))
   30382             :          {
   30383          90 :             if (!token_is(token_t::e_comma))
   30384             :             {
   30385           0 :                set_error(make_error(
   30386             :                   parser_error::e_syntax,
   30387           0 :                   current_token(),
   30388             :                   "ERR215 - Expected ',' between condition and message for assert statement",
   30389             :                   exprtk_error_location));
   30390             : 
   30391           0 :                return error_node();
   30392             :             }
   30393             :             // Parse the assert message
   30394          90 :             else if (
   30395         180 :                       (0 == (assert_message = parse_expression())) ||
   30396          90 :                       !details::is_generally_string_node(assert_message)
   30397             :                     )
   30398             :             {
   30399           0 :                set_error(make_error(
   30400             :                   parser_error::e_syntax,
   30401           0 :                   current_token(),
   30402             :                   "ERR216 - " +
   30403           0 :                   (assert_message ?
   30404             :                   std::string("Expected string for assert message") :
   30405             :                   std::string("Failed to parse message for assert statement")),
   30406             :                   exprtk_error_location));
   30407             : 
   30408           0 :                return error_node();
   30409             :             }
   30410          90 :             else if (!token_is(token_t::e_rbracket))
   30411             :             {
   30412          36 :                if (!token_is(token_t::e_comma))
   30413             :                {
   30414           0 :                   set_error(make_error(
   30415             :                      parser_error::e_syntax,
   30416           0 :                      current_token(),
   30417             :                      "ERR217 - Expected ',' between message and ID for assert statement",
   30418             :                      exprtk_error_location));
   30419             : 
   30420           0 :                   return error_node();
   30421             :                }
   30422             :                // Parse assert ID
   30423          36 :                else if (
   30424          72 :                          (0 == (assert_id = parse_expression())) ||
   30425          36 :                          !details::is_const_string_node(assert_id)
   30426             :                        )
   30427             :                {
   30428           0 :                   set_error(make_error(
   30429             :                      parser_error::e_syntax,
   30430           0 :                      current_token(),
   30431             :                      "ERR218 - " +
   30432           0 :                      (assert_id ?
   30433             :                      std::string("Expected literal string for assert ID") :
   30434             :                      std::string("Failed to parse string for assert ID")),
   30435             :                      exprtk_error_location));
   30436             : 
   30437           0 :                   return error_node();
   30438             :                }
   30439          36 :                else if (!token_is(token_t::e_rbracket))
   30440             :                {
   30441           0 :                   set_error(make_error(
   30442             :                      parser_error::e_syntax,
   30443           0 :                      current_token(),
   30444             :                      "ERR219 - Expected ')' at start of assert statement",
   30445             :                      exprtk_error_location));
   30446             : 
   30447           0 :                   return error_node();
   30448             :                }
   30449             :             }
   30450             :          }
   30451             : 
   30452         108 :          exprtk::assert_check::assert_context context;
   30453         108 :          context.condition = lexer().substr(start_token.position, end_token.position);
   30454         108 :          context.offet     = start_token.position;
   30455             : 
   30456         108 :          if (0 == assert_check_)
   30457             :          {
   30458             :             exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n",
   30459             :                           context.condition.c_str()));
   30460             : 
   30461          24 :             return new details::null_node<T>();
   30462             :          }
   30463             : 
   30464             :          #ifndef exprtk_disable_string_capabilities
   30465          84 :          if (assert_message && details::is_const_string_node(assert_message))
   30466             :          {
   30467          70 :             context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str();
   30468             :          }
   30469             : 
   30470          84 :          if (assert_id && details::is_const_string_node(assert_id))
   30471             :          {
   30472          28 :             context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str();
   30473             : 
   30474          28 :             if (assert_ids_.end() != assert_ids_.find(context.id))
   30475             :             {
   30476           0 :                set_error(make_error(
   30477             :                   parser_error::e_syntax,
   30478           0 :                   current_token(),
   30479             :                   "ERR220 - Duplicate assert ID: " + context.id,
   30480             :                   exprtk_error_location));
   30481             : 
   30482           0 :                return error_node();
   30483             :             }
   30484             : 
   30485          28 :             assert_ids_.insert(context.id);
   30486          28 :             free_node(node_allocator_, assert_id);
   30487             :          }
   30488             :          #endif
   30489             : 
   30490             :          expression_node_ptr result_node =
   30491          84 :             expression_generator_.assert_call(
   30492             :                assert_condition,
   30493             :                assert_message,
   30494             :                context);
   30495             : 
   30496             :          exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str()      ));
   30497             :          exprtk_debug(("parse_assert_statement() - assert message:   [%s]\n", context.message  .c_str()      ));
   30498             :          exprtk_debug(("parse_assert_statement() - assert id:        [%s]\n", context.id       .c_str()      ));
   30499             :          exprtk_debug(("parse_assert_statement() - assert offset:    [%d]\n", static_cast<int>(context.offet)));
   30500             : 
   30501          84 :          if (0 == result_node)
   30502             :          {
   30503           0 :             set_error(make_error(
   30504             :                parser_error::e_syntax,
   30505           0 :                current_token(),
   30506             :                "ERR221 - Failed to synthesize assert",
   30507             :                exprtk_error_location));
   30508             : 
   30509           0 :             return error_node();
   30510             :          }
   30511             : 
   30512          84 :          sdd.delete_ptr = false;
   30513          84 :          return result_node;
   30514         108 :       }
   30515             : 
   30516     1859554 :       inline bool post_variable_process(const std::string& symbol)
   30517             :       {
   30518     1859554 :          if (
   30519     3718684 :               peek_token_is(token_t::e_lbracket   ) ||
   30520     3718684 :               peek_token_is(token_t::e_lcrlbracket) ||
   30521     3718684 :               peek_token_is(token_t::e_lsqrbracket)
   30522             :             )
   30523             :          {
   30524         426 :             if (!settings_.commutative_check_enabled())
   30525             :             {
   30526           0 :                set_error(make_error(
   30527             :                   parser_error::e_syntax,
   30528           0 :                   current_token(),
   30529             :                   "ERR222 - Invalid sequence of variable '" + symbol + "' and bracket",
   30530             :                   exprtk_error_location));
   30531             : 
   30532           0 :                return false;
   30533             :             }
   30534             : 
   30535         426 :             lexer().insert_front(token_t::e_mul);
   30536             :          }
   30537             : 
   30538     1859554 :          return true;
   30539             :       }
   30540             : 
   30541     1724379 :       inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
   30542             :       {
   30543     1724379 :          bool implied_mul = false;
   30544             : 
   30545     1724379 :          if (details::is_generally_string_node(branch))
   30546        9869 :             return true;
   30547             : 
   30548     1714510 :          const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
   30549             : 
   30550     1714510 :          switch (token)
   30551             :          {
   30552        2145 :             case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   , hold) ||
   30553        3810 :                                                         token_is(token_t::e_lcrlbracket, hold) ||
   30554        1665 :                                                         token_is(token_t::e_lsqrbracket, hold) ;
   30555        2145 :                                           break;
   30556             : 
   30557     1706280 :             case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   , hold) ||
   30558     3412080 :                                                         token_is(token_t::e_lcrlbracket, hold) ||
   30559     1705800 :                                                         token_is(token_t::e_lsqrbracket, hold) ;
   30560     1706280 :                                           break;
   30561             : 
   30562        6085 :             case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   , hold) ||
   30563       12170 :                                                         token_is(token_t::e_lcrlbracket, hold) ||
   30564        6085 :                                                         token_is(token_t::e_lsqrbracket, hold) ;
   30565        6085 :                                           break;
   30566             : 
   30567           0 :             default                     : return true;
   30568             :          }
   30569             : 
   30570     1714510 :          if (implied_mul)
   30571             :          {
   30572        2100 :             if (!settings_.commutative_check_enabled())
   30573             :             {
   30574           0 :                set_error(make_error(
   30575             :                   parser_error::e_syntax,
   30576           0 :                   current_token(),
   30577             :                   "ERR223 - Invalid sequence of brackets",
   30578             :                   exprtk_error_location));
   30579             : 
   30580           0 :                return false;
   30581             :             }
   30582        2100 :             else if (token_t::e_eof != current_token().type)
   30583             :             {
   30584        2100 :                lexer().insert_front(current_token().type);
   30585        2100 :                lexer().insert_front(token_t::e_mul);
   30586        2100 :                next_token();
   30587             :             }
   30588             :          }
   30589             : 
   30590     1714510 :          return true;
   30591             :       }
   30592             : 
   30593             :       typedef typename interval_container_t<const void*>::interval_t interval_t;
   30594             :       typedef interval_container_t<const void*> immutable_memory_map_t;
   30595             :       typedef std::map<interval_t,token_t> immutable_symtok_map_t;
   30596             : 
   30597          18 :       inline interval_t make_memory_range(const T& t)
   30598             :       {
   30599          18 :          const T* begin = reinterpret_cast<const T*>(&t);
   30600          18 :          const T* end   = begin + 1;
   30601          18 :          return interval_t(begin, end);
   30602             :       }
   30603             : 
   30604          13 :       inline interval_t make_memory_range(const T* begin, const std::size_t size)
   30605             :       {
   30606          13 :          return interval_t(begin, begin + size);
   30607             :       }
   30608             : 
   30609          24 :       inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size)
   30610             :       {
   30611          24 :          return interval_t(begin, begin + size);
   30612             :       }
   30613             : 
   30614          55 :       void lodge_immutable_symbol(const lexer::token& token, const interval_t interval)
   30615             :       {
   30616          55 :          immutable_memory_map_.add_interval(interval);
   30617          55 :          immutable_symtok_map_[interval] = token;
   30618          55 :       }
   30619             : 
   30620     2057676 :       inline expression_node_ptr parse_symtab_symbol()
   30621             :       {
   30622     2057676 :          const std::string symbol = current_token().value;
   30623             : 
   30624             :          // Are we dealing with a variable or a special constant?
   30625             :          typedef typename symtab_store::variable_context var_ctxt_t;
   30626     2057676 :          var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol);
   30627             : 
   30628     2057676 :          if (var_ctx.variable)
   30629             :          {
   30630     1800665 :             assert(var_ctx.symbol_table);
   30631             : 
   30632     1800665 :             expression_node_ptr result_variable = var_ctx.variable;
   30633             : 
   30634     1800665 :             if (symtab_store_.is_constant_node(symbol))
   30635             :             {
   30636       43250 :                result_variable = expression_generator_(var_ctx.variable->value());
   30637             :             }
   30638     1757415 :             else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability())
   30639             :             {
   30640          18 :                lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref()));
   30641          18 :                result_variable = var_ctx.variable;
   30642             :             }
   30643             : 
   30644     1800665 :             if (!post_variable_process(symbol))
   30645           0 :                return error_node();
   30646             : 
   30647     1800665 :             lodge_symbol(symbol, e_st_variable);
   30648             : 
   30649     1800665 :             next_token();
   30650             : 
   30651     1800665 :             return result_variable;
   30652             :          }
   30653             : 
   30654             :          // Are we dealing with a locally defined variable, vector or string?
   30655      257011 :          if (!sem_.empty())
   30656             :          {
   30657      130535 :             scope_element& se = sem_.get_active_element(symbol);
   30658             : 
   30659      130535 :             if (se.active && details::imatch(se.name, symbol))
   30660             :             {
   30661      120510 :                if (
   30662      120510 :                     (scope_element::e_variable == se.type) ||
   30663       68838 :                     (scope_element::e_literal  == se.type)
   30664             :                   )
   30665             :                {
   30666       55887 :                   se.active = true;
   30667       55887 :                   lodge_symbol(symbol, e_st_local_variable);
   30668             : 
   30669       55887 :                   if (!post_variable_process(symbol))
   30670           0 :                      return error_node();
   30671             : 
   30672       55887 :                   next_token();
   30673             : 
   30674       55887 :                   return (scope_element::e_variable == se.type) ?
   30675             :                            se.var_node :
   30676       55887 :                            expression_generator_(se.var_node->value());
   30677             :                }
   30678       64623 :                else if (scope_element::e_vector == se.type)
   30679             :                {
   30680       45388 :                   return parse_vector();
   30681             :                }
   30682             :                #ifndef exprtk_disable_string_capabilities
   30683       19235 :                else if (scope_element::e_string == se.type)
   30684             :                {
   30685       19235 :                   return parse_string();
   30686             :                }
   30687             :                #endif
   30688             :             }
   30689             :          }
   30690             : 
   30691             :          #ifndef exprtk_disable_string_capabilities
   30692             :          // Are we dealing with a string variable?
   30693      136501 :          if (symtab_store_.is_stringvar(symbol))
   30694             :          {
   30695       49475 :             return parse_string();
   30696             :          }
   30697             :          #endif
   30698             : 
   30699             :          {
   30700             :             // Are we dealing with a function?
   30701       87026 :             ifunction<T>* function = symtab_store_.get_function(symbol);
   30702             : 
   30703       87026 :             if (function)
   30704             :             {
   30705       60611 :                lodge_symbol(symbol, e_st_function);
   30706             : 
   30707             :                expression_node_ptr func_node =
   30708       60611 :                                       parse_function_invocation(function,symbol);
   30709             : 
   30710       60611 :                if (func_node)
   30711       60611 :                   return func_node;
   30712             :                else
   30713             :                {
   30714           0 :                   set_error(make_error(
   30715             :                      parser_error::e_syntax,
   30716           0 :                      current_token(),
   30717             :                      "ERR224 - Failed to generate node for function: '" + symbol + "'",
   30718             :                      exprtk_error_location));
   30719             : 
   30720           0 :                   return error_node();
   30721             :                }
   30722             :             }
   30723             :          }
   30724             : 
   30725             :          {
   30726             :             // Are we dealing with a vararg function?
   30727       26415 :             ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
   30728             : 
   30729       26415 :             if (vararg_function)
   30730             :             {
   30731          49 :                lodge_symbol(symbol, e_st_function);
   30732             : 
   30733             :                expression_node_ptr vararg_func_node =
   30734          49 :                                       parse_vararg_function_call(vararg_function, symbol);
   30735             : 
   30736          49 :                if (vararg_func_node)
   30737          49 :                   return vararg_func_node;
   30738             :                else
   30739             :                {
   30740           0 :                   set_error(make_error(
   30741             :                      parser_error::e_syntax,
   30742           0 :                      current_token(),
   30743             :                      "ERR225 - Failed to generate node for vararg function: '" + symbol + "'",
   30744             :                      exprtk_error_location));
   30745             : 
   30746           0 :                   return error_node();
   30747             :                }
   30748             :             }
   30749             :          }
   30750             : 
   30751             :          {
   30752             :             // Are we dealing with a vararg generic function?
   30753       26366 :             igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
   30754             : 
   30755       26366 :             if (generic_function)
   30756             :             {
   30757        3500 :                lodge_symbol(symbol, e_st_function);
   30758             : 
   30759             :                expression_node_ptr genericfunc_node =
   30760        3500 :                                       parse_generic_function_call(generic_function, symbol);
   30761             : 
   30762        3500 :                if (genericfunc_node)
   30763        3500 :                   return genericfunc_node;
   30764             :                else
   30765             :                {
   30766           0 :                   set_error(make_error(
   30767             :                      parser_error::e_syntax,
   30768           0 :                      current_token(),
   30769             :                      "ERR226 - Failed to generate node for generic function: '" + symbol + "'",
   30770             :                      exprtk_error_location));
   30771             : 
   30772           0 :                   return error_node();
   30773             :                }
   30774             :             }
   30775             :          }
   30776             : 
   30777             :          #ifndef exprtk_disable_string_capabilities
   30778             :          {
   30779             :             // Are we dealing with a vararg string returning function?
   30780       22866 :             igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
   30781             : 
   30782       22866 :             if (string_function)
   30783             :             {
   30784          36 :                lodge_symbol(symbol, e_st_function);
   30785             : 
   30786             :                expression_node_ptr stringfunc_node =
   30787          36 :                                       parse_string_function_call(string_function, symbol);
   30788             : 
   30789          36 :                if (stringfunc_node)
   30790          36 :                   return stringfunc_node;
   30791             :                else
   30792             :                {
   30793           0 :                   set_error(make_error(
   30794             :                      parser_error::e_syntax,
   30795           0 :                      current_token(),
   30796             :                      "ERR227 - Failed to generate node for string function: '" + symbol + "'",
   30797             :                      exprtk_error_location));
   30798             : 
   30799           0 :                   return error_node();
   30800             :                }
   30801             :             }
   30802             :          }
   30803             : 
   30804             :          {
   30805             :             // Are we dealing with a vararg overloaded scalar/string returning function?
   30806       22830 :             igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
   30807             : 
   30808       22830 :             if (overload_function)
   30809             :             {
   30810          72 :                lodge_symbol(symbol, e_st_function);
   30811             : 
   30812             :                expression_node_ptr overloadfunc_node =
   30813          72 :                                       parse_overload_function_call(overload_function, symbol);
   30814             : 
   30815          72 :                if (overloadfunc_node)
   30816          72 :                   return overloadfunc_node;
   30817             :                else
   30818             :                {
   30819           0 :                   set_error(make_error(
   30820             :                      parser_error::e_syntax,
   30821           0 :                      current_token(),
   30822             :                      "ERR228 - Failed to generate node for overload function: '" + symbol + "'",
   30823             :                      exprtk_error_location));
   30824             : 
   30825           0 :                   return error_node();
   30826             :                }
   30827             :             }
   30828             :          }
   30829             :          #endif
   30830             : 
   30831             :          // Are we dealing with a vector?
   30832       22758 :          if (symtab_store_.is_vector(symbol))
   30833             :          {
   30834        6869 :             lodge_symbol(symbol, e_st_vector);
   30835        6869 :             return parse_vector();
   30836             :          }
   30837             : 
   30838       15889 :          if (details::is_reserved_symbol(symbol))
   30839             :          {
   30840          23 :                if (
   30841          23 :                     settings_.function_enabled(symbol) ||
   30842           0 :                     !details::is_base_function(symbol)
   30843             :                   )
   30844             :                {
   30845          46 :                   set_error(make_error(
   30846             :                      parser_error::e_syntax,
   30847          23 :                      current_token(),
   30848             :                      "ERR229 - Invalid use of reserved symbol '" + symbol + "'",
   30849             :                      exprtk_error_location));
   30850             : 
   30851          23 :                   return error_node();
   30852             :                }
   30853             :          }
   30854             : 
   30855             :          // Should we handle unknown symbols?
   30856       15866 :          if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
   30857             :          {
   30858        5208 :             if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
   30859             :             {
   30860        5208 :                symbol_table_t& symtab = symtab_store_.get_symbol_table();
   30861             : 
   30862        5208 :                std::string error_message;
   30863             : 
   30864        5208 :                if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
   30865             :                {
   30866        3002 :                   T default_value = T(0);
   30867             : 
   30868        3002 :                   typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
   30869             : 
   30870        3002 :                   if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
   30871             :                   {
   30872        3002 :                      bool create_result = false;
   30873             : 
   30874        3002 :                      switch (usr_symbol_type)
   30875             :                      {
   30876        1502 :                         case unknown_symbol_resolver::e_usr_variable_type :
   30877        1502 :                            create_result = symtab.create_variable(symbol, default_value);
   30878        1502 :                            break;
   30879             : 
   30880        1500 :                         case unknown_symbol_resolver::e_usr_constant_type :
   30881        1500 :                            create_result = symtab.add_constant(symbol, default_value);
   30882        1500 :                            break;
   30883             : 
   30884           0 :                         default                                           : create_result = false;
   30885             :                      }
   30886             : 
   30887        3002 :                      if (create_result)
   30888             :                      {
   30889        3002 :                         expression_node_ptr var = symtab_store_.get_variable(symbol);
   30890             : 
   30891        3002 :                         if (var)
   30892             :                         {
   30893        3002 :                            if (symtab_store_.is_constant_node(symbol))
   30894             :                            {
   30895        1500 :                               var = expression_generator_(var->value());
   30896             :                            }
   30897             : 
   30898        3002 :                            lodge_symbol(symbol, e_st_variable);
   30899             : 
   30900        3002 :                            if (!post_variable_process(symbol))
   30901        3002 :                               return error_node();
   30902             : 
   30903        3002 :                            next_token();
   30904             : 
   30905        3002 :                            return var;
   30906             :                         }
   30907             :                      }
   30908             :                   }
   30909             : 
   30910           0 :                   set_error(make_error(
   30911             :                      parser_error::e_symtab,
   30912           0 :                      current_token(),
   30913             :                      "ERR230 - Failed to create variable: '" + symbol + "'" +
   30914           0 :                      (error_message.empty() ? "" : " - " + error_message),
   30915             :                      exprtk_error_location));
   30916             : 
   30917             :                }
   30918        2206 :                else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
   30919             :                {
   30920        2206 :                   if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
   30921             :                   {
   30922        2206 :                      expression_node_ptr result = parse_symtab_symbol();
   30923             : 
   30924        2206 :                      if (result)
   30925             :                      {
   30926        2206 :                         return result;
   30927             :                      }
   30928             :                   }
   30929             : 
   30930           0 :                   set_error(make_error(
   30931             :                      parser_error::e_symtab,
   30932           0 :                      current_token(),
   30933             :                      "ERR231 - Failed to resolve symbol: '" + symbol + "'" +
   30934           0 :                      (error_message.empty() ? "" : " - " + error_message),
   30935             :                      exprtk_error_location));
   30936             :                }
   30937             : 
   30938           0 :                return error_node();
   30939        5208 :             }
   30940             :          }
   30941             : 
   30942       21316 :          set_error(make_error(
   30943             :             parser_error::e_syntax,
   30944       10658 :             current_token(),
   30945             :             "ERR232 - Undefined symbol: '" + symbol + "'",
   30946             :             exprtk_error_location));
   30947             : 
   30948       10658 :          return error_node();
   30949     2057676 :       }
   30950             : 
   30951     2535008 :       inline expression_node_ptr parse_symbol()
   30952             :       {
   30953     2535010 :          static const std::string symbol_if       = "if"      ;
   30954     2535010 :          static const std::string symbol_while    = "while"   ;
   30955     2535010 :          static const std::string symbol_repeat   = "repeat"  ;
   30956     2535010 :          static const std::string symbol_for      = "for"     ;
   30957     2535010 :          static const std::string symbol_switch   = "switch"  ;
   30958     2535010 :          static const std::string symbol_null     = "null"    ;
   30959     2535010 :          static const std::string symbol_break    = "break"   ;
   30960     2535010 :          static const std::string symbol_continue = "continue";
   30961     2535010 :          static const std::string symbol_var      = "var"     ;
   30962     2535010 :          static const std::string symbol_const    = "const"   ;
   30963     2535010 :          static const std::string symbol_swap     = "swap"    ;
   30964     2535010 :          static const std::string symbol_return   = "return"  ;
   30965     2535010 :          static const std::string symbol_not      = "not"     ;
   30966     2535010 :          static const std::string symbol_assert   = "assert"  ;
   30967             : 
   30968     2535008 :          const std::string symbol = current_token().value;
   30969             : 
   30970     2535008 :          if (valid_vararg_operation(symbol))
   30971             :          {
   30972       22327 :             return parse_vararg_function();
   30973             :          }
   30974     2512681 :          else if (details::imatch(symbol, symbol_not))
   30975             :          {
   30976         728 :             return parse_not_statement();
   30977             :          }
   30978     2511953 :          else if (valid_base_operation(symbol))
   30979             :          {
   30980      358621 :             return parse_base_operation();
   30981             :          }
   30982     2153332 :          else if (
   30983     2158559 :                    details::imatch(symbol, symbol_if) &&
   30984        5227 :                    settings_.control_struct_enabled(symbol)
   30985             :                  )
   30986             :          {
   30987        5227 :             return parse_conditional_statement();
   30988             :          }
   30989     2148105 :          else if (
   30990     2148127 :                    details::imatch(symbol, symbol_while) &&
   30991          22 :                    settings_.control_struct_enabled(symbol)
   30992             :                  )
   30993             :          {
   30994          22 :             return parse_while_loop();
   30995             :          }
   30996     2148083 :          else if (
   30997     2148175 :                    details::imatch(symbol, symbol_repeat) &&
   30998          92 :                    settings_.control_struct_enabled(symbol)
   30999             :                  )
   31000             :          {
   31001          92 :             return parse_repeat_until_loop();
   31002             :          }
   31003     2147991 :          else if (
   31004     2150726 :                    details::imatch(symbol, symbol_for) &&
   31005        2735 :                    settings_.control_struct_enabled(symbol)
   31006             :                  )
   31007             :          {
   31008        2735 :             return parse_for_loop();
   31009             :          }
   31010     2145256 :          else if (
   31011     2146451 :                    details::imatch(symbol, symbol_switch) &&
   31012        1195 :                    settings_.control_struct_enabled(symbol)
   31013             :                  )
   31014             :          {
   31015        1195 :             return parse_switch_statement();
   31016             :          }
   31017     2144061 :          else if (details::is_valid_sf_symbol(symbol))
   31018             :          {
   31019        4245 :             return parse_special_function();
   31020             :          }
   31021     2139816 :          else if (details::imatch(symbol, symbol_null))
   31022             :          {
   31023         275 :             return parse_null_statement();
   31024             :          }
   31025             :          #ifndef exprtk_disable_break_continue
   31026     2139541 :          else if (details::imatch(symbol, symbol_break))
   31027             :          {
   31028         483 :             return parse_break_statement();
   31029             :          }
   31030     2139058 :          else if (details::imatch(symbol, symbol_continue))
   31031             :          {
   31032         460 :             return parse_continue_statement();
   31033             :          }
   31034             :          #endif
   31035     2138598 :          else if (details::imatch(symbol, symbol_var))
   31036             :          {
   31037       79605 :             return parse_define_var_statement();
   31038             :          }
   31039     2058993 :          else if (details::imatch(symbol, symbol_const))
   31040             :          {
   31041        2645 :             return parse_define_constvar_statement();
   31042             :          }
   31043     2056348 :          else if (details::imatch(symbol, symbol_swap))
   31044             :          {
   31045         560 :             return parse_swap_statement();
   31046             :          }
   31047             :          #ifndef exprtk_disable_return_statement
   31048     2055788 :          else if (
   31049     2055904 :                    details::imatch(symbol, symbol_return) &&
   31050         116 :                    settings_.control_struct_enabled(symbol)
   31051             :                  )
   31052             :          {
   31053         116 :             return parse_return_statement();
   31054             :          }
   31055             :          #endif
   31056     2055672 :          else if (details::imatch(symbol, symbol_assert))
   31057             :          {
   31058         108 :             return parse_assert_statement();
   31059             :          }
   31060     2055564 :          else if (symtab_store_.valid() || !sem_.empty())
   31061             :          {
   31062     2055470 :             return parse_symtab_symbol();
   31063             :          }
   31064             :          else
   31065             :          {
   31066         188 :             set_error(make_error(
   31067             :                parser_error::e_symtab,
   31068          94 :                current_token(),
   31069             :                "ERR233 - Unknown variable or function encountered. Symbol table(s) "
   31070             :                "is either invalid or does not contain symbol: '" + symbol + "'",
   31071             :                exprtk_error_location));
   31072             : 
   31073          94 :             return error_node();
   31074             :          }
   31075     2535008 :       }
   31076             : 
   31077     6346791 :       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
   31078             :       {
   31079     6346791 :          stack_limit_handler slh(*this);
   31080             : 
   31081     6346791 :          if (!slh)
   31082             :          {
   31083           0 :             return error_node();
   31084             :          }
   31085             : 
   31086     6346791 :          expression_node_ptr branch = error_node();
   31087             : 
   31088     6346791 :          if (token_t::e_number == current_token().type)
   31089             :          {
   31090     1805868 :             T numeric_value = T(0);
   31091             : 
   31092     1805868 :             if (details::string_to_real(current_token().value, numeric_value))
   31093             :             {
   31094     1805868 :                expression_node_ptr literal_exp = expression_generator_(numeric_value);
   31095             : 
   31096     1805868 :                if (0 == literal_exp)
   31097             :                {
   31098           0 :                   set_error(make_error(
   31099             :                      parser_error::e_numeric,
   31100           0 :                      current_token(),
   31101           0 :                      "ERR234 - Failed generate node for scalar: '" + current_token().value + "'",
   31102             :                      exprtk_error_location));
   31103             : 
   31104           0 :                   return error_node();
   31105             :                }
   31106             : 
   31107     1805868 :                next_token();
   31108     1805868 :                branch = literal_exp;
   31109             :             }
   31110             :             else
   31111             :             {
   31112           0 :                set_error(make_error(
   31113             :                   parser_error::e_numeric,
   31114           0 :                   current_token(),
   31115           0 :                   "ERR235 - Failed to convert '" + current_token().value + "' to a number",
   31116             :                   exprtk_error_location));
   31117             : 
   31118           0 :                return error_node();
   31119             :             }
   31120             :          }
   31121     4540923 :          else if (token_t::e_symbol == current_token().type)
   31122             :          {
   31123     2535008 :             branch = parse_symbol();
   31124             :          }
   31125             :          #ifndef exprtk_disable_string_capabilities
   31126     2005915 :          else if (token_t::e_string == current_token().type)
   31127             :          {
   31128       52875 :             branch = parse_const_string();
   31129             :          }
   31130             :          #endif
   31131     1953040 :          else if (token_t::e_lbracket == current_token().type)
   31132             :          {
   31133     1836231 :             next_token();
   31134             : 
   31135     1836231 :             if (0 == (branch = parse_expression()))
   31136      120578 :                return error_node();
   31137     1715653 :             else if (token_is(token_t::e_eof))
   31138             :             {}
   31139     1715623 :             else if (!token_is(token_t::e_rbracket))
   31140             :             {
   31141         222 :                set_error(make_error(
   31142             :                   parser_error::e_syntax,
   31143          74 :                   current_token(),
   31144          74 :                   "ERR236 - Expected ')' instead of: '" + current_token().value + "'",
   31145             :                   exprtk_error_location));
   31146             : 
   31147          74 :                details::free_node(node_allocator_,branch);
   31148             : 
   31149          74 :                return error_node();
   31150             :             }
   31151     1715549 :             else if (!post_bracket_process(token_t::e_lbracket,branch))
   31152             :             {
   31153           0 :                details::free_node(node_allocator_,branch);
   31154             : 
   31155           0 :                return error_node();
   31156             :             }
   31157             : 
   31158     1715579 :             parse_pending_vector_index_operator(branch);
   31159             :          }
   31160      116809 :          else if (token_t::e_lsqrbracket == current_token().type)
   31161             :          {
   31162        6387 :             next_token();
   31163             : 
   31164        6387 :             if (0 == (branch = parse_expression()))
   31165           2 :                return error_node();
   31166        6385 :             else if (!token_is(token_t::e_rsqrbracket))
   31167             :             {
   31168           0 :                set_error(make_error(
   31169             :                   parser_error::e_syntax,
   31170           0 :                   current_token(),
   31171           0 :                   "ERR237 - Expected ']' instead of: '" + current_token().value + "'",
   31172             :                   exprtk_error_location));
   31173             : 
   31174           0 :                details::free_node(node_allocator_,branch);
   31175             : 
   31176           0 :                return error_node();
   31177             :             }
   31178        6385 :             else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
   31179             :             {
   31180           0 :                details::free_node(node_allocator_,branch);
   31181             : 
   31182           0 :                return error_node();
   31183             :             }
   31184             :          }
   31185      110422 :          else if (token_t::e_lcrlbracket == current_token().type)
   31186             :          {
   31187        2445 :             next_token();
   31188             : 
   31189        2445 :             if (0 == (branch = parse_expression()))
   31190           0 :                return error_node();
   31191        2445 :             else if (!token_is(token_t::e_rcrlbracket))
   31192             :             {
   31193           0 :                set_error(make_error(
   31194             :                   parser_error::e_syntax,
   31195           0 :                   current_token(),
   31196           0 :                   "ERR238 - Expected '}' instead of: '" + current_token().value + "'",
   31197             :                   exprtk_error_location));
   31198             : 
   31199           0 :                details::free_node(node_allocator_,branch);
   31200             : 
   31201           0 :                return error_node();
   31202             :             }
   31203        2445 :             else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
   31204             :             {
   31205           0 :                details::free_node(node_allocator_,branch);
   31206             : 
   31207           0 :                return error_node();
   31208             :             }
   31209             :          }
   31210      107977 :          else if (token_t::e_sub == current_token().type)
   31211             :          {
   31212      101315 :             next_token();
   31213      101315 :             branch = parse_expression(e_level11);
   31214             : 
   31215      101315 :             if (
   31216      202618 :                  branch &&
   31217             :                  !(
   31218      101303 :                     details::is_neg_unary_node    (branch) &&
   31219         640 :                     simplify_unary_negation_branch(branch)
   31220             :                   )
   31221             :                )
   31222             :             {
   31223      100663 :                expression_node_ptr result = expression_generator_(details::e_neg,branch);
   31224             : 
   31225      100663 :                if (0 == result)
   31226             :                {
   31227           0 :                   details::free_node(node_allocator_,branch);
   31228             : 
   31229           0 :                   return error_node();
   31230             :                }
   31231             :                else
   31232      100663 :                   branch = result;
   31233             :             }
   31234             :          }
   31235        6662 :          else if (token_t::e_add == current_token().type)
   31236             :          {
   31237        6575 :             next_token();
   31238        6575 :             branch = parse_expression(e_level13);
   31239             :          }
   31240          87 :          else if (token_t::e_eof == current_token().type)
   31241             :          {
   31242          64 :             set_error(make_error(
   31243             :                parser_error::e_syntax,
   31244          16 :                current_token(),
   31245             :                "ERR239 - Premature end of expression[1]",
   31246             :                exprtk_error_location));
   31247             : 
   31248          16 :             return error_node();
   31249             :          }
   31250             :          else
   31251             :          {
   31252         284 :             set_error(make_error(
   31253             :                parser_error::e_syntax,
   31254          71 :                current_token(),
   31255             :                "ERR240 - Premature end of expression[2]",
   31256             :                exprtk_error_location));
   31257             : 
   31258          71 :             return error_node();
   31259             :          }
   31260             : 
   31261     6226050 :          if (
   31262     6193283 :               branch                    &&
   31263    12419333 :               (e_level00 == precedence) &&
   31264     9623484 :               token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
   31265             :             )
   31266             :          {
   31267         700 :             branch = parse_ternary_conditional_statement(branch);
   31268             :          }
   31269             : 
   31270     6226050 :          parse_pending_string_rangesize(branch);
   31271             : 
   31272     6226050 :          return branch;
   31273     6346791 :       }
   31274             : 
   31275             :       template <typename Type>
   31276             :       class expression_generator
   31277             :       {
   31278             :       public:
   31279             : 
   31280             :          typedef details::expression_node<Type>* expression_node_ptr;
   31281             :          typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
   31282             :          typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
   31283             :          typedef typename exprtk::parser<Type> parser_t;
   31284             :          typedef const Type& vtype;
   31285             :          typedef const Type  ctype;
   31286             : 
   31287      108660 :          inline void init_synthesize_map()
   31288             :          {
   31289             :             #ifndef exprtk_disable_enhanced_features
   31290      217320 :             synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
   31291      217320 :             synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
   31292      217320 :             synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
   31293             : 
   31294             :             #define register_synthezier(S)                      \
   31295             :             synthesize_map_[S ::node_type::id()] = S ::process; \
   31296             : 
   31297      108660 :             register_synthezier(synthesize_vovov_expression0)
   31298      108660 :             register_synthezier(synthesize_vovov_expression1)
   31299      108660 :             register_synthezier(synthesize_vovoc_expression0)
   31300      108660 :             register_synthezier(synthesize_vovoc_expression1)
   31301      108660 :             register_synthezier(synthesize_vocov_expression0)
   31302      108660 :             register_synthezier(synthesize_vocov_expression1)
   31303      108660 :             register_synthezier(synthesize_covov_expression0)
   31304      108660 :             register_synthezier(synthesize_covov_expression1)
   31305      108660 :             register_synthezier(synthesize_covoc_expression0)
   31306      108660 :             register_synthezier(synthesize_covoc_expression1)
   31307      108660 :             register_synthezier(synthesize_cocov_expression1)
   31308      108660 :             register_synthezier(synthesize_vococ_expression0)
   31309             : 
   31310      108660 :             register_synthezier(synthesize_vovovov_expression0)
   31311      108660 :             register_synthezier(synthesize_vovovoc_expression0)
   31312      108660 :             register_synthezier(synthesize_vovocov_expression0)
   31313      108660 :             register_synthezier(synthesize_vocovov_expression0)
   31314      108660 :             register_synthezier(synthesize_covovov_expression0)
   31315      108660 :             register_synthezier(synthesize_covocov_expression0)
   31316      108660 :             register_synthezier(synthesize_vocovoc_expression0)
   31317      108660 :             register_synthezier(synthesize_covovoc_expression0)
   31318      108660 :             register_synthezier(synthesize_vococov_expression0)
   31319             : 
   31320      108660 :             register_synthezier(synthesize_vovovov_expression1)
   31321      108660 :             register_synthezier(synthesize_vovovoc_expression1)
   31322      108660 :             register_synthezier(synthesize_vovocov_expression1)
   31323      108660 :             register_synthezier(synthesize_vocovov_expression1)
   31324      108660 :             register_synthezier(synthesize_covovov_expression1)
   31325      108660 :             register_synthezier(synthesize_covocov_expression1)
   31326      108660 :             register_synthezier(synthesize_vocovoc_expression1)
   31327      108660 :             register_synthezier(synthesize_covovoc_expression1)
   31328      108660 :             register_synthezier(synthesize_vococov_expression1)
   31329             : 
   31330      108660 :             register_synthezier(synthesize_vovovov_expression2)
   31331      108660 :             register_synthezier(synthesize_vovovoc_expression2)
   31332      108660 :             register_synthezier(synthesize_vovocov_expression2)
   31333      108660 :             register_synthezier(synthesize_vocovov_expression2)
   31334      108660 :             register_synthezier(synthesize_covovov_expression2)
   31335      108660 :             register_synthezier(synthesize_covocov_expression2)
   31336      108660 :             register_synthezier(synthesize_vocovoc_expression2)
   31337      108660 :             register_synthezier(synthesize_covovoc_expression2)
   31338             : 
   31339      108660 :             register_synthezier(synthesize_vovovov_expression3)
   31340      108660 :             register_synthezier(synthesize_vovovoc_expression3)
   31341      108660 :             register_synthezier(synthesize_vovocov_expression3)
   31342      108660 :             register_synthezier(synthesize_vocovov_expression3)
   31343      108660 :             register_synthezier(synthesize_covovov_expression3)
   31344      108660 :             register_synthezier(synthesize_covocov_expression3)
   31345      108660 :             register_synthezier(synthesize_vocovoc_expression3)
   31346      108660 :             register_synthezier(synthesize_covovoc_expression3)
   31347      108660 :             register_synthezier(synthesize_vococov_expression3)
   31348             : 
   31349      108660 :             register_synthezier(synthesize_vovovov_expression4)
   31350      108660 :             register_synthezier(synthesize_vovovoc_expression4)
   31351      108660 :             register_synthezier(synthesize_vovocov_expression4)
   31352      108660 :             register_synthezier(synthesize_vocovov_expression4)
   31353      108660 :             register_synthezier(synthesize_covovov_expression4)
   31354      108660 :             register_synthezier(synthesize_covocov_expression4)
   31355      108660 :             register_synthezier(synthesize_vocovoc_expression4)
   31356      108660 :             register_synthezier(synthesize_covovoc_expression4)
   31357             : 
   31358             :             #undef register_synthezier
   31359             :             #endif
   31360      108660 :          }
   31361             : 
   31362      108660 :          inline void set_parser(parser_t& p)
   31363             :          {
   31364      108660 :             parser_ = &p;
   31365      108660 :          }
   31366             : 
   31367      108660 :          inline void set_uom(unary_op_map_t& unary_op_map)
   31368             :          {
   31369      108660 :             unary_op_map_ = &unary_op_map;
   31370      108660 :          }
   31371             : 
   31372      108660 :          inline void set_bom(binary_op_map_t& binary_op_map)
   31373             :          {
   31374      108660 :             binary_op_map_ = &binary_op_map;
   31375      108660 :          }
   31376             : 
   31377      108660 :          inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
   31378             :          {
   31379      108660 :             inv_binary_op_map_ = &inv_binary_op_map;
   31380      108660 :          }
   31381             : 
   31382      108660 :          inline void set_sf3m(sf3_map_t& sf3_map)
   31383             :          {
   31384      108660 :             sf3_map_ = &sf3_map;
   31385      108660 :          }
   31386             : 
   31387      108660 :          inline void set_sf4m(sf4_map_t& sf4_map)
   31388             :          {
   31389      108660 :             sf4_map_ = &sf4_map;
   31390      108660 :          }
   31391             : 
   31392      380686 :          inline void set_allocator(details::node_allocator& na)
   31393             :          {
   31394      380686 :             node_allocator_ = &na;
   31395      380686 :          }
   31396             : 
   31397      108660 :          inline void set_strength_reduction_state(const bool enabled)
   31398             :          {
   31399      108660 :             strength_reduction_enabled_ = enabled;
   31400      108660 :          }
   31401             : 
   31402             :          inline bool strength_reduction_enabled() const
   31403             :          {
   31404             :             return strength_reduction_enabled_;
   31405             :          }
   31406             : 
   31407       33571 :          inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
   31408             :          {
   31409       33571 :             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
   31410             : 
   31411       33571 :             if (binary_op_map_->end() == bop_itr)
   31412           0 :                return false;
   31413             : 
   31414       33571 :             bop = bop_itr->second;
   31415             : 
   31416       33571 :             return true;
   31417             :          }
   31418             : 
   31419        1800 :          inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
   31420             :          {
   31421        1800 :             typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
   31422             : 
   31423        1800 :             if ((*unary_op_map_).end() == uop_itr)
   31424           0 :                return false;
   31425             : 
   31426        1800 :             uop = uop_itr->second;
   31427             : 
   31428        1800 :             return true;
   31429             :          }
   31430             : 
   31431           0 :          inline details::operator_type get_operator(const binary_functor_t& bop) const
   31432             :          {
   31433           0 :             return (*inv_binary_op_map_).find(bop)->second;
   31434             :          }
   31435             : 
   31436     1864959 :          inline expression_node_ptr operator() (const Type& v) const
   31437             :          {
   31438     1864959 :             return node_allocator_->allocate<literal_node_t>(v);
   31439             :          }
   31440             : 
   31441             :          #ifndef exprtk_disable_string_capabilities
   31442       52875 :          inline expression_node_ptr operator() (const std::string& s) const
   31443             :          {
   31444       52875 :             return node_allocator_->allocate<string_literal_node_t>(s);
   31445             :          }
   31446             : 
   31447       22401 :          inline expression_node_ptr operator() (std::string& s, range_t& rp) const
   31448             :          {
   31449       22401 :             return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
   31450             :          }
   31451             : 
   31452        5553 :          inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
   31453             :          {
   31454        5553 :             return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
   31455             :          }
   31456             : 
   31457        4102 :          inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
   31458             :          {
   31459        4102 :             if (is_generally_string_node(branch))
   31460        4102 :                return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
   31461             :             else
   31462           0 :                return error_node();
   31463             :          }
   31464             :          #endif
   31465             : 
   31466      133618 :          inline bool unary_optimisable(const details::operator_type& operation) const
   31467             :          {
   31468      123812 :             return (details::e_abs   == operation) || (details::e_acos  == operation) ||
   31469      123752 :                    (details::e_acosh == operation) || (details::e_asin  == operation) ||
   31470      123632 :                    (details::e_asinh == operation) || (details::e_atan  == operation) ||
   31471      123502 :                    (details::e_atanh == operation) || (details::e_ceil  == operation) ||
   31472      123442 :                    (details::e_cos   == operation) || (details::e_cosh  == operation) ||
   31473      107657 :                    (details::e_exp   == operation) || (details::e_expm1 == operation) ||
   31474      107537 :                    (details::e_floor == operation) || (details::e_log   == operation) ||
   31475      107363 :                    (details::e_log10 == operation) || (details::e_log2  == operation) ||
   31476      107253 :                    (details::e_log1p == operation) || (details::e_neg   == operation) ||
   31477       98649 :                    (details::e_pos   == operation) || (details::e_round == operation) ||
   31478       98589 :                    (details::e_sin   == operation) || (details::e_sinc  == operation) ||
   31479       18237 :                    (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
   31480       18029 :                    (details::e_tan   == operation) || (details::e_tanh  == operation) ||
   31481         941 :                    (details::e_cot   == operation) || (details::e_sec   == operation) ||
   31482         807 :                    (details::e_csc   == operation) || (details::e_r2d   == operation) ||
   31483         682 :                    (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
   31484         562 :                    (details::e_g2d   == operation) || (details::e_notl  == operation) ||
   31485         486 :                    (details::e_sgn   == operation) || (details::e_erf   == operation) ||
   31486         213 :                    (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
   31487      257430 :                    (details::e_frac  == operation) || (details::e_trunc == operation) ;
   31488             :          }
   31489             : 
   31490             :          inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
   31491             :          {
   31492             :             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
   31493             : 
   31494             :             if (sf3_map_->end() == itr)
   31495             :                return false;
   31496             :             else
   31497             :                tfunc = itr->second.first;
   31498             : 
   31499             :             return true;
   31500             :          }
   31501             : 
   31502             :          inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
   31503             :          {
   31504             :             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
   31505             : 
   31506             :             if (sf4_map_->end() == itr)
   31507             :                return false;
   31508             :             else
   31509             :                qfunc = itr->second.first;
   31510             : 
   31511             :             return true;
   31512             :          }
   31513             : 
   31514      377040 :          inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
   31515             :          {
   31516      377040 :             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
   31517             : 
   31518      377040 :             if (sf3_map_->end() == itr)
   31519        5960 :                return false;
   31520             :             else
   31521      371080 :                operation = itr->second.second;
   31522             : 
   31523      371080 :             return true;
   31524             :          }
   31525             : 
   31526      243720 :          inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
   31527             :          {
   31528      243720 :             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
   31529             : 
   31530      243720 :             if (sf4_map_->end() == itr)
   31531      145836 :                return false;
   31532             :             else
   31533       97884 :                operation = itr->second.second;
   31534             : 
   31535       97884 :             return true;
   31536             :          }
   31537             : 
   31538      171745 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
   31539             :          {
   31540      171745 :             if (0 == branch[0])
   31541             :             {
   31542           0 :                return error_node();
   31543             :             }
   31544      171745 :             else if (details::is_null_node(branch[0]))
   31545             :             {
   31546           0 :                return branch[0];
   31547             :             }
   31548      171745 :             else if (details::is_break_node(branch[0]))
   31549             :             {
   31550           0 :                return error_node();
   31551             :             }
   31552      171745 :             else if (details::is_continue_node(branch[0]))
   31553             :             {
   31554           0 :                return error_node();
   31555             :             }
   31556      171745 :             else if (details::is_constant_node(branch[0]))
   31557             :             {
   31558      100770 :                return synthesize_expression<unary_node_t,1>(operation,branch);
   31559             :             }
   31560       70975 :             else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
   31561             :             {
   31562        8332 :                return synthesize_uv_expression(operation,branch);
   31563             :             }
   31564       62643 :             else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
   31565             :             {
   31566        2690 :                return synthesize_uvec_expression(operation,branch);
   31567             :             }
   31568             :             else
   31569       59953 :                return synthesize_unary_expression(operation,branch);
   31570             :          }
   31571             : 
   31572     5936917 :          inline bool is_assignment_operation(const details::operator_type& operation) const
   31573             :          {
   31574             :             return (
   31575    11853680 :                      (details::e_addass == operation) ||
   31576     5916763 :                      (details::e_subass == operation) ||
   31577     5914672 :                      (details::e_mulass == operation) ||
   31578     5914012 :                      (details::e_divass == operation) ||
   31579     5913352 :                      (details::e_modass == operation)
   31580    11873834 :                    ) &&
   31581     5960632 :                    parser_->settings_.assignment_enabled(operation);
   31582             :          }
   31583             : 
   31584             :          #ifndef exprtk_disable_string_capabilities
   31585     3047559 :          inline bool valid_string_operation(const details::operator_type& operation) const
   31586             :          {
   31587     5346060 :             return (details::e_add    == operation) ||
   31588     2298501 :                    (details::e_lt     == operation) ||
   31589     2290601 :                    (details::e_lte    == operation) ||
   31590     2288230 :                    (details::e_gt     == operation) ||
   31591     2280836 :                    (details::e_gte    == operation) ||
   31592     2280001 :                    (details::e_eq     == operation) ||
   31593     2191326 :                    (details::e_ne     == operation) ||
   31594     2185831 :                    (details::e_in     == operation) ||
   31595     2184299 :                    (details::e_like   == operation) ||
   31596     2178159 :                    (details::e_ilike  == operation) ||
   31597     2171669 :                    (details::e_assign == operation) ||
   31598     7442826 :                    (details::e_addass == operation) ||
   31599     5144325 :                    (details::e_swap   == operation) ;
   31600             :          }
   31601             :          #else
   31602             :          inline bool valid_string_operation(const details::operator_type&) const
   31603             :          {
   31604             :             return false;
   31605             :          }
   31606             :          #endif
   31607             : 
   31608     1034692 :          inline std::string to_str(const details::operator_type& operation) const
   31609             :          {
   31610     1034692 :             switch (operation)
   31611             :             {
   31612      692346 :                case details::e_add  : return "+"      ;
   31613      671628 :                case details::e_sub  : return "-"      ;
   31614     1042827 :                case details::e_mul  : return "*"      ;
   31615      642708 :                case details::e_div  : return "/"      ;
   31616          66 :                case details::e_mod  : return "%"      ;
   31617        2121 :                case details::e_pow  : return "^"      ;
   31618        1533 :                case details::e_lt   : return "<"      ;
   31619         363 :                case details::e_lte  : return "<="     ;
   31620        3030 :                case details::e_gt   : return ">"      ;
   31621           0 :                case details::e_gte  : return ">="     ;
   31622       37275 :                case details::e_eq   : return "=="     ;
   31623         360 :                case details::e_ne   : return "!="     ;
   31624        9816 :                case details::e_and  : return "and"    ;
   31625           0 :                case details::e_nand : return "nand"   ;
   31626           3 :                case details::e_or   : return "or"     ;
   31627           0 :                case details::e_nor  : return "nor"    ;
   31628           0 :                case details::e_xor  : return "xor"    ;
   31629           0 :                case details::e_xnor : return "xnor"   ;
   31630           0 :                default              : return "UNKNOWN";
   31631             :             }
   31632             :          }
   31633             : 
   31634    11168957 :          inline bool operation_optimisable(const details::operator_type& operation) const
   31635             :          {
   31636    18996421 :             return (details::e_add  == operation) ||
   31637     7827464 :                    (details::e_sub  == operation) ||
   31638     5749346 :                    (details::e_mul  == operation) ||
   31639     3858880 :                    (details::e_div  == operation) ||
   31640     2500605 :                    (details::e_mod  == operation) ||
   31641     2499108 :                    (details::e_pow  == operation) ||
   31642     2361325 :                    (details::e_lt   == operation) ||
   31643     2346170 :                    (details::e_lte  == operation) ||
   31644     2341654 :                    (details::e_gt   == operation) ||
   31645     2326949 :                    (details::e_gte  == operation) ||
   31646     2325329 :                    (details::e_eq   == operation) ||
   31647     2204983 :                    (details::e_ne   == operation) ||
   31648     2202530 :                    (details::e_and  == operation) ||
   31649     2149266 :                    (details::e_nand == operation) ||
   31650     2144462 :                    (details::e_or   == operation) ||
   31651     2139253 :                    (details::e_nor  == operation) ||
   31652    21128925 :                    (details::e_xor  == operation) ||
   31653    13301461 :                    (details::e_xnor == operation) ;
   31654             :          }
   31655             : 
   31656     5182302 :          inline std::string branch_to_id(expression_node_ptr branch) const
   31657             :          {
   31658     5182304 :             static const std::string null_str   ("(null)" );
   31659     5182304 :             static const std::string const_str  ("(c)"    );
   31660     5182304 :             static const std::string var_str    ("(v)"    );
   31661     5182304 :             static const std::string vov_str    ("(vov)"  );
   31662     5182304 :             static const std::string cov_str    ("(cov)"  );
   31663     5182304 :             static const std::string voc_str    ("(voc)"  );
   31664     5182304 :             static const std::string str_str    ("(s)"    );
   31665     5182304 :             static const std::string strrng_str ("(rngs)" );
   31666     5182304 :             static const std::string cs_str     ("(cs)"   );
   31667     5182304 :             static const std::string cstrrng_str("(crngs)");
   31668             : 
   31669     5182302 :             if (details::is_null_node(branch))
   31670           0 :                return null_str;
   31671     5182302 :             else if (details::is_constant_node(branch))
   31672     1384901 :                return const_str;
   31673     3797401 :             else if (details::is_variable_node(branch))
   31674     1730261 :                return var_str;
   31675     2067140 :             else if (details::is_vov_node(branch))
   31676      256010 :                return vov_str;
   31677     1811130 :             else if (details::is_cov_node(branch))
   31678      235649 :                return cov_str;
   31679     1575481 :             else if (details::is_voc_node(branch))
   31680      194933 :                return voc_str;
   31681     1380548 :             else if (details::is_string_node(branch))
   31682           0 :                return str_str;
   31683     1380548 :             else if (details::is_const_string_node(branch))
   31684           0 :                return cs_str;
   31685     1380548 :             else if (details::is_string_range_node(branch))
   31686           0 :                return strrng_str;
   31687     1380548 :             else if (details::is_const_string_range_node(branch))
   31688           0 :                return cstrrng_str;
   31689     1380548 :             else if (details::is_t0ot1ot2_node(branch))
   31690      346237 :                return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
   31691     1034311 :             else if (details::is_t0ot1ot2ot3_node(branch))
   31692       88722 :                return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
   31693             :             else
   31694     1891178 :                return "ERROR";
   31695             :          }
   31696             : 
   31697     2591151 :          inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
   31698             :          {
   31699     7773453 :             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
   31700             :          }
   31701             : 
   31702      855557 :          inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31703             :          {
   31704      855557 :             if (!operation_optimisable(operation))
   31705      266483 :                return false;
   31706             :             else
   31707      771141 :                return details::is_constant_node(branch[0]) &&
   31708      771141 :                       details::is_variable_node(branch[1]) ;
   31709             :          }
   31710             : 
   31711             :          inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31712             :          {
   31713             :             if (!operation_optimisable(operation))
   31714             :                return false;
   31715             :             else
   31716             :                return details::is_variable_node(branch[0]) &&
   31717             :                       details::is_constant_node(branch[1]) ;
   31718             :          }
   31719             : 
   31720             :          inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31721             :          {
   31722             :             if (!operation_optimisable(operation))
   31723             :                return false;
   31724             :             else
   31725             :                return details::is_variable_node(branch[0]) &&
   31726             :                       details::is_variable_node(branch[1]) ;
   31727             :          }
   31728             : 
   31729     1101697 :          inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31730             :          {
   31731     1101697 :             if (!operation_optimisable(operation))
   31732      266483 :                return false;
   31733             :             else
   31734     1116413 :                return details::is_constant_node(branch[0]) &&
   31735     1116413 :                      !details::is_constant_node(branch[1]) ;
   31736             :          }
   31737             : 
   31738     1002565 :          inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31739             :          {
   31740     1002565 :             if (!operation_optimisable(operation))
   31741      266483 :                return false;
   31742             :             else
   31743     1290097 :                return !details::is_constant_node(branch[0]) &&
   31744     1290097 :                        details::is_constant_node(branch[1]) ;
   31745             :          }
   31746             : 
   31747     1544104 :          inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31748             :          {
   31749     1544104 :             if (
   31750     1544104 :                  (details::e_add == operation) ||
   31751     1030141 :                  (details::e_sub == operation) ||
   31752      725772 :                  (details::e_mul == operation) ||
   31753      461042 :                  (details::e_div == operation)
   31754             :                )
   31755             :             {
   31756     2482909 :                return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
   31757     2482909 :                       (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
   31758             :             }
   31759             :             else
   31760      301049 :                return false;
   31761             :          }
   31762             : 
   31763     1536146 :          inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31764             :          {
   31765     1536146 :             if (
   31766     1536146 :                  (details::e_add == operation) ||
   31767     1023996 :                  (details::e_sub == operation) ||
   31768      722217 :                  (details::e_mul == operation) ||
   31769      458847 :                  (details::e_div == operation)
   31770             :                )
   31771             :             {
   31772     2467939 :                return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
   31773     2467939 :                       (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
   31774             :             }
   31775             :             else
   31776      301049 :                return false;
   31777             :          }
   31778             : 
   31779     1516802 :          inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31780             :          {
   31781     1516802 :             if (!operation_optimisable(operation))
   31782      266483 :                return false;
   31783             :             else
   31784     1252603 :                return details::is_uv_node(branch[0]) &&
   31785     1252603 :                       details::is_uv_node(branch[1]) ;
   31786             :          }
   31787             : 
   31788     1515902 :          inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31789             :          {
   31790     1515902 :             if (!operation_optimisable(operation))
   31791      266483 :                return false;
   31792             :             else
   31793     1302078 :                return details::is_variable_node(branch[0]) &&
   31794     1302078 :                      !details::is_variable_node(branch[1]) ;
   31795             :          }
   31796             : 
   31797     1463243 :          inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31798             :          {
   31799     1463243 :             if (!operation_optimisable(operation))
   31800      266483 :                return false;
   31801             :             else
   31802     2393520 :                return !details::is_variable_node(branch[0]) &&
   31803     2393520 :                        details::is_variable_node(branch[1]) ;
   31804             :          }
   31805             : 
   31806      855557 :          inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31807             :          {
   31808      855557 :             if (!operation_optimisable(operation))
   31809      266483 :                return false;
   31810             :             else
   31811      771141 :                return !details::is_constant_node(branch[0]) ||
   31812      771141 :                       !details::is_constant_node(branch[1]) ;
   31813             :          }
   31814             : 
   31815     3002237 :          inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31816             :          {
   31817     3002237 :             if (is_assignment_operation(operation))
   31818             :             {
   31819       11859 :                const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
   31820             : 
   31821       11859 :                if (details::is_string_node(branch[0]))
   31822        2600 :                   return !b1_is_genstring;
   31823        9259 :                else if (details::is_literal_node(branch[0]))
   31824           0 :                   return true;
   31825             :                else
   31826             :                   return (
   31827        9259 :                            !details::is_variable_node              (branch[0]) &&
   31828        4377 :                            !details::is_vector_elem_node           (branch[0]) &&
   31829        3876 :                            !details::is_vector_celem_node          (branch[0]) &&
   31830        3876 :                            !details::is_vector_elem_rtc_node       (branch[0]) &&
   31831        3864 :                            !details::is_vector_celem_rtc_node      (branch[0]) &&
   31832        3864 :                            !details::is_rebasevector_elem_node     (branch[0]) &&
   31833        3564 :                            !details::is_rebasevector_celem_node    (branch[0]) &&
   31834        3264 :                            !details::is_rebasevector_elem_rtc_node (branch[0]) &&
   31835        3264 :                            !details::is_rebasevector_celem_rtc_node(branch[0]) &&
   31836        3264 :                            !details::is_vector_node                (branch[0])
   31837             :                          )
   31838       13636 :                          || b1_is_genstring;
   31839             :             }
   31840             :             else
   31841     2990378 :                return false;
   31842             :          }
   31843             : 
   31844     2857635 :          inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
   31845             :          {
   31846     2857635 :             if (
   31847     2857635 :                  !details::is_constant_node(branch[1]) ||
   31848      851589 :                   details::is_constant_node(branch[0]) ||
   31849      653422 :                   details::is_variable_node(branch[0]) ||
   31850     4006100 :                   details::is_vector_node  (branch[0]) ||
   31851      296876 :                   details::is_generally_string_node(branch[0])
   31852             :                )
   31853     2560759 :                return false;
   31854             : 
   31855      296876 :             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   31856             : 
   31857      296876 :             return cardinal_pow_optimisable(operation, c);
   31858             :          }
   31859             : 
   31860     3002234 :          inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
   31861             :          {
   31862             :             return (
   31863     3002234 :                      details::is_break_node   (branch[0]) ||
   31864     3002234 :                      details::is_break_node   (branch[1]) ||
   31865     9006702 :                      details::is_continue_node(branch[0]) ||
   31866     3002234 :                      details::is_continue_node(branch[1])
   31867     3002234 :                    );
   31868             :          }
   31869             : 
   31870     3002237 :          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31871             :          {
   31872     3002237 :             const bool b0_string = is_generally_string_node(branch[0]);
   31873     3002237 :             const bool b1_string = is_generally_string_node(branch[1]);
   31874             : 
   31875     3002237 :             bool result = false;
   31876             : 
   31877     3002237 :             if (b0_string != b1_string)
   31878           0 :                result = true;
   31879     3002237 :             else if (!valid_string_operation(operation) && b0_string && b1_string)
   31880           0 :                result = true;
   31881             : 
   31882     3002237 :             if (result)
   31883             :             {
   31884           0 :                parser_->set_synthesis_error("Invalid string operation");
   31885             :             }
   31886             : 
   31887     3002237 :             return result;
   31888             :          }
   31889             : 
   31890         471 :          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
   31891             :          {
   31892         471 :             const bool b0_string = is_generally_string_node(branch[0]);
   31893         471 :             const bool b1_string = is_generally_string_node(branch[1]);
   31894         471 :             const bool b2_string = is_generally_string_node(branch[2]);
   31895             : 
   31896         471 :             bool result = false;
   31897             : 
   31898         471 :             if ((b0_string != b1_string) || (b1_string != b2_string))
   31899           0 :                result = true;
   31900         471 :             else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
   31901           0 :                result = true;
   31902             : 
   31903         471 :             if (result)
   31904             :             {
   31905           0 :                parser_->set_synthesis_error("Invalid string operation");
   31906             :             }
   31907             : 
   31908         471 :             return result;
   31909             :          }
   31910             : 
   31911     2903212 :          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31912             :          {
   31913     2903212 :             const bool b0_string = is_generally_string_node(branch[0]);
   31914     2903212 :             const bool b1_string = is_generally_string_node(branch[1]);
   31915             : 
   31916     2903212 :             return (b0_string && b1_string && valid_string_operation(operation));
   31917             :          }
   31918             : 
   31919         471 :          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
   31920             :          {
   31921         471 :             const bool b0_string = is_generally_string_node(branch[0]);
   31922         471 :             const bool b1_string = is_generally_string_node(branch[1]);
   31923         471 :             const bool b2_string = is_generally_string_node(branch[2]);
   31924             : 
   31925         471 :             return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
   31926             :          }
   31927             : 
   31928             :          #ifndef exprtk_disable_sc_andor
   31929     2904068 :          inline bool is_shortcircuit_expression(const details::operator_type& operation) const
   31930             :          {
   31931             :             return (
   31932     5807700 :                      (details::e_scand == operation) ||
   31933     2903632 :                      (details::e_scor  == operation)
   31934     2904068 :                    );
   31935             :          }
   31936             :          #else
   31937             :          inline bool is_shortcircuit_expression(const details::operator_type&) const
   31938             :          {
   31939             :             return false;
   31940             :          }
   31941             :          #endif
   31942             : 
   31943     2857890 :          inline bool is_null_present(expression_node_ptr (&branch)[2]) const
   31944             :          {
   31945             :             return (
   31946     5715720 :                      details::is_null_node(branch[0]) ||
   31947     2857830 :                      details::is_null_node(branch[1])
   31948     2857890 :                    );
   31949             :          }
   31950             : 
   31951     2922824 :          inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31952             :          {
   31953     2922824 :             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
   31954     2904068 :                return false;
   31955             :             else
   31956             :                return (
   31957       36707 :                         (details::e_lt    == operation) ||
   31958       17951 :                         (details::e_lte   == operation) ||
   31959       17671 :                         (details::e_gt    == operation) ||
   31960       17351 :                         (details::e_gte   == operation) ||
   31961       17151 :                         (details::e_eq    == operation) ||
   31962       12579 :                         (details::e_ne    == operation) ||
   31963       12419 :                         (details::e_equal == operation) ||
   31964       12299 :                         (details::e_and   == operation) ||
   31965       12299 :                         (details::e_nand  == operation) ||
   31966       12299 :                         (details::e_or    == operation) ||
   31967       12299 :                         (details::e_nor   == operation) ||
   31968       49006 :                         (details::e_xor   == operation) ||
   31969       12299 :                         (details::e_xnor  == operation)
   31970       18756 :                       );
   31971             :          }
   31972             : 
   31973     2916367 :          inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   31974             :          {
   31975     2916367 :             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
   31976     2904068 :                return false;
   31977             :             else
   31978             :                return (
   31979       21984 :                         (details::e_add == operation) ||
   31980        9685 :                         (details::e_sub == operation) ||
   31981        5484 :                         (details::e_mul == operation) ||
   31982       22024 :                         (details::e_div == operation) ||
   31983          40 :                         (details::e_pow == operation)
   31984       12299 :                       );
   31985             :          }
   31986             : 
   31987     3002237 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
   31988             :          {
   31989     3002237 :             if ((0 == branch[0]) || (0 == branch[1]))
   31990             :             {
   31991           0 :                parser_->set_error(parser_error::make_error(
   31992             :                   parser_error::e_syntax,
   31993           0 :                   parser_->current_state().token,
   31994             :                   "ERR241 - Invalid branches received for operator '" + details::to_str(operation) + "'",
   31995             :                   exprtk_error_location));
   31996             : 
   31997           0 :                return error_node();
   31998             :             }
   31999     3002237 :             else if (is_invalid_string_op(operation,branch))
   32000             :             {
   32001           0 :                parser_->set_error(parser_error::make_error(
   32002             :                   parser_error::e_syntax,
   32003           0 :                   parser_->current_state().token,
   32004             :                   "ERR242 - Invalid branch pair for string operator '" + details::to_str(operation) + "'",
   32005             :                   exprtk_error_location));
   32006             : 
   32007           0 :                return error_node();
   32008             :             }
   32009     3002237 :             else if (is_invalid_assignment_op(operation,branch))
   32010             :             {
   32011           9 :                parser_->set_error(parser_error::make_error(
   32012             :                   parser_error::e_syntax,
   32013           6 :                   parser_->current_state().token,
   32014             :                   "ERR243 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'",
   32015             :                   exprtk_error_location));
   32016             : 
   32017           3 :                return error_node();
   32018             :             }
   32019     3002234 :             else if (is_invalid_break_continue_op(branch))
   32020             :             {
   32021           0 :                parser_->set_error(parser_error::make_error(
   32022             :                   parser_error::e_syntax,
   32023           0 :                   parser_->current_state().token,
   32024             :                   "ERR244 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'",
   32025             :                   exprtk_error_location));
   32026             : 
   32027           0 :                return error_node();
   32028             :             }
   32029     3002234 :             else if (details::e_assign == operation)
   32030             :             {
   32031       64826 :                return synthesize_assignment_expression(operation, branch);
   32032             :             }
   32033     2937408 :             else if (details::e_swap == operation)
   32034             :             {
   32035        2728 :                return synthesize_swap_expression(branch);
   32036             :             }
   32037     2934680 :             else if (is_assignment_operation(operation))
   32038             :             {
   32039       11856 :                return synthesize_assignment_operation_expression(operation, branch);
   32040             :             }
   32041     2922824 :             else if (is_vector_eqineq_logic_operation(operation, branch))
   32042             :             {
   32043        6457 :                return synthesize_veceqineqlogic_operation_expression(operation, branch);
   32044             :             }
   32045     2916367 :             else if (is_vector_arithmetic_operation(operation, branch))
   32046             :             {
   32047       12299 :                return synthesize_vecarithmetic_operation_expression(operation, branch);
   32048             :             }
   32049     2904068 :             else if (is_shortcircuit_expression(operation))
   32050             :             {
   32051         856 :                return synthesize_shortcircuit_expression(operation, branch);
   32052             :             }
   32053     2903212 :             else if (is_string_operation(operation, branch))
   32054             :             {
   32055       45322 :                return synthesize_string_expression(operation, branch);
   32056             :             }
   32057     2857890 :             else if (is_null_present(branch))
   32058             :             {
   32059         255 :                return synthesize_null_expression(operation, branch);
   32060             :             }
   32061             :             #ifndef exprtk_disable_cardinal_pow_optimisation
   32062     2857635 :             else if (is_constpow_operation(operation, branch))
   32063             :             {
   32064           1 :                return cardinal_pow_optimisation(branch);
   32065             :             }
   32066             :             #endif
   32067             : 
   32068     2857634 :             expression_node_ptr result = error_node();
   32069             : 
   32070             :             #ifndef exprtk_disable_enhanced_features
   32071     2857634 :             if (synthesize_expression(operation, branch, result))
   32072             :             {
   32073     1313530 :                return result;
   32074             :             }
   32075             :             else
   32076             :             #endif
   32077             : 
   32078             :             {
   32079             :                /*
   32080             :                   Possible reductions:
   32081             :                   1. c o cob -> cob
   32082             :                   2. cob o c -> cob
   32083             :                   3. c o boc -> boc
   32084             :                   4. boc o c -> boc
   32085             :                */
   32086     1544104 :                result = error_node();
   32087             : 
   32088     1544104 :                if (cocob_optimisable(operation, branch))
   32089             :                {
   32090        7958 :                   result = synthesize_cocob_expression::process((*this), operation, branch);
   32091             :                }
   32092     1536146 :                else if (coboc_optimisable(operation, branch) && (0 == result))
   32093             :                {
   32094       24432 :                   result = synthesize_coboc_expression::process((*this), operation, branch);
   32095             :                }
   32096             : 
   32097     1544104 :                if (result)
   32098       27302 :                   return result;
   32099             :             }
   32100             : 
   32101     1516802 :             if (uvouv_optimisable(operation, branch))
   32102             :             {
   32103         900 :                return synthesize_uvouv_expression(operation, branch);
   32104             :             }
   32105     1515902 :             else if (vob_optimisable(operation, branch))
   32106             :             {
   32107       52659 :                return synthesize_vob_expression::process((*this), operation, branch);
   32108             :             }
   32109     1463243 :             else if (bov_optimisable(operation, branch))
   32110             :             {
   32111      361546 :                return synthesize_bov_expression::process((*this), operation, branch);
   32112             :             }
   32113     1101697 :             else if (cob_optimisable(operation, branch))
   32114             :             {
   32115       99132 :                return synthesize_cob_expression::process((*this), operation, branch);
   32116             :             }
   32117     1002565 :             else if (boc_optimisable(operation, branch))
   32118             :             {
   32119      147008 :                return synthesize_boc_expression::process((*this), operation, branch);
   32120             :             }
   32121             :             #ifndef exprtk_disable_enhanced_features
   32122      855557 :             else if (cov_optimisable(operation, branch))
   32123             :             {
   32124           0 :                return synthesize_cov_expression::process((*this), operation, branch);
   32125             :             }
   32126             :             #endif
   32127      855557 :             else if (binext_optimisable(operation, branch))
   32128             :             {
   32129      407007 :                return synthesize_binary_ext_expression::process((*this), operation, branch);
   32130             :             }
   32131             :             else
   32132      448550 :                return synthesize_expression<binary_node_t,2>(operation, branch);
   32133             :          }
   32134             : 
   32135         471 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
   32136             :          {
   32137         471 :             if (
   32138         471 :                  (0 == branch[0]) ||
   32139         471 :                  (0 == branch[1]) ||
   32140         471 :                  (0 == branch[2])
   32141             :                )
   32142             :             {
   32143           0 :                details::free_all_nodes(*node_allocator_,branch);
   32144             : 
   32145           0 :                parser_->set_error(parser_error::make_error(
   32146             :                   parser_error::e_syntax,
   32147           0 :                   parser_->current_state().token,
   32148             :                   "ERR245 - Invalid branches operator '" + details::to_str(operation) + "'",
   32149             :                   exprtk_error_location));
   32150             : 
   32151           0 :                return error_node();
   32152             :             }
   32153         471 :             else if (is_invalid_string_op(operation, branch))
   32154             :             {
   32155           0 :                parser_->set_error(parser_error::make_error(
   32156             :                   parser_error::e_syntax,
   32157           0 :                   parser_->current_state().token,
   32158             :                   "ERR246 - Invalid branches for string operator '" + details::to_str(operation) + "'",
   32159             :                   exprtk_error_location));
   32160             : 
   32161           0 :                return error_node();
   32162             :             }
   32163         471 :             else if (is_string_operation(operation, branch))
   32164             :             {
   32165         355 :                return synthesize_string_expression(operation, branch);
   32166             :             }
   32167             :             else
   32168         116 :                return synthesize_expression<trinary_node_t,3>(operation, branch);
   32169             :          }
   32170             : 
   32171           0 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
   32172             :          {
   32173           0 :             return synthesize_expression<quaternary_node_t,4>(operation,branch);
   32174             :          }
   32175             : 
   32176      101383 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
   32177             :          {
   32178      101383 :             expression_node_ptr branch[1] = { b0 };
   32179      202766 :             return (*this)(operation,branch);
   32180             :          }
   32181             : 
   32182     2682458 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
   32183             :          {
   32184     2682458 :             expression_node_ptr result = error_node();
   32185             : 
   32186     2682458 :             if ((0 != b0) && (0 != b1))
   32187             :             {
   32188     2682458 :                expression_node_ptr branch[2] = { b0, b1 };
   32189     2682458 :                result = expression_generator<Type>::operator()(operation, branch);
   32190     2682458 :                b0 = branch[0];
   32191     2682458 :                b1 = branch[1];
   32192             :             }
   32193             : 
   32194     2682458 :             return result;
   32195             :          }
   32196             : 
   32197        5634 :          inline expression_node_ptr conditional(expression_node_ptr condition,
   32198             :                                                 expression_node_ptr consequent,
   32199             :                                                 expression_node_ptr alternative) const
   32200             :          {
   32201        5634 :             if ((0 == condition) || (0 == consequent))
   32202             :             {
   32203           0 :                details::free_node(*node_allocator_, condition  );
   32204           0 :                details::free_node(*node_allocator_, consequent );
   32205           0 :                details::free_node(*node_allocator_, alternative);
   32206             : 
   32207           0 :                const std::string invalid_branches =
   32208           0 :                                  ((0 == condition ) ? std::string("condition ") : "") +
   32209           0 :                                  ((0 == consequent) ? std::string("consequent") : "") ;
   32210             : 
   32211           0 :                parser_->set_error(parser_error::make_error(
   32212             :                   parser_error::e_parser,
   32213           0 :                   parser_->current_state().token,
   32214             :                   "ERR247 - Invalid " + invalid_branches + " for conditional statement",
   32215             :                   exprtk_error_location));
   32216             : 
   32217           0 :                return error_node();
   32218           0 :             }
   32219             :             // Can the condition be immediately evaluated? if so optimise.
   32220        5634 :             else if (details::is_constant_node(condition))
   32221             :             {
   32222             :                // True branch
   32223        1756 :                if (details::is_true(condition))
   32224             :                {
   32225        1126 :                   details::free_node(*node_allocator_, condition  );
   32226        1126 :                   details::free_node(*node_allocator_, alternative);
   32227             : 
   32228        1126 :                   return consequent;
   32229             :                }
   32230             :                // False branch
   32231             :                else
   32232             :                {
   32233         630 :                   details::free_node(*node_allocator_, condition );
   32234         630 :                   details::free_node(*node_allocator_, consequent);
   32235             : 
   32236         630 :                   if (alternative)
   32237         570 :                      return alternative;
   32238             :                   else
   32239          60 :                      return node_allocator_->allocate<details::null_node<T> >();
   32240             :                }
   32241             :             }
   32242             : 
   32243        3878 :             expression_node_ptr result = error_node();
   32244        3878 :             std::string node_name      = "Unknown!";
   32245             : 
   32246        3878 :             if ((0 != consequent) && (0 != alternative))
   32247             :             {
   32248        2847 :                result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative);
   32249        2847 :                node_name = "conditional_node_t";
   32250             :             }
   32251             :             else
   32252             :             {
   32253        1031 :                result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent);
   32254        1031 :                node_name = "cons_conditional_node_t";
   32255             :             }
   32256             : 
   32257        3878 :             if (result && result->valid())
   32258             :             {
   32259        3878 :                return result;
   32260             :             }
   32261             : 
   32262           0 :             parser_->set_error(parser_error::make_error(
   32263             :                parser_error::e_parser,
   32264           0 :                token_t(),
   32265             :                "ERR248 - Failed to synthesize node: " + node_name,
   32266             :                exprtk_error_location));
   32267             : 
   32268           0 :             details::free_node(*node_allocator_, result);
   32269           0 :             return error_node();
   32270        3878 :          }
   32271             : 
   32272             :          #ifndef exprtk_disable_string_capabilities
   32273        1151 :          inline expression_node_ptr conditional_string(expression_node_ptr condition,
   32274             :                                                        expression_node_ptr consequent,
   32275             :                                                        expression_node_ptr alternative) const
   32276             :          {
   32277        1151 :             if ((0 == condition) || (0 == consequent))
   32278             :             {
   32279           0 :                details::free_node(*node_allocator_, condition  );
   32280           0 :                details::free_node(*node_allocator_, consequent );
   32281           0 :                details::free_node(*node_allocator_, alternative);
   32282             : 
   32283           0 :                const std::string invalid_branches =
   32284           0 :                                  ((0 == condition ) ? std::string("condition ") : "") +
   32285           0 :                                  ((0 == consequent) ? std::string("consequent") : "") ;
   32286             : 
   32287           0 :                parser_->set_error(parser_error::make_error(
   32288             :                   parser_error::e_parser,
   32289           0 :                   parser_->current_state().token,
   32290             :                   "ERR249 - Invalid " + invalid_branches + " for string conditional statement",
   32291             :                   exprtk_error_location));
   32292             : 
   32293           0 :                return error_node();
   32294           0 :             }
   32295             :             // Can the condition be immediately evaluated? if so optimise.
   32296        1151 :             else if (details::is_constant_node(condition))
   32297             :             {
   32298             :                // True branch
   32299           0 :                if (details::is_true(condition))
   32300             :                {
   32301           0 :                   details::free_node(*node_allocator_, condition  );
   32302           0 :                   details::free_node(*node_allocator_, alternative);
   32303             : 
   32304           0 :                   return consequent;
   32305             :                }
   32306             :                // False branch
   32307             :                else
   32308             :                {
   32309           0 :                   details::free_node(*node_allocator_, condition );
   32310           0 :                   details::free_node(*node_allocator_, consequent);
   32311             : 
   32312           0 :                   if (alternative)
   32313           0 :                      return alternative;
   32314             :                   else
   32315           0 :                      return node_allocator_->
   32316           0 :                               allocate_c<details::string_literal_node<Type> >("");
   32317             :                }
   32318             :             }
   32319        1151 :             else if ((0 != consequent) && (0 != alternative))
   32320             :             {
   32321        1151 :                expression_node_ptr result =
   32322        1151 :                   node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative);
   32323             : 
   32324        1151 :                if (result && result->valid())
   32325             :                {
   32326        1151 :                   return result;
   32327             :                }
   32328             : 
   32329           0 :                parser_->set_error(parser_error::make_error(
   32330             :                   parser_error::e_parser,
   32331           0 :                   token_t(),
   32332             :                   "ERR250 - Failed to synthesize node: conditional_string_node_t",
   32333             :                   exprtk_error_location));
   32334             : 
   32335           0 :                details::free_node(*node_allocator_, result);
   32336             :             }
   32337             : 
   32338           0 :             return error_node();
   32339             :          }
   32340             :          #else
   32341             :          inline expression_node_ptr conditional_string(expression_node_ptr,
   32342             :                                                        expression_node_ptr,
   32343             :                                                        expression_node_ptr) const
   32344             :          {
   32345             :             return error_node();
   32346             :          }
   32347             :          #endif
   32348             : 
   32349        1773 :          inline expression_node_ptr conditional_vector(expression_node_ptr condition,
   32350             :                                                        expression_node_ptr consequent,
   32351             :                                                        expression_node_ptr alternative) const
   32352             :          {
   32353        1773 :             if ((0 == condition) || (0 == consequent))
   32354             :             {
   32355           0 :                details::free_node(*node_allocator_, condition  );
   32356           0 :                details::free_node(*node_allocator_, consequent );
   32357           0 :                details::free_node(*node_allocator_, alternative);
   32358             : 
   32359           0 :                const std::string invalid_branches =
   32360           0 :                                  ((0 == condition ) ? std::string("condition ") : "") +
   32361           0 :                                  ((0 == consequent) ? std::string("consequent") : "") ;
   32362             : 
   32363           0 :                parser_->set_error(parser_error::make_error(
   32364             :                   parser_error::e_parser,
   32365           0 :                   parser_->current_state().token,
   32366             :                   "ERR251 - Invalid " + invalid_branches + " for vector conditional statement",
   32367             :                   exprtk_error_location));
   32368             : 
   32369           0 :                return error_node();
   32370           0 :             }
   32371             :             // Can the condition be immediately evaluated? if so optimise.
   32372        1773 :             else if (details::is_constant_node(condition))
   32373             :             {
   32374             :                // True branch
   32375         880 :                if (details::is_true(condition))
   32376             :                {
   32377         440 :                   details::free_node(*node_allocator_, condition  );
   32378         440 :                   details::free_node(*node_allocator_, alternative);
   32379             : 
   32380         440 :                   return consequent;
   32381             :                }
   32382             :                // False branch
   32383             :                else
   32384             :                {
   32385         440 :                   details::free_node(*node_allocator_, condition );
   32386         440 :                   details::free_node(*node_allocator_, consequent);
   32387             : 
   32388         440 :                   if (alternative)
   32389         440 :                      return alternative;
   32390             :                   else
   32391           0 :                      return node_allocator_->allocate<details::null_node<T> >();
   32392             : 
   32393             :                }
   32394             :             }
   32395         893 :             else if ((0 != consequent) && (0 != alternative))
   32396             :             {
   32397         893 :                return node_allocator_->
   32398         893 :                         allocate<conditional_vector_node_t>(condition, consequent, alternative);
   32399             :             }
   32400             :             else
   32401           0 :                return error_node();
   32402             :          }
   32403             : 
   32404        2747 :          inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
   32405             :          {
   32406        2747 :             if (
   32407        2747 :                  parser_->loop_runtime_check_ &&
   32408           0 :                  (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type))
   32409             :                )
   32410             :             {
   32411           0 :                return parser_->loop_runtime_check_;
   32412             :             }
   32413             : 
   32414        2747 :             return loop_runtime_check_ptr(0);
   32415             :          }
   32416             : 
   32417        6903 :          inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const
   32418             :          {
   32419        6903 :             return parser_->vector_access_runtime_check_;
   32420             :          }
   32421             : 
   32422          22 :          inline expression_node_ptr while_loop(expression_node_ptr& condition,
   32423             :                                                expression_node_ptr& branch,
   32424             :                                                const bool break_continue_present = false) const
   32425             :          {
   32426          22 :             if (
   32427          34 :                  !break_continue_present              &&
   32428          34 :                  !parser_->state_.return_stmt_present &&
   32429          12 :                  details::is_constant_node(condition)
   32430             :                )
   32431             :             {
   32432           0 :                expression_node_ptr result = error_node();
   32433           0 :                if (details::is_true(condition))
   32434             :                {
   32435             :                   // Infinite loops are not allowed.
   32436             : 
   32437           0 :                   parser_->set_error(parser_error::make_error(
   32438             :                      parser_error::e_parser,
   32439           0 :                      parser_->current_state().token,
   32440             :                      "ERR252 - Infinite loop condition without 'break' or 'return' not allowed in while-loops",
   32441             :                      exprtk_error_location));
   32442             : 
   32443           0 :                   result = error_node();
   32444             :                }
   32445             :                else
   32446           0 :                   result = node_allocator_->allocate<details::null_node<Type> >();
   32447             : 
   32448           0 :                details::free_node(*node_allocator_, condition);
   32449           0 :                details::free_node(*node_allocator_, branch   );
   32450             : 
   32451           0 :                return result;
   32452             :             }
   32453          22 :             else if (details::is_null_node(condition))
   32454             :             {
   32455           0 :                details::free_node(*node_allocator_,condition);
   32456             : 
   32457           0 :                return branch;
   32458             :             }
   32459             : 
   32460          22 :             loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop);
   32461             : 
   32462          22 :             if (!break_continue_present)
   32463             :             {
   32464          12 :                if (rtc)
   32465           0 :                   return node_allocator_->allocate<while_loop_rtc_node_t>
   32466           0 :                            (condition, branch,  rtc);
   32467             :                else
   32468          12 :                   return node_allocator_->allocate<while_loop_node_t>
   32469          12 :                            (condition, branch);
   32470             :             }
   32471             :             #ifndef exprtk_disable_break_continue
   32472             :             else
   32473             :             {
   32474          10 :                if (rtc)
   32475           0 :                   return node_allocator_->allocate<while_loop_bc_rtc_node_t>
   32476           0 :                            (condition, branch, rtc);
   32477             :                else
   32478          10 :                   return node_allocator_->allocate<while_loop_bc_node_t>
   32479          10 :                            (condition, branch);
   32480             :             }
   32481             :             #else
   32482             :                return error_node();
   32483             :             #endif
   32484             :          }
   32485             : 
   32486          82 :          inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
   32487             :                                                       expression_node_ptr& branch,
   32488             :                                                       const bool break_continue_present = false) const
   32489             :          {
   32490          82 :             if (!break_continue_present && details::is_constant_node(condition))
   32491             :             {
   32492          80 :                if (
   32493         160 :                     details::is_true(condition) &&
   32494          80 :                     details::is_constant_node(branch)
   32495             :                   )
   32496             :                {
   32497          80 :                   free_node(*node_allocator_,condition);
   32498             : 
   32499          80 :                   return branch;
   32500             :                }
   32501             : 
   32502           0 :                details::free_node(*node_allocator_, condition);
   32503           0 :                details::free_node(*node_allocator_, branch   );
   32504             : 
   32505           0 :                return error_node();
   32506             :             }
   32507           2 :             else if (details::is_null_node(condition))
   32508             :             {
   32509           0 :                details::free_node(*node_allocator_,condition);
   32510             : 
   32511           0 :                return branch;
   32512             :             }
   32513             : 
   32514           2 :             loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop);
   32515             : 
   32516           2 :             if (!break_continue_present)
   32517             :             {
   32518           1 :                if (rtc)
   32519           0 :                   return node_allocator_->allocate<repeat_until_loop_rtc_node_t>
   32520           0 :                            (condition, branch,  rtc);
   32521             :                else
   32522           1 :                   return node_allocator_->allocate<repeat_until_loop_node_t>
   32523           1 :                            (condition, branch);
   32524             :             }
   32525             :             #ifndef exprtk_disable_break_continue
   32526             :             else
   32527             :             {
   32528           1 :                if (rtc)
   32529           0 :                   return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t>
   32530           0 :                            (condition, branch, rtc);
   32531             :                else
   32532           1 :                   return node_allocator_->allocate<repeat_until_loop_bc_node_t>
   32533           1 :                            (condition, branch);
   32534             :             }
   32535             :             #else
   32536             :                return error_node();
   32537             :             #endif
   32538             :          }
   32539             : 
   32540        2723 :          inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
   32541             :                                              expression_node_ptr& condition,
   32542             :                                              expression_node_ptr& incrementor,
   32543             :                                              expression_node_ptr& loop_body,
   32544             :                                              bool break_continue_present = false) const
   32545             :          {
   32546        2723 :             if (
   32547        4834 :                  !break_continue_present              &&
   32548        4827 :                  !parser_->state_.return_stmt_present &&
   32549        2104 :                  details::is_constant_node(condition)
   32550             :                )
   32551             :             {
   32552           0 :                expression_node_ptr result = error_node();
   32553             : 
   32554           0 :                if (details::is_true(condition))
   32555             :                {
   32556             :                   // Infinite loops are not allowed.
   32557             : 
   32558           0 :                   parser_->set_error(parser_error::make_error(
   32559             :                      parser_error::e_parser,
   32560           0 :                      parser_->current_state().token,
   32561             :                      "ERR253 - Infinite loop condition without 'break' or 'return' not allowed in for-loop",
   32562             :                      exprtk_error_location));
   32563             : 
   32564           0 :                   result = error_node();
   32565             :                }
   32566             :                else
   32567           0 :                   result = node_allocator_->allocate<details::null_node<Type> >();
   32568             : 
   32569           0 :                details::free_node(*node_allocator_, initialiser);
   32570           0 :                details::free_node(*node_allocator_, condition  );
   32571           0 :                details::free_node(*node_allocator_, incrementor);
   32572           0 :                details::free_node(*node_allocator_, loop_body  );
   32573             : 
   32574           0 :                return result;
   32575             :             }
   32576        2723 :             else if (details::is_null_node(condition) || (0 == condition))
   32577             :             {
   32578           0 :                details::free_node(*node_allocator_, initialiser);
   32579           0 :                details::free_node(*node_allocator_, condition  );
   32580           0 :                details::free_node(*node_allocator_, incrementor);
   32581             : 
   32582           0 :                return loop_body;
   32583             :             }
   32584             : 
   32585        2723 :             loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop);
   32586             : 
   32587        2723 :             if (!break_continue_present)
   32588             :             {
   32589        2111 :                if (rtc)
   32590           0 :                   return node_allocator_->allocate<for_loop_rtc_node_t>
   32591           0 :                                           (
   32592             :                                              initialiser,
   32593             :                                              condition,
   32594             :                                              incrementor,
   32595             :                                              loop_body,
   32596             :                                              rtc
   32597           0 :                                           );
   32598             :                else
   32599        2111 :                   return node_allocator_->allocate<for_loop_node_t>
   32600        2111 :                                           (
   32601             :                                              initialiser,
   32602             :                                              condition,
   32603             :                                              incrementor,
   32604             :                                              loop_body
   32605        2111 :                                           );
   32606             :             }
   32607             :             #ifndef exprtk_disable_break_continue
   32608             :             else
   32609             :             {
   32610         612 :                if (rtc)
   32611           0 :                   return node_allocator_->allocate<for_loop_bc_rtc_node_t>
   32612           0 :                                           (
   32613             :                                              initialiser,
   32614             :                                              condition,
   32615             :                                              incrementor,
   32616             :                                              loop_body,
   32617             :                                              rtc
   32618           0 :                                           );
   32619             :                else
   32620         612 :                   return node_allocator_->allocate<for_loop_bc_node_t>
   32621         612 :                                           (
   32622             :                                              initialiser,
   32623             :                                              condition,
   32624             :                                              incrementor,
   32625             :                                              loop_body
   32626         612 :                                           );
   32627             :             }
   32628             :             #else
   32629             :                return error_node();
   32630             :             #endif
   32631             :          }
   32632             : 
   32633             :          template <typename Allocator,
   32634             :                    template <typename, typename> class Sequence>
   32635         190 :          inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
   32636             :          {
   32637         190 :             expression_node_ptr result = error_node();
   32638             : 
   32639         190 :             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
   32640             :             {
   32641         180 :                expression_node_ptr condition  = arg_list[(2 * i)    ];
   32642         180 :                expression_node_ptr consequent = arg_list[(2 * i) + 1];
   32643             : 
   32644         180 :                if ((0 == result) && details::is_true(condition))
   32645             :                {
   32646         180 :                   result = consequent;
   32647         180 :                   break;
   32648             :                }
   32649             :             }
   32650             : 
   32651         190 :             if (0 == result)
   32652             :             {
   32653          10 :                result = arg_list.back();
   32654             :             }
   32655             : 
   32656         740 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   32657             :             {
   32658         550 :                expression_node_ptr current_expr = arg_list[i];
   32659             : 
   32660         550 :                if (current_expr && (current_expr != result))
   32661             :                {
   32662         360 :                   free_node(*node_allocator_,current_expr);
   32663             :                }
   32664             :             }
   32665             : 
   32666         190 :             return result;
   32667             :          }
   32668             : 
   32669             :          template <typename Allocator,
   32670             :                    template <typename, typename> class Sequence>
   32671          10 :          inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
   32672             :          {
   32673          10 :             expression_node_ptr result = error_node();
   32674             : 
   32675          50 :             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
   32676             :             {
   32677          40 :                expression_node_ptr condition  = arg_list[(2 * i)    ];
   32678          40 :                expression_node_ptr consequent = arg_list[(2 * i) + 1];
   32679             : 
   32680          40 :                if (details::is_true(condition))
   32681             :                {
   32682          40 :                   result = consequent;
   32683             :                }
   32684             :             }
   32685             : 
   32686          10 :             if (0 == result)
   32687             :             {
   32688           0 :                const T zero = T(0);
   32689           0 :                result       = node_allocator_->allocate<literal_node_t>(zero);
   32690             :             }
   32691             : 
   32692          90 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   32693             :             {
   32694          80 :                expression_node_ptr& current_expr = arg_list[i];
   32695             : 
   32696          80 :                if (current_expr && (current_expr != result))
   32697             :                {
   32698          70 :                   details::free_node(*node_allocator_,current_expr);
   32699             :                }
   32700             :             }
   32701             : 
   32702          10 :             return result;
   32703             :          }
   32704             : 
   32705             :          struct switch_nodes
   32706             :          {
   32707             :             typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t;
   32708             : 
   32709             :             #define case_stmt(N)                                                         \
   32710             :             if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
   32711             : 
   32712             :             struct switch_impl_1
   32713             :             {
   32714         740 :                static inline T process(const arg_list_t& arg)
   32715             :                {
   32716         740 :                   case_stmt(0)
   32717             : 
   32718          10 :                   assert(arg.size() == ((2 * 1) + 1));
   32719             : 
   32720          10 :                   return arg.back().first->value();
   32721             :                }
   32722             :             };
   32723             : 
   32724             :             struct switch_impl_2
   32725             :             {
   32726    11458441 :                static inline T process(const arg_list_t& arg)
   32727             :                {
   32728    11458441 :                   case_stmt(0) case_stmt(1)
   32729             : 
   32730     5755024 :                   assert(arg.size() == ((2 * 2) + 1));
   32731             : 
   32732     5755024 :                   return arg.back().first->value();
   32733             :                }
   32734             :             };
   32735             : 
   32736             :             struct switch_impl_3
   32737             :             {
   32738         100 :                static inline T process(const arg_list_t& arg)
   32739             :                {
   32740         100 :                   case_stmt(0) case_stmt(1)
   32741          99 :                   case_stmt(2)
   32742             : 
   32743          98 :                   assert(arg.size() == ((2 * 3) + 1));
   32744             : 
   32745          98 :                   return arg.back().first->value();
   32746             :                }
   32747             :             };
   32748             : 
   32749             :             struct switch_impl_4
   32750             :             {
   32751           0 :                static inline T process(const arg_list_t& arg)
   32752             :                {
   32753           0 :                   case_stmt(0) case_stmt(1)
   32754           0 :                   case_stmt(2) case_stmt(3)
   32755             : 
   32756           0 :                   assert(arg.size() == ((2 * 4) + 1));
   32757             : 
   32758           0 :                   return arg.back().first->value();
   32759             :                }
   32760             :             };
   32761             : 
   32762             :             struct switch_impl_5
   32763             :             {
   32764           0 :                static inline T process(const arg_list_t& arg)
   32765             :                {
   32766           0 :                   case_stmt(0) case_stmt(1)
   32767           0 :                   case_stmt(2) case_stmt(3)
   32768           0 :                   case_stmt(4)
   32769             : 
   32770           0 :                   assert(arg.size() == ((2 * 5) + 1));
   32771             : 
   32772           0 :                   return arg.back().first->value();
   32773             :                }
   32774             :             };
   32775             : 
   32776             :             struct switch_impl_6
   32777             :             {
   32778         136 :                static inline T process(const arg_list_t& arg)
   32779             :                {
   32780         136 :                   case_stmt(0) case_stmt(1)
   32781         135 :                   case_stmt(2) case_stmt(3)
   32782         133 :                   case_stmt(4) case_stmt(5)
   32783             : 
   32784         132 :                   assert(arg.size() == ((2 * 6) + 1));
   32785             : 
   32786         132 :                   return arg.back().first->value();
   32787             :                }
   32788             :             };
   32789             : 
   32790             :             struct switch_impl_7
   32791             :             {
   32792           0 :                static inline T process(const arg_list_t& arg)
   32793             :                {
   32794           0 :                   case_stmt(0) case_stmt(1)
   32795           0 :                   case_stmt(2) case_stmt(3)
   32796           0 :                   case_stmt(4) case_stmt(5)
   32797           0 :                   case_stmt(6)
   32798             : 
   32799           0 :                   assert(arg.size() == ((2 * 7) + 1));
   32800             : 
   32801           0 :                   return arg.back().first->value();
   32802             :                }
   32803             :             };
   32804             : 
   32805             :             #undef case_stmt
   32806             :          };
   32807             : 
   32808             :          template <typename Allocator,
   32809             :                    template <typename, typename> class Sequence>
   32810        1195 :          inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present)
   32811             :          {
   32812        1195 :             if (arg_list.empty())
   32813           0 :                return error_node();
   32814        1195 :             else if (
   32815        2390 :                       !all_nodes_valid(arg_list) ||
   32816        1195 :                       (!default_statement_present && (arg_list.size() < 2))
   32817             :                     )
   32818             :             {
   32819           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32820             : 
   32821           0 :                return error_node();
   32822             :             }
   32823        1195 :             else if (is_constant_foldable(arg_list))
   32824         190 :                return const_optimise_switch(arg_list);
   32825             : 
   32826        1005 :             switch ((arg_list.size() - 1) / 2)
   32827             :             {
   32828             :                #define case_stmt(N)                                                       \
   32829             :                case N :                                                                   \
   32830             :                   return node_allocator_->                                                \
   32831             :                             allocate<details::switch_n_node                               \
   32832             :                               <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \
   32833             : 
   32834         740 :                case_stmt(1)
   32835         263 :                case_stmt(2)
   32836           1 :                case_stmt(3)
   32837           0 :                case_stmt(4)
   32838           0 :                case_stmt(5)
   32839           1 :                case_stmt(6)
   32840           0 :                case_stmt(7)
   32841             :                #undef case_stmt
   32842             : 
   32843           0 :                default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
   32844             :             }
   32845             :          }
   32846             : 
   32847             :          template <typename Allocator,
   32848             :                    template <typename, typename> class Sequence>
   32849         190 :          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
   32850             :          {
   32851         190 :             if (!all_nodes_valid(arg_list))
   32852             :             {
   32853           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32854             : 
   32855           0 :                return error_node();
   32856             :             }
   32857         190 :             else if (is_constant_foldable(arg_list))
   32858          10 :                return const_optimise_mswitch(arg_list);
   32859             :             else
   32860         180 :                return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
   32861             :          }
   32862             : 
   32863          84 :          inline expression_node_ptr assert_call(expression_node_ptr& assert_condition,
   32864             :                                                 expression_node_ptr& assert_message,
   32865             :                                                 const assert_check::assert_context& context)
   32866             :          {
   32867             :             typedef details::assert_node<Type> alloc_type;
   32868             : 
   32869         168 :             expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type>
   32870          84 :                (assert_condition, assert_message, parser_->assert_check_, context);
   32871             : 
   32872          84 :             if (result && result->valid())
   32873             :             {
   32874         168 :                parser_->state_.activate_side_effect("assert_call()");
   32875          84 :                return result;
   32876             :             }
   32877             : 
   32878           0 :             details::free_node(*node_allocator_, result          );
   32879           0 :             details::free_node(*node_allocator_, assert_condition);
   32880           0 :             details::free_node(*node_allocator_, assert_message  );
   32881             : 
   32882           0 :             return error_node();
   32883             :          }
   32884             : 
   32885             :          #define unary_opr_switch_statements             \
   32886             :          case_stmt(details::e_abs   , details::abs_op  ) \
   32887             :          case_stmt(details::e_acos  , details::acos_op ) \
   32888             :          case_stmt(details::e_acosh , details::acosh_op) \
   32889             :          case_stmt(details::e_asin  , details::asin_op ) \
   32890             :          case_stmt(details::e_asinh , details::asinh_op) \
   32891             :          case_stmt(details::e_atan  , details::atan_op ) \
   32892             :          case_stmt(details::e_atanh , details::atanh_op) \
   32893             :          case_stmt(details::e_ceil  , details::ceil_op ) \
   32894             :          case_stmt(details::e_cos   , details::cos_op  ) \
   32895             :          case_stmt(details::e_cosh  , details::cosh_op ) \
   32896             :          case_stmt(details::e_exp   , details::exp_op  ) \
   32897             :          case_stmt(details::e_expm1 , details::expm1_op) \
   32898             :          case_stmt(details::e_floor , details::floor_op) \
   32899             :          case_stmt(details::e_log   , details::log_op  ) \
   32900             :          case_stmt(details::e_log10 , details::log10_op) \
   32901             :          case_stmt(details::e_log2  , details::log2_op ) \
   32902             :          case_stmt(details::e_log1p , details::log1p_op) \
   32903             :          case_stmt(details::e_neg   , details::neg_op  ) \
   32904             :          case_stmt(details::e_pos   , details::pos_op  ) \
   32905             :          case_stmt(details::e_round , details::round_op) \
   32906             :          case_stmt(details::e_sin   , details::sin_op  ) \
   32907             :          case_stmt(details::e_sinc  , details::sinc_op ) \
   32908             :          case_stmt(details::e_sinh  , details::sinh_op ) \
   32909             :          case_stmt(details::e_sqrt  , details::sqrt_op ) \
   32910             :          case_stmt(details::e_tan   , details::tan_op  ) \
   32911             :          case_stmt(details::e_tanh  , details::tanh_op ) \
   32912             :          case_stmt(details::e_cot   , details::cot_op  ) \
   32913             :          case_stmt(details::e_sec   , details::sec_op  ) \
   32914             :          case_stmt(details::e_csc   , details::csc_op  ) \
   32915             :          case_stmt(details::e_r2d   , details::r2d_op  ) \
   32916             :          case_stmt(details::e_d2r   , details::d2r_op  ) \
   32917             :          case_stmt(details::e_d2g   , details::d2g_op  ) \
   32918             :          case_stmt(details::e_g2d   , details::g2d_op  ) \
   32919             :          case_stmt(details::e_notl  , details::notl_op ) \
   32920             :          case_stmt(details::e_sgn   , details::sgn_op  ) \
   32921             :          case_stmt(details::e_erf   , details::erf_op  ) \
   32922             :          case_stmt(details::e_erfc  , details::erfc_op ) \
   32923             :          case_stmt(details::e_ncdf  , details::ncdf_op ) \
   32924             :          case_stmt(details::e_frac  , details::frac_op ) \
   32925             :          case_stmt(details::e_trunc , details::trunc_op) \
   32926             : 
   32927        8332 :          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
   32928             :                                                              expression_node_ptr (&branch)[1])
   32929             :          {
   32930        8332 :             T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
   32931             : 
   32932        8332 :             switch (operation)
   32933             :             {
   32934             :                #define case_stmt(op0, op1)                                                         \
   32935             :                case op0 : return node_allocator_->                                                 \
   32936             :                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
   32937             : 
   32938        8332 :                unary_opr_switch_statements
   32939             :                #undef case_stmt
   32940           0 :                default : return error_node();
   32941             :             }
   32942             :          }
   32943             : 
   32944        2690 :          inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
   32945             :                                                                expression_node_ptr (&branch)[1])
   32946             :          {
   32947        2690 :             switch (operation)
   32948             :             {
   32949             :                #define case_stmt(op0, op1)                                                   \
   32950             :                case op0 : return node_allocator_->                                           \
   32951             :                              allocate<typename details::unary_vector_node<Type,op1<Type> > > \
   32952             :                                 (operation, branch[0]);                                      \
   32953             : 
   32954        2690 :                unary_opr_switch_statements
   32955             :                #undef case_stmt
   32956           0 :                default : return error_node();
   32957             :             }
   32958             :          }
   32959             : 
   32960       59953 :          inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
   32961             :                                                                 expression_node_ptr (&branch)[1])
   32962             :          {
   32963       59953 :             switch (operation)
   32964             :             {
   32965             :                #define case_stmt(op0, op1)                                                               \
   32966             :                case op0 : return node_allocator_->                                                       \
   32967             :                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
   32968             : 
   32969       59953 :                unary_opr_switch_statements
   32970             :                #undef case_stmt
   32971           0 :                default : return error_node();
   32972             :             }
   32973             :          }
   32974             : 
   32975         720 :          inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
   32976             :                                                        expression_node_ptr (&branch)[3])
   32977             :          {
   32978         720 :             expression_node_ptr temp_node = error_node();
   32979             : 
   32980         720 :             switch (operation)
   32981             :             {
   32982             :                #define case_stmt(op)                                                        \
   32983             :                case details::e_sf##op : temp_node = node_allocator_->                       \
   32984             :                              allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
   32985             :                                 (operation, branch);                                        \
   32986             :                              break;                                                         \
   32987             : 
   32988          60 :                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   32989          60 :                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   32990          60 :                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   32991          60 :                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   32992          60 :                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   32993          60 :                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   32994          60 :                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   32995          60 :                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
   32996          60 :                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
   32997          60 :                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
   32998          60 :                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
   32999          60 :                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
   33000             :                #undef case_stmt
   33001           0 :                default : return error_node();
   33002             :             }
   33003             : 
   33004         720 :             assert(temp_node);
   33005             : 
   33006         720 :             const T v = temp_node->value();
   33007             : 
   33008         720 :             details::free_node(*node_allocator_,temp_node);
   33009             : 
   33010         720 :             return node_allocator_->allocate<literal_node_t>(v);
   33011             :          }
   33012             : 
   33013        1200 :          inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
   33014             :          {
   33015             :             typedef details::variable_node<Type>* variable_ptr;
   33016             : 
   33017        1200 :             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
   33018        1200 :             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
   33019        1200 :             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
   33020             : 
   33021        1200 :             switch (operation)
   33022             :             {
   33023             :                #define case_stmt(op)                                                                \
   33024             :                case details::e_sf##op : return node_allocator_->                                    \
   33025             :                              allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
   33026             :                                 (v0, v1, v2);                                                       \
   33027             : 
   33028         100 :                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   33029         100 :                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   33030         100 :                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   33031         100 :                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   33032         100 :                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   33033         100 :                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   33034         100 :                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   33035         100 :                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
   33036         100 :                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
   33037         100 :                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
   33038         100 :                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
   33039         100 :                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
   33040             :                #undef case_stmt
   33041           0 :                default : return error_node();
   33042             :             }
   33043             :          }
   33044             : 
   33045        1920 :          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
   33046             :          {
   33047        1920 :             if (!all_nodes_valid(branch))
   33048           0 :                return error_node();
   33049        1920 :             else if (is_constant_foldable(branch))
   33050         720 :                return const_optimise_sf3(operation,branch);
   33051        1200 :             else if (all_nodes_variables(branch))
   33052        1200 :                return varnode_optimise_sf3(operation,branch);
   33053             :             else
   33054             :             {
   33055           0 :                switch (operation)
   33056             :                {
   33057             :                   #define case_stmt(op)                                                        \
   33058             :                   case details::e_sf##op : return node_allocator_->                            \
   33059             :                                 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
   33060             :                                    (operation, branch);                                        \
   33061             : 
   33062           0 :                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   33063           0 :                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   33064           0 :                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   33065           0 :                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   33066           0 :                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   33067           0 :                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   33068           0 :                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   33069           0 :                   case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
   33070           0 :                   case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
   33071           0 :                   case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
   33072           0 :                   case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
   33073           0 :                   case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
   33074             :                   #undef case_stmt
   33075           0 :                   default : return error_node();
   33076             :                }
   33077             :             }
   33078             :          }
   33079             : 
   33080         815 :          inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
   33081             :          {
   33082         815 :             expression_node_ptr temp_node = error_node();
   33083             : 
   33084         815 :             switch (operation)
   33085             :             {
   33086             :                #define case_stmt(op)                                                                    \
   33087             :                case details::e_sf##op : temp_node = node_allocator_->                                   \
   33088             :                                          allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
   33089             :                                             (operation, branch);                                        \
   33090             :                                         break;                                                          \
   33091             : 
   33092          60 :                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
   33093          60 :                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
   33094          60 :                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
   33095          60 :                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
   33096          60 :                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
   33097          60 :                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
   33098          60 :                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
   33099          60 :                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
   33100          60 :                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
   33101          60 :                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
   33102          60 :                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
   33103          80 :                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
   33104          75 :                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
   33105             :                #undef case_stmt
   33106           0 :                default : return error_node();
   33107             :             }
   33108             : 
   33109         815 :             assert(temp_node);
   33110             : 
   33111         815 :             const T v = temp_node->value();
   33112             : 
   33113         815 :             details::free_node(*node_allocator_,temp_node);
   33114             : 
   33115         815 :             return node_allocator_->allocate<literal_node_t>(v);
   33116             :          }
   33117             : 
   33118        1510 :          inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
   33119             :          {
   33120             :             typedef details::variable_node<Type>* variable_ptr;
   33121             : 
   33122        1510 :             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
   33123        1510 :             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
   33124        1510 :             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
   33125        1510 :             const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
   33126             : 
   33127        1510 :             switch (operation)
   33128             :             {
   33129             :                #define case_stmt(op)                                                                 \
   33130             :                case details::e_sf##op : return node_allocator_->                                     \
   33131             :                              allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
   33132             :                                 (v0, v1, v2, v3);                                                    \
   33133             : 
   33134         100 :                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
   33135         100 :                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
   33136         100 :                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
   33137         100 :                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
   33138         100 :                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
   33139         100 :                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
   33140         100 :                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
   33141         100 :                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
   33142         100 :                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
   33143         100 :                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
   33144         100 :                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
   33145         220 :                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
   33146         190 :                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
   33147             :                #undef case_stmt
   33148           0 :                default : return error_node();
   33149             :             }
   33150             :          }
   33151             : 
   33152        2325 :          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
   33153             :          {
   33154        2325 :             if (!all_nodes_valid(branch))
   33155           0 :                return error_node();
   33156        2325 :             else if (is_constant_foldable(branch))
   33157         815 :                return const_optimise_sf4(operation,branch);
   33158        1510 :             else if (all_nodes_variables(branch))
   33159        1510 :                return varnode_optimise_sf4(operation,branch);
   33160           0 :             switch (operation)
   33161             :             {
   33162             :                #define case_stmt(op)                                                        \
   33163             :                case details::e_sf##op : return node_allocator_->                            \
   33164             :                              allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
   33165             :                                 (operation, branch);                                        \
   33166             : 
   33167           0 :                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
   33168           0 :                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
   33169           0 :                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
   33170           0 :                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
   33171           0 :                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
   33172           0 :                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
   33173           0 :                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
   33174           0 :                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
   33175           0 :                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
   33176           0 :                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
   33177           0 :                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
   33178           0 :                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
   33179           0 :                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
   33180             :                #undef case_stmt
   33181           0 :                default : return error_node();
   33182             :             }
   33183             :          }
   33184             : 
   33185             :          template <typename Allocator,
   33186             :                    template <typename, typename> class Sequence>
   33187        1377 :          inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
   33188             :          {
   33189        1377 :             expression_node_ptr temp_node = error_node();
   33190             : 
   33191        1377 :             switch (operation)
   33192             :             {
   33193             :                #define case_stmt(op0, op1)                                                \
   33194             :                case op0 : temp_node = node_allocator_->                                   \
   33195             :                                          allocate<details::vararg_node<Type,op1<Type> > > \
   33196             :                                             (arg_list);                                   \
   33197             :                           break;                                                          \
   33198             : 
   33199         160 :                case_stmt(details::e_sum   , details::vararg_add_op  )
   33200         160 :                case_stmt(details::e_prod  , details::vararg_mul_op  )
   33201         145 :                case_stmt(details::e_avg   , details::vararg_avg_op  )
   33202         227 :                case_stmt(details::e_min   , details::vararg_min_op  )
   33203         205 :                case_stmt(details::e_max   , details::vararg_max_op  )
   33204         240 :                case_stmt(details::e_mand  , details::vararg_mand_op )
   33205         240 :                case_stmt(details::e_mor   , details::vararg_mor_op  )
   33206           0 :                case_stmt(details::e_multi , details::vararg_multi_op)
   33207             :                #undef case_stmt
   33208           0 :                default : return error_node();
   33209             :             }
   33210             : 
   33211        1377 :             const T v = temp_node->value();
   33212             : 
   33213        1377 :             details::free_node(*node_allocator_,temp_node);
   33214             : 
   33215        1377 :             return node_allocator_->allocate<literal_node_t>(v);
   33216             :          }
   33217             : 
   33218          24 :          inline bool special_one_parameter_vararg(const details::operator_type& operation) const
   33219             :          {
   33220             :             return (
   33221          24 :                      (details::e_sum  == operation) ||
   33222           0 :                      (details::e_prod == operation) ||
   33223           0 :                      (details::e_avg  == operation) ||
   33224          24 :                      (details::e_min  == operation) ||
   33225           0 :                      (details::e_max  == operation)
   33226          24 :                    );
   33227             :          }
   33228             : 
   33229             :          template <typename Allocator,
   33230             :                    template <typename, typename> class Sequence>
   33231        2308 :          inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation,
   33232             :                                                                 Sequence<expression_node_ptr,Allocator>& arg_list)
   33233             :          {
   33234        2308 :             switch (operation)
   33235             :             {
   33236             :                #define case_stmt(op0, op1)                                                  \
   33237             :                case op0 : return node_allocator_->                                          \
   33238             :                              allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
   33239             : 
   33240           1 :                case_stmt(details::e_sum   , details::vararg_add_op  )
   33241           1 :                case_stmt(details::e_prod  , details::vararg_mul_op  )
   33242         101 :                case_stmt(details::e_avg   , details::vararg_avg_op  )
   33243        2071 :                case_stmt(details::e_min   , details::vararg_min_op  )
   33244         101 :                case_stmt(details::e_max   , details::vararg_max_op  )
   33245          16 :                case_stmt(details::e_mand  , details::vararg_mand_op )
   33246          17 :                case_stmt(details::e_mor   , details::vararg_mor_op  )
   33247           0 :                case_stmt(details::e_multi , details::vararg_multi_op)
   33248             :                #undef case_stmt
   33249           0 :                default : return error_node();
   33250             :             }
   33251             :          }
   33252             : 
   33253             :          template <typename Allocator,
   33254             :                    template <typename, typename> class Sequence>
   33255        2401 :          inline expression_node_ptr vectorize_func(const details::operator_type& operation,
   33256             :                                                    Sequence<expression_node_ptr,Allocator>& arg_list)
   33257             :          {
   33258        2401 :             if (1 == arg_list.size())
   33259             :             {
   33260        2401 :                switch (operation)
   33261             :                {
   33262             :                   #define case_stmt(op0, op1)                                                     \
   33263             :                   case op0 : return node_allocator_->                                             \
   33264             :                                 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
   33265             : 
   33266        2016 :                   case_stmt(details::e_sum  , details::vec_add_op)
   33267          60 :                   case_stmt(details::e_prod , details::vec_mul_op)
   33268          91 :                   case_stmt(details::e_avg  , details::vec_avg_op)
   33269         162 :                   case_stmt(details::e_min  , details::vec_min_op)
   33270          72 :                   case_stmt(details::e_max  , details::vec_max_op)
   33271             :                   #undef case_stmt
   33272           0 :                   default : return error_node();
   33273             :                }
   33274             :             }
   33275             :             else
   33276           0 :                return error_node();
   33277             :          }
   33278             : 
   33279             :          template <typename Allocator,
   33280             :                    template <typename, typename> class Sequence>
   33281       49616 :          inline expression_node_ptr vararg_function(const details::operator_type& operation,
   33282             :                                                     Sequence<expression_node_ptr,Allocator>& arg_list)
   33283             :          {
   33284       49616 :             if (!all_nodes_valid(arg_list))
   33285             :             {
   33286           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   33287             : 
   33288           0 :                return error_node();
   33289             :             }
   33290       49616 :             else if (is_constant_foldable(arg_list))
   33291        1377 :                return const_optimise_varargfunc(operation,arg_list);
   33292       48239 :             else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0]))
   33293        2401 :                return vectorize_func(operation,arg_list);
   33294       45838 :             else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation))
   33295          24 :                return arg_list[0];
   33296       45814 :             else if (all_nodes_variables(arg_list))
   33297        2308 :                return varnode_optimise_varargfunc(operation,arg_list);
   33298             : 
   33299             :             #ifndef exprtk_disable_string_capabilities
   33300       43506 :             if (details::e_smulti == operation)
   33301             :             {
   33302         170 :                expression_node_ptr result = node_allocator_->
   33303          85 :                  allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
   33304          85 :                if (result && result->valid())
   33305             :                {
   33306          85 :                   return result;
   33307             :                }
   33308             : 
   33309           0 :                parser_->set_error(parser_error::make_error(
   33310             :                   parser_error::e_synthesis,
   33311           0 :                   token_t(),
   33312             :                   "ERR254 - Failed to synthesize node: str_vararg_node<vararg_multi_op>",
   33313             :                   exprtk_error_location));
   33314             : 
   33315           0 :                details::free_node(*node_allocator_, result);
   33316             :             }
   33317             :             else
   33318             :             #endif
   33319             :             {
   33320       43421 :                expression_node_ptr result = error_node();
   33321             : 
   33322       43421 :                switch (operation)
   33323             :                {
   33324             :                   #define case_stmt(op0, op1)                                               \
   33325             :                   case op0 : result = node_allocator_->                                     \
   33326             :                                 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
   33327             :                              break;                                                         \
   33328             : 
   33329           3 :                   case_stmt(details::e_sum   , details::vararg_add_op  )
   33330           3 :                   case_stmt(details::e_prod  , details::vararg_mul_op  )
   33331           1 :                   case_stmt(details::e_avg   , details::vararg_avg_op  )
   33332        1950 :                   case_stmt(details::e_min   , details::vararg_min_op  )
   33333           1 :                   case_stmt(details::e_max   , details::vararg_max_op  )
   33334           0 :                   case_stmt(details::e_mand  , details::vararg_mand_op )
   33335           0 :                   case_stmt(details::e_mor   , details::vararg_mor_op  )
   33336       41463 :                   case_stmt(details::e_multi , details::vararg_multi_op)
   33337             :                   #undef case_stmt
   33338       43421 :                   default : return error_node();
   33339             :                }
   33340             : 
   33341       43421 :                if (result && result->valid())
   33342             :                {
   33343       43421 :                   return result;
   33344             :                }
   33345             : 
   33346           0 :                parser_->set_error(parser_error::make_error(
   33347             :                   parser_error::e_synthesis,
   33348           0 :                   token_t(),
   33349             :                   "ERR255 - Failed to synthesize node: vararg_node",
   33350             :                   exprtk_error_location));
   33351             : 
   33352           0 :                details::free_node(*node_allocator_, result);
   33353             :             }
   33354             : 
   33355           0 :             return error_node();
   33356             :          }
   33357             : 
   33358             :          template <std::size_t N>
   33359       60380 :          inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
   33360             :          {
   33361             :             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
   33362       60380 :             expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
   33363             : 
   33364       60380 :             if (0 == result)
   33365           0 :                return error_node();
   33366             :             else
   33367             :             {
   33368             :                // Can the function call be completely optimised?
   33369       60380 :                if (details::is_constant_node(result))
   33370         120 :                   return result;
   33371       60260 :                else if (!all_nodes_valid(b))
   33372             :                {
   33373           0 :                   details::free_node(*node_allocator_,result);
   33374           0 :                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
   33375             : 
   33376           0 :                   return error_node();
   33377             :                }
   33378       60260 :                else if (N != f->param_count)
   33379             :                {
   33380           0 :                   details::free_node(*node_allocator_,result);
   33381           0 :                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
   33382             : 
   33383           0 :                   return error_node();
   33384             :                }
   33385             : 
   33386       60260 :                function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result);
   33387             : 
   33388       60260 :                if (!func_node_ptr->init_branches(b))
   33389             :                {
   33390           0 :                   details::free_node(*node_allocator_,result);
   33391           0 :                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
   33392             : 
   33393           0 :                   return error_node();
   33394             :                }
   33395             : 
   33396       60260 :                if (result && result->valid())
   33397             :                {
   33398       60260 :                   return result;
   33399             :                }
   33400             : 
   33401           0 :                parser_->set_error(parser_error::make_error(
   33402             :                   parser_error::e_synthesis,
   33403           0 :                   token_t(),
   33404             :                   "ERR256 - Failed to synthesize node: function_N_node_t",
   33405             :                   exprtk_error_location));
   33406             : 
   33407           0 :                details::free_node(*node_allocator_, result);
   33408           0 :                return error_node();
   33409             :             }
   33410             :          }
   33411             : 
   33412         231 :          inline expression_node_ptr function(ifunction_t* f)
   33413             :          {
   33414             :             typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
   33415         231 :             return node_allocator_->allocate<function_N_node_t>(f);
   33416             :          }
   33417             : 
   33418          49 :          inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
   33419             :                                                          std::vector<expression_node_ptr>& arg_list)
   33420             :          {
   33421          49 :             if (!all_nodes_valid(arg_list))
   33422             :             {
   33423           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   33424             : 
   33425           0 :                return error_node();
   33426             :             }
   33427             : 
   33428             :             typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
   33429             : 
   33430          49 :             expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
   33431             : 
   33432          49 :             if (
   33433          49 :                  !arg_list.empty()        &&
   33434          49 :                  !vaf->has_side_effects() &&
   33435           0 :                  is_constant_foldable(arg_list)
   33436             :                )
   33437             :             {
   33438           0 :                const Type v = result->value();
   33439           0 :                details::free_node(*node_allocator_,result);
   33440           0 :                result = node_allocator_->allocate<literal_node_t>(v);
   33441             :             }
   33442             : 
   33443          98 :             parser_->state_.activate_side_effect("vararg_function_call()");
   33444             : 
   33445          49 :             if (result && result->valid())
   33446             :             {
   33447          49 :                return result;
   33448             :             }
   33449             : 
   33450           0 :             parser_->set_error(parser_error::make_error(
   33451             :                parser_error::e_synthesis,
   33452           0 :                token_t(),
   33453             :                "ERR257 - Failed to synthesize node: vararg_function_node<ivararg_function_t>",
   33454             :                exprtk_error_location));
   33455             : 
   33456           0 :             details::free_node(*node_allocator_, result);
   33457           0 :             return error_node();
   33458             :          }
   33459             : 
   33460        3536 :          inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
   33461             :                                                           std::vector<expression_node_ptr>& arg_list,
   33462             :                                                           const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
   33463             :          {
   33464        3536 :             if (!all_nodes_valid(arg_list))
   33465             :             {
   33466           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   33467           0 :                return error_node();
   33468             :             }
   33469             : 
   33470             :             typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
   33471             :             typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
   33472             : 
   33473        3536 :             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
   33474             : 
   33475        3536 :             expression_node_ptr result = error_node();
   33476        3536 :             std::string node_name = "Unknown";
   33477             : 
   33478        3536 :             if (no_psi == param_seq_index)
   33479             :             {
   33480          57 :                result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
   33481          57 :                node_name = "generic_function_node<igeneric_function_t>";
   33482             :             }
   33483             :             else
   33484             :             {
   33485        3479 :                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
   33486        3479 :                node_name = "multimode_genfunction_node<igeneric_function_t>";
   33487             :             }
   33488             : 
   33489        3536 :             alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
   33490             : 
   33491        3536 :             assert(genfunc_node_ptr);
   33492             : 
   33493        3536 :             if (
   33494        3536 :                  !arg_list.empty()                  &&
   33495        3521 :                  !gf->has_side_effects()            &&
   33496        7057 :                  parser_->state_.type_check_enabled &&
   33497           0 :                  is_constant_foldable(arg_list)
   33498             :                )
   33499             :             {
   33500           0 :                genfunc_node_ptr->init_branches();
   33501             : 
   33502           0 :                const Type v = result->value();
   33503             : 
   33504           0 :                details::free_node(*node_allocator_,result);
   33505             : 
   33506           0 :                return node_allocator_->allocate<literal_node_t>(v);
   33507             :             }
   33508        3536 :             else if (genfunc_node_ptr->init_branches())
   33509             :             {
   33510        3536 :                if (result && result->valid())
   33511             :                {
   33512        7072 :                   parser_->state_.activate_side_effect("generic_function_call()");
   33513        3536 :                   return result;
   33514             :                }
   33515             : 
   33516           0 :                parser_->set_error(parser_error::make_error(
   33517             :                   parser_error::e_synthesis,
   33518           0 :                   token_t(),
   33519             :                   "ERR258 - Failed to synthesize node: " + node_name,
   33520             :                   exprtk_error_location));
   33521             : 
   33522           0 :                details::free_node(*node_allocator_, result);
   33523           0 :                return error_node();
   33524             :             }
   33525             :             else
   33526             :             {
   33527           0 :                details::free_node(*node_allocator_, result);
   33528           0 :                details::free_all_nodes(*node_allocator_, arg_list);
   33529             : 
   33530           0 :                return error_node();
   33531             :             }
   33532        3536 :          }
   33533             : 
   33534             :          #ifndef exprtk_disable_string_capabilities
   33535          72 :          inline expression_node_ptr string_function_call(igeneric_function_t* gf,
   33536             :                                                          std::vector<expression_node_ptr>& arg_list,
   33537             :                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
   33538             :          {
   33539          72 :             if (!all_nodes_valid(arg_list))
   33540             :             {
   33541           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   33542           0 :                return error_node();
   33543             :             }
   33544             : 
   33545             :             typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
   33546             :             typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
   33547             : 
   33548          72 :             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
   33549             : 
   33550          72 :             expression_node_ptr result = error_node();
   33551          72 :             std::string node_name = "Unknown";
   33552             : 
   33553          72 :             if (no_psi == param_seq_index)
   33554             :             {
   33555           0 :                result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
   33556           0 :                node_name = "string_function_node<igeneric_function_t>";
   33557             :             }
   33558             :             else
   33559             :             {
   33560          72 :                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
   33561          72 :                node_name = "multimode_strfunction_node<igeneric_function_t>";
   33562             :             }
   33563             : 
   33564          72 :             alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
   33565             : 
   33566          72 :             assert(strfunc_node_ptr);
   33567             : 
   33568          72 :             if (
   33569          72 :                  !arg_list.empty()       &&
   33570          72 :                  !gf->has_side_effects() &&
   33571           0 :                  is_constant_foldable(arg_list)
   33572             :                )
   33573             :             {
   33574           0 :                strfunc_node_ptr->init_branches();
   33575             : 
   33576           0 :                const Type v = result->value();
   33577             : 
   33578           0 :                details::free_node(*node_allocator_,result);
   33579             : 
   33580           0 :                return node_allocator_->allocate<literal_node_t>(v);
   33581             :             }
   33582          72 :             else if (strfunc_node_ptr->init_branches())
   33583             :             {
   33584          72 :                if (result && result->valid())
   33585             :                {
   33586         144 :                   parser_->state_.activate_side_effect("string_function_call()");
   33587          72 :                   return result;
   33588             :                }
   33589             : 
   33590           0 :                parser_->set_error(parser_error::make_error(
   33591             :                   parser_error::e_synthesis,
   33592           0 :                   token_t(),
   33593             :                   "ERR259 - Failed to synthesize node: " + node_name,
   33594             :                   exprtk_error_location));
   33595             : 
   33596           0 :                details::free_node(*node_allocator_, result);
   33597           0 :                return error_node();
   33598             :             }
   33599             :             else
   33600             :             {
   33601           0 :                details::free_node     (*node_allocator_,result  );
   33602           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   33603             : 
   33604           0 :                return error_node();
   33605             :             }
   33606          72 :          }
   33607             :          #endif
   33608             : 
   33609             :          #ifndef exprtk_disable_return_statement
   33610         116 :          inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
   33611             :          {
   33612         116 :             if (!all_nodes_valid(arg_list))
   33613             :             {
   33614           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   33615           0 :                return error_node();
   33616             :             }
   33617             : 
   33618             :             typedef details::return_node<Type> alloc_type;
   33619             : 
   33620         232 :             expression_node_ptr result = node_allocator_->
   33621         116 :                                             allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
   33622             : 
   33623         116 :             alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
   33624             : 
   33625         116 :             assert(return_node_ptr);
   33626             : 
   33627         116 :             if (return_node_ptr->init_branches())
   33628             :             {
   33629         116 :                if (result && result->valid())
   33630             :                {
   33631         232 :                   parser_->state_.activate_side_effect("return_call()");
   33632         116 :                   return result;
   33633             :                }
   33634             : 
   33635           0 :                parser_->set_error(parser_error::make_error(
   33636             :                   parser_error::e_synthesis,
   33637           0 :                   token_t(),
   33638             :                   "ERR260 - Failed to synthesize node: return_node",
   33639             :                   exprtk_error_location));
   33640             : 
   33641           0 :                details::free_node(*node_allocator_, result);
   33642           0 :                return error_node();
   33643             :             }
   33644             :             else
   33645             :             {
   33646           0 :                details::free_node     (*node_allocator_, result  );
   33647           0 :                details::free_all_nodes(*node_allocator_, arg_list);
   33648             : 
   33649           0 :                return error_node();
   33650             :             }
   33651             :          }
   33652             : 
   33653         111 :          inline expression_node_ptr return_envelope(expression_node_ptr body,
   33654             :                                                     results_context_t* rc,
   33655             :                                                     bool*& return_invoked)
   33656             :          {
   33657             :             typedef details::return_envelope_node<Type> alloc_type;
   33658             : 
   33659         111 :             expression_node_ptr result = node_allocator_->
   33660         111 :                                             allocate_cr<alloc_type>(body,(*rc));
   33661             : 
   33662         111 :             return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
   33663             : 
   33664         111 :             return result;
   33665             :          }
   33666             :          #else
   33667             :          inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
   33668             :          {
   33669             :             return error_node();
   33670             :          }
   33671             : 
   33672             :          inline expression_node_ptr return_envelope(expression_node_ptr,
   33673             :                                                     results_context_t*,
   33674             :                                                     bool*&)
   33675             :          {
   33676             :             return error_node();
   33677             :          }
   33678             :          #endif
   33679             : 
   33680       19542 :          inline expression_node_ptr vector_element(const std::string&  symbol,
   33681             :                                                    vector_holder_ptr   vector_base,
   33682             :                                                    expression_node_ptr vec_node,
   33683             :                                                    expression_node_ptr index)
   33684             :          {
   33685       19542 :             expression_node_ptr result = error_node();
   33686       19542 :             std::string node_name = "Unknown";
   33687             : 
   33688       19542 :             if (details::is_constant_node(index))
   33689             :             {
   33690       14723 :                const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
   33691             : 
   33692       14723 :                details::free_node(*node_allocator_,index);
   33693             : 
   33694       14723 :                if (vec_index >= vector_base->size())
   33695             :                {
   33696           0 :                   parser_->set_error(parser_error::make_error(
   33697             :                      parser_error::e_parser,
   33698           0 :                      token_t(),
   33699             :                      "ERR261 - Index of " + details::to_str(vec_index) + " out of range for "
   33700             :                      "vector '" + symbol + "' of size " + details::to_str(vector_base->size()),
   33701             :                      exprtk_error_location));
   33702             : 
   33703           0 :                   details::free_node(*node_allocator_,vec_node);
   33704             : 
   33705        2084 :                   return error_node();
   33706             :                }
   33707             : 
   33708       14723 :                if (vector_base->rebaseable())
   33709             :                {
   33710        1894 :                   vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
   33711             : 
   33712        1894 :                   result = (rtc) ?
   33713           0 :                      node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
   33714        1894 :                      node_allocator_->allocate<rebasevector_celem_node_t    >(vec_node, vec_index, vector_base     ) ;
   33715             : 
   33716        1894 :                   node_name = (rtc) ?
   33717             :                      "rebasevector_elem_rtc_node_t" :
   33718             :                      "rebasevector_elem_node_t"     ;
   33719             : 
   33720        1894 :                   if (result && result->valid())
   33721             :                   {
   33722        1894 :                      return result;
   33723             :                   }
   33724             : 
   33725           0 :                   parser_->set_error(parser_error::make_error(
   33726             :                      parser_error::e_synthesis,
   33727           0 :                      token_t(),
   33728             :                      "ERR262 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
   33729             :                      exprtk_error_location));
   33730             : 
   33731           0 :                   details::free_node(*node_allocator_, result);
   33732           0 :                   return error_node();
   33733             :                }
   33734       12829 :                else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node))
   33735             :                {
   33736         190 :                   vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
   33737             : 
   33738         190 :                   result = (rtc) ?
   33739           0 :                      node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
   33740         190 :                      node_allocator_->allocate<vector_celem_node_t    >(vec_node, vec_index, vector_base     ) ;
   33741             : 
   33742         190 :                   node_name = (rtc) ?
   33743             :                      "vector_elem_rtc_node_t" :
   33744             :                      "vector_elem_node_t"     ;
   33745             : 
   33746         190 :                   if (result && result->valid())
   33747             :                   {
   33748         190 :                      return result;
   33749             :                   }
   33750             : 
   33751           0 :                   parser_->set_error(parser_error::make_error(
   33752             :                      parser_error::e_synthesis,
   33753           0 :                      token_t(),
   33754             :                      "ERR263 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
   33755             :                      exprtk_error_location));
   33756             : 
   33757           0 :                   details::free_node(*node_allocator_, result);
   33758           0 :                   return error_node();
   33759             :                }
   33760             : 
   33761       12639 :                const scope_element& se = parser_->sem_.get_element(symbol,vec_index);
   33762             : 
   33763       12639 :                if (se.index == vec_index)
   33764             :                {
   33765        1580 :                   result = se.var_node;
   33766        1580 :                   details::free_node(*node_allocator_,vec_node);
   33767             :                }
   33768             :                else
   33769             :                {
   33770       11059 :                   scope_element nse;
   33771       11059 :                   nse.name      = symbol;
   33772       11059 :                   nse.active    = true;
   33773       11059 :                   nse.ref_count = 1;
   33774       11059 :                   nse.type      = scope_element::e_vecelem;
   33775       11059 :                   nse.index     = vec_index;
   33776       11059 :                   nse.depth     = parser_->state_.scope_depth;
   33777       11059 :                   nse.data      = 0;
   33778       11059 :                   nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index]));
   33779             : 
   33780       11059 :                   if (!parser_->sem_.add_element(nse))
   33781             :                   {
   33782           0 :                      parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
   33783             : 
   33784           0 :                      parser_->sem_.free_element(nse);
   33785             : 
   33786           0 :                      result = error_node();
   33787             :                   }
   33788             : 
   33789       11059 :                   details::free_node(*node_allocator_,vec_node);
   33790             : 
   33791             :                   exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str()));
   33792             : 
   33793       22118 :                   parser_->state_.activate_side_effect("vector_element()");
   33794             : 
   33795       11059 :                   result = nse.var_node;
   33796       11059 :                   node_name = "variable_node_t";
   33797       11059 :                }
   33798             :             }
   33799             :             else
   33800             :             {
   33801        4819 :                vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
   33802             : 
   33803        4819 :                if (vector_base->rebaseable())
   33804             :                {
   33805        1016 :                   result = (rtc) ?
   33806           2 :                      node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
   33807        1014 :                      node_allocator_->allocate<rebasevector_elem_node_t    >(vec_node, index, vector_base     ) ;
   33808             : 
   33809        1016 :                   node_name = (rtc) ?
   33810             :                      "rebasevector_elem_rtc_node_t" :
   33811             :                      "rebasevector_elem_node_t"     ;
   33812             :                }
   33813             :                else
   33814             :                {
   33815        3803 :                   result = rtc ?
   33816          92 :                      node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
   33817        3711 :                      node_allocator_->allocate<vector_elem_node_t    >(vec_node, index, vector_base     ) ;
   33818             : 
   33819        3803 :                   node_name = (rtc) ?
   33820             :                      "vector_elem_rtc_node_t" :
   33821             :                      "vector_elem_node_t"     ;
   33822             :                }
   33823             :             }
   33824             : 
   33825       17458 :             if (result && result->valid())
   33826             :             {
   33827       17458 :                return result;
   33828             :             }
   33829             : 
   33830           0 :             parser_->set_error(parser_error::make_error(
   33831             :                parser_error::e_synthesis,
   33832           0 :                token_t(),
   33833             :                "ERR264 - Failed to synthesize node: " + node_name,
   33834             :                exprtk_error_location));
   33835             : 
   33836           0 :             details::free_node(*node_allocator_, result);
   33837           0 :             return error_node();
   33838       19542 :          }
   33839             : 
   33840             :       private:
   33841             : 
   33842             :          template <std::size_t N, typename NodePtr>
   33843      686855 :          inline bool is_constant_foldable(NodePtr (&b)[N]) const
   33844             :          {
   33845     1415881 :             for (std::size_t i = 0; i < N; ++i)
   33846             :             {
   33847     1112548 :                if (0 == b[i])
   33848           0 :                   return false;
   33849     1112548 :                else if (!details::is_constant_node(b[i]))
   33850      383522 :                   return false;
   33851             :             }
   33852             : 
   33853      303333 :             return true;
   33854             :          }
   33855             : 
   33856             :          template <typename NodePtr,
   33857             :                    typename Allocator,
   33858             :                    template <typename, typename> class Sequence>
   33859       51001 :          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
   33860             :          {
   33861       56177 :             for (std::size_t i = 0; i < b.size(); ++i)
   33862             :             {
   33863       54600 :                if (0 == b[i])
   33864           0 :                   return false;
   33865       54600 :                else if (!details::is_constant_node(b[i]))
   33866       49424 :                   return false;
   33867             :             }
   33868             : 
   33869        1577 :             return true;
   33870             :          }
   33871             : 
   33872       76654 :          void lodge_assignment(symbol_type cst, expression_node_ptr node)
   33873             :          {
   33874      153308 :             parser_->state_.activate_side_effect("lodge_assignment()");
   33875             : 
   33876       76654 :             if (!parser_->dec_.collect_assignments())
   33877       76650 :                return;
   33878             : 
   33879           4 :             std::string symbol_name;
   33880             : 
   33881           4 :             switch (cst)
   33882             :             {
   33883           3 :                case e_st_variable : symbol_name = parser_->symtab_store_
   33884             :                                                      .get_variable_name(node);
   33885           3 :                                     break;
   33886             : 
   33887             :                #ifndef exprtk_disable_string_capabilities
   33888           1 :                case e_st_string   : symbol_name = parser_->symtab_store_
   33889             :                                                      .get_stringvar_name(node);
   33890           1 :                                     break;
   33891             :                #endif
   33892             : 
   33893           0 :                case e_st_vector   : {
   33894             :                                        typedef details::vector_holder<T> vector_holder_t;
   33895             : 
   33896           0 :                                        vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
   33897             : 
   33898           0 :                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
   33899             :                                     }
   33900           0 :                                     break;
   33901             : 
   33902           0 :                case e_st_vecelem  : {
   33903             :                                        typedef details::vector_holder<T> vector_holder_t;
   33904             : 
   33905           0 :                                        vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
   33906             : 
   33907           0 :                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
   33908             : 
   33909           0 :                                        cst = e_st_vector;
   33910             :                                     }
   33911           0 :                                     break;
   33912             : 
   33913           0 :                default            : return;
   33914             :             }
   33915             : 
   33916           4 :             if (!symbol_name.empty())
   33917             :             {
   33918           4 :                parser_->dec_.add_assignment(symbol_name,cst);
   33919             :             }
   33920           4 :          }
   33921             : 
   33922       76682 :          const void* base_ptr(expression_node_ptr node)
   33923             :          {
   33924       76682 :             if (node)
   33925             :             {
   33926       76682 :                switch(node->type())
   33927             :                {
   33928       51074 :                   case details::expression_node<T>::e_variable:
   33929       51074 :                      return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref());
   33930             : 
   33931         585 :                   case details::expression_node<T>::e_vecelem:
   33932         585 :                      return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref());
   33933             : 
   33934           0 :                   case details::expression_node<T>::e_veccelem:
   33935           0 :                      return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref());
   33936             : 
   33937          32 :                   case details::expression_node<T>::e_vecelemrtc:
   33938          32 :                      return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref());
   33939             : 
   33940           0 :                   case details::expression_node<T>::e_veccelemrtc:
   33941           0 :                      return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref());
   33942             : 
   33943         300 :                   case details::expression_node<T>::e_rbvecelem:
   33944         300 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref());
   33945             : 
   33946           0 :                   case details::expression_node<T>::e_rbvecelemrtc:
   33947           0 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref());
   33948             : 
   33949         300 :                   case details::expression_node<T>::e_rbveccelem:
   33950         300 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref());
   33951             : 
   33952           0 :                   case details::expression_node<T>::e_rbveccelemrtc:
   33953           0 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref());
   33954             : 
   33955        4937 :                   case details::expression_node<T>::e_vector:
   33956        4937 :                      return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data());
   33957             : 
   33958             :                   #ifndef exprtk_disable_string_capabilities
   33959       14592 :                   case details::expression_node<T>::e_stringvar:
   33960       14592 :                      return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base()));
   33961             : 
   33962        4862 :                   case details::expression_node<T>::e_stringvarrng:
   33963        4862 :                      return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base()));
   33964             :                   #endif
   33965           0 :                   default : return reinterpret_cast<const void*>(0);
   33966             :                }
   33967             :             }
   33968             : 
   33969           0 :             return reinterpret_cast<const void*>(0);
   33970             :          }
   33971             : 
   33972       76682 :          bool assign_immutable_symbol(expression_node_ptr node)
   33973             :          {
   33974       76682 :             interval_t interval;
   33975       76682 :             const void* baseptr_addr = base_ptr(node);
   33976             : 
   33977             :             exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr));
   33978             : 
   33979       76682 :             if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval))
   33980             :             {
   33981          28 :                typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval);
   33982             : 
   33983          28 :                if (parser_->immutable_symtok_map_.end() != itr)
   33984             :                {
   33985          28 :                   token_t& token = itr->second;
   33986          56 :                   parser_->set_error(parser_error::make_error(
   33987             :                      parser_error::e_parser,
   33988             :                      token,
   33989          28 :                      "ERR265 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.",
   33990             :                      exprtk_error_location));
   33991             :                }
   33992             :                else
   33993           0 :                   parser_->set_synthesis_error("Unable to assign symbol is immutable.");
   33994             : 
   33995          28 :                return true;
   33996             :             }
   33997             : 
   33998       76654 :             return false;
   33999             :          }
   34000             : 
   34001       64826 :          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   34002             :          {
   34003       64826 :             if (assign_immutable_symbol(branch[0]))
   34004             :             {
   34005          17 :                return error_node();
   34006             :             }
   34007       64809 :             else if (details::is_variable_node(branch[0]))
   34008             :             {
   34009       46190 :                lodge_assignment(e_st_variable,branch[0]);
   34010       46190 :                return synthesize_expression<assignment_node_t,2>(operation,branch);
   34011             :             }
   34012       18619 :             else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0]))
   34013             :             {
   34014          83 :                lodge_assignment(e_st_vecelem,branch[0]);
   34015          83 :                return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
   34016             :             }
   34017       18536 :             else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0]))
   34018             :             {
   34019          20 :                lodge_assignment(e_st_vecelem,branch[0]);
   34020          20 :                return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch);
   34021             :             }
   34022       18516 :             else if (details::is_rebasevector_elem_node(branch[0]))
   34023             :             {
   34024           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   34025           0 :                return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
   34026             :             }
   34027       18516 :             else if (details::is_rebasevector_elem_rtc_node(branch[0]))
   34028             :             {
   34029           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   34030           0 :                return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch);
   34031             :             }
   34032       18516 :             else if (details::is_rebasevector_celem_node(branch[0]))
   34033             :             {
   34034           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   34035           0 :                return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
   34036             :             }
   34037             :             #ifndef exprtk_disable_string_capabilities
   34038       18516 :             else if (details::is_string_node(branch[0]))
   34039             :             {
   34040       11991 :                lodge_assignment(e_st_string,branch[0]);
   34041       11991 :                return synthesize_expression<assignment_string_node_t,2>(operation, branch);
   34042             :             }
   34043        6525 :             else if (details::is_string_range_node(branch[0]))
   34044             :             {
   34045        4850 :                lodge_assignment(e_st_string,branch[0]);
   34046        4850 :                return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
   34047             :             }
   34048             :             #endif
   34049        1675 :             else if (details::is_vector_node(branch[0]))
   34050             :             {
   34051        1675 :                lodge_assignment(e_st_vector,branch[0]);
   34052             : 
   34053        1675 :                if (details::is_ivector_node(branch[1]))
   34054        1471 :                   return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
   34055             :                else
   34056         204 :                   return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
   34057             :             }
   34058           0 :             else if (details::is_literal_node(branch[0]))
   34059             :             {
   34060           0 :                parser_->set_error(parser_error::make_error(
   34061             :                   parser_error::e_syntax,
   34062           0 :                   parser_->current_state().token,
   34063             :                   "ERR266 - Cannot assign value to const variable",
   34064             :                   exprtk_error_location));
   34065             : 
   34066           0 :                return error_node();
   34067             :             }
   34068             :             else
   34069             :             {
   34070           0 :                parser_->set_error(parser_error::make_error(
   34071             :                   parser_error::e_syntax,
   34072           0 :                   parser_->current_state().token,
   34073             :                   "ERR267 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
   34074             :                   exprtk_error_location));
   34075             : 
   34076           0 :                return error_node();
   34077             :             }
   34078             :          }
   34079             : 
   34080       11856 :          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
   34081             :                                                                                expression_node_ptr (&branch)[2])
   34082             :          {
   34083       11856 :             if (assign_immutable_symbol(branch[0]))
   34084             :             {
   34085          11 :                return error_node();
   34086             :             }
   34087             : 
   34088       11845 :             expression_node_ptr result = error_node();
   34089       11845 :             std::string node_name = "Unknown";
   34090             : 
   34091       11845 :             if (details::is_variable_node(branch[0]))
   34092             :             {
   34093        4875 :                lodge_assignment(e_st_variable,branch[0]);
   34094             : 
   34095        4875 :                switch (operation)
   34096             :                {
   34097             :                   #define case_stmt(op0, op1)                                                                 \
   34098             :                   case op0 : result = node_allocator_->                                                       \
   34099             :                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
   34100             :                                    (operation, branch[0], branch[1]);                                         \
   34101             :                              node_name = "assignment_op_node";                                                \
   34102             :                              break;                                                                           \
   34103             : 
   34104        4315 :                   case_stmt(details::e_addass , details::add_op)
   34105         245 :                   case_stmt(details::e_subass , details::sub_op)
   34106         120 :                   case_stmt(details::e_mulass , details::mul_op)
   34107         120 :                   case_stmt(details::e_divass , details::div_op)
   34108          75 :                   case_stmt(details::e_modass , details::mod_op)
   34109             :                   #undef case_stmt
   34110           0 :                   default : return error_node();
   34111             :                }
   34112             :             }
   34113        6970 :             else if (details::is_vector_elem_node(branch[0]))
   34114             :             {
   34115         500 :                lodge_assignment(e_st_vecelem,branch[0]);
   34116             : 
   34117         500 :                switch (operation)
   34118             :                {
   34119             :                   #define case_stmt(op0, op1)                                                                           \
   34120             :                   case op0 : result = node_allocator_->                                                                 \
   34121             :                                  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
   34122             :                                     (operation, branch[0], branch[1]);                                                  \
   34123             :                              node_name = "assignment_vec_elem_op_node";                                                 \
   34124             :                              break;                                                                                     \
   34125             : 
   34126         230 :                   case_stmt(details::e_addass , details::add_op)
   34127         170 :                   case_stmt(details::e_subass , details::sub_op)
   34128          50 :                   case_stmt(details::e_mulass , details::mul_op)
   34129          50 :                   case_stmt(details::e_divass , details::div_op)
   34130           0 :                   case_stmt(details::e_modass , details::mod_op)
   34131             :                   #undef case_stmt
   34132           0 :                   default : return error_node();
   34133             :                }
   34134             :             }
   34135        6470 :             else if (details::is_vector_elem_rtc_node(branch[0]))
   34136             :             {
   34137          12 :                lodge_assignment(e_st_vecelem,branch[0]);
   34138             : 
   34139          12 :                switch (operation)
   34140             :                {
   34141             :                   #define case_stmt(op0, op1)                                                                               \
   34142             :                   case op0 : result = node_allocator_->                                                                     \
   34143             :                                  template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \
   34144             :                                     (operation, branch[0], branch[1]);                                                      \
   34145             :                              node_name = "assignment_vec_elem_op_rtc_node";                                                 \
   34146             :                              break;                                                                                         \
   34147             : 
   34148           8 :                   case_stmt(details::e_addass , details::add_op)
   34149           4 :                   case_stmt(details::e_subass , details::sub_op)
   34150           0 :                   case_stmt(details::e_mulass , details::mul_op)
   34151           0 :                   case_stmt(details::e_divass , details::div_op)
   34152           0 :                   case_stmt(details::e_modass , details::mod_op)
   34153             :                   #undef case_stmt
   34154           0 :                   default : return error_node();
   34155             :                }
   34156             :             }
   34157        6458 :             else if (details::is_vector_celem_rtc_node(branch[0]))
   34158             :             {
   34159           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   34160             : 
   34161           0 :                switch (operation)
   34162             :                {
   34163             :                   #define case_stmt(op0, op1)                                                                                \
   34164             :                   case op0 : result = node_allocator_->                                                                      \
   34165             :                                  template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \
   34166             :                                     (operation, branch[0], branch[1]);                                                       \
   34167             :                              node_name = "assignment_vec_celem_op_rtc_node";                                                 \
   34168             :                              break;                                                                                          \
   34169             : 
   34170           0 :                   case_stmt(details::e_addass , details::add_op)
   34171           0 :                   case_stmt(details::e_subass , details::sub_op)
   34172           0 :                   case_stmt(details::e_mulass , details::mul_op)
   34173           0 :                   case_stmt(details::e_divass , details::div_op)
   34174           0 :                   case_stmt(details::e_modass , details::mod_op)
   34175             :                   #undef case_stmt
   34176           0 :                   default : return error_node();
   34177             :                }
   34178             :             }
   34179        6458 :             else if (details::is_rebasevector_elem_node(branch[0]))
   34180             :             {
   34181         300 :                lodge_assignment(e_st_vecelem,branch[0]);
   34182             : 
   34183         300 :                switch (operation)
   34184             :                {
   34185             :                   #define case_stmt(op0, op1)                                                                                 \
   34186             :                   case op0 : result = node_allocator_->                                                                       \
   34187             :                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
   34188             :                                     (operation, branch[0], branch[1]);                                                        \
   34189             :                              node_name = "assignment_rebasevec_elem_op_node";                                                 \
   34190             :                              break;                                                                                           \
   34191             : 
   34192         180 :                   case_stmt(details::e_addass , details::add_op)
   34193         120 :                   case_stmt(details::e_subass , details::sub_op)
   34194           0 :                   case_stmt(details::e_mulass , details::mul_op)
   34195           0 :                   case_stmt(details::e_divass , details::div_op)
   34196           0 :                   case_stmt(details::e_modass , details::mod_op)
   34197             :                   #undef case_stmt
   34198           0 :                   default : return error_node();
   34199             :                }
   34200             :             }
   34201        6158 :             else if (details::is_rebasevector_celem_node(branch[0]))
   34202             :             {
   34203         300 :                lodge_assignment(e_st_vecelem,branch[0]);
   34204             : 
   34205         300 :                switch (operation)
   34206             :                {
   34207             :                   #define case_stmt(op0, op1)                                                                                  \
   34208             :                   case op0 : result = node_allocator_->                                                                        \
   34209             :                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
   34210             :                                     (operation, branch[0], branch[1]);                                                         \
   34211             :                              node_name = "assignment_rebasevec_celem_op_node";                                                 \
   34212             :                              break;                                                                                            \
   34213             : 
   34214         180 :                   case_stmt(details::e_addass , details::add_op)
   34215         120 :                   case_stmt(details::e_subass , details::sub_op)
   34216           0 :                   case_stmt(details::e_mulass , details::mul_op)
   34217           0 :                   case_stmt(details::e_divass , details::div_op)
   34218           0 :                   case_stmt(details::e_modass , details::mod_op)
   34219             :                   #undef case_stmt
   34220           0 :                   default : return error_node();
   34221             :                }
   34222             :             }
   34223        5858 :             else if (details::is_rebasevector_elem_rtc_node(branch[0]))
   34224             :             {
   34225           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   34226             : 
   34227           0 :                switch (operation)
   34228             :                {
   34229             :                   #define case_stmt(op0, op1)                                                                                     \
   34230             :                   case op0 : result = node_allocator_->                                                                           \
   34231             :                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \
   34232             :                                     (operation, branch[0], branch[1]);                                                            \
   34233             :                              node_name = "assignment_rebasevec_elem_op_rtc_node";                                                 \
   34234             :                              break;                                                                                               \
   34235             : 
   34236           0 :                   case_stmt(details::e_addass , details::add_op)
   34237           0 :                   case_stmt(details::e_subass , details::sub_op)
   34238           0 :                   case_stmt(details::e_mulass , details::mul_op)
   34239           0 :                   case_stmt(details::e_divass , details::div_op)
   34240           0 :                   case_stmt(details::e_modass , details::mod_op)
   34241             :                   #undef case_stmt
   34242           0 :                   default : return error_node();
   34243             :                }
   34244             :             }
   34245        5858 :             else if (details::is_rebasevector_celem_rtc_node(branch[0]))
   34246             :             {
   34247           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   34248             : 
   34249           0 :                switch (operation)
   34250             :                {
   34251             :                   #define case_stmt(op0, op1)                                                                                      \
   34252             :                   case op0 : result = node_allocator_->                                                                            \
   34253             :                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \
   34254             :                                     (operation, branch[0], branch[1]);                                                             \
   34255             :                              node_name = "assignment_rebasevec_celem_op_rtc_node";                                                 \
   34256             :                              break;                                                                                                \
   34257             : 
   34258           0 :                   case_stmt(details::e_addass , details::add_op)
   34259           0 :                   case_stmt(details::e_subass , details::sub_op)
   34260           0 :                   case_stmt(details::e_mulass , details::mul_op)
   34261           0 :                   case_stmt(details::e_divass , details::div_op)
   34262           0 :                   case_stmt(details::e_modass , details::mod_op)
   34263             :                   #undef case_stmt
   34264           0 :                   default : return error_node();
   34265             :                }
   34266             :             }
   34267        5858 :             else if (details::is_vector_node(branch[0]))
   34268             :             {
   34269        3258 :                lodge_assignment(e_st_vector,branch[0]);
   34270             : 
   34271        3258 :                if (details::is_ivector_node(branch[1]))
   34272             :                {
   34273         766 :                   switch (operation)
   34274             :                   {
   34275             :                      #define case_stmt(op0, op1)                                                                        \
   34276             :                      case op0 : result = node_allocator_->                                                              \
   34277             :                                    template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
   34278             :                                       (operation, branch[0], branch[1]);                                                \
   34279             :                                 node_name = "assignment_rebasevec_celem_op_node";                                       \
   34280             :                                 break;                                                                                  \
   34281             : 
   34282         526 :                      case_stmt(details::e_addass , details::add_op)
   34283          80 :                      case_stmt(details::e_subass , details::sub_op)
   34284          80 :                      case_stmt(details::e_mulass , details::mul_op)
   34285          80 :                      case_stmt(details::e_divass , details::div_op)
   34286           0 :                      case_stmt(details::e_modass , details::mod_op)
   34287             :                      #undef case_stmt
   34288           0 :                      default : return error_node();
   34289             :                   }
   34290             :                }
   34291             :                else
   34292             :                {
   34293        2492 :                   switch (operation)
   34294             :                   {
   34295             :                      #define case_stmt(op0, op1)                                                                     \
   34296             :                      case op0 : result = node_allocator_->                                                           \
   34297             :                                    template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
   34298             :                                       (operation, branch[0], branch[1]);                                             \
   34299             :                                 node_name = "assignment_vec_op_node";                                                \
   34300             :                                 break;                                                                               \
   34301             : 
   34302        2027 :                      case_stmt(details::e_addass , details::add_op)
   34303         305 :                      case_stmt(details::e_subass , details::sub_op)
   34304          80 :                      case_stmt(details::e_mulass , details::mul_op)
   34305          80 :                      case_stmt(details::e_divass , details::div_op)
   34306           0 :                      case_stmt(details::e_modass , details::mod_op)
   34307             :                      #undef case_stmt
   34308           0 :                      default : return error_node();
   34309             :                   }
   34310             :                }
   34311             :             }
   34312             :             #ifndef exprtk_disable_string_capabilities
   34313        2600 :             else if (
   34314        5200 :                       (details::e_addass == operation) &&
   34315        2600 :                       details::is_string_node(branch[0])
   34316             :                     )
   34317             :             {
   34318             :                typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
   34319             : 
   34320        2600 :                lodge_assignment(e_st_string,branch[0]);
   34321             : 
   34322        2600 :                result = synthesize_expression<addass_t,2>(operation,branch);
   34323        2600 :                node_name = "assignment_string_node<T,details::asn_addassignment>";
   34324             :             }
   34325             :             #endif
   34326             :             else
   34327             :             {
   34328           0 :                parser_->set_error(parser_error::make_error(
   34329             :                   parser_error::e_syntax,
   34330           0 :                   parser_->current_state().token,
   34331             :                   "ERR268 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
   34332             :                   exprtk_error_location));
   34333             : 
   34334           0 :                return error_node();
   34335             :             }
   34336             : 
   34337       11845 :             if (result && result->valid())
   34338             :             {
   34339       11845 :                return result;
   34340             :             }
   34341             : 
   34342           0 :             parser_->set_error(parser_error::make_error(
   34343             :                parser_error::e_synthesis,
   34344           0 :                token_t(),
   34345             :                "ERR269 - Failed to synthesize node: " + node_name,
   34346             :                exprtk_error_location));
   34347             : 
   34348           0 :             details::free_node(*node_allocator_, result);
   34349           0 :             return error_node();
   34350       11845 :          }
   34351             : 
   34352        6457 :          inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
   34353             :                                                                                    expression_node_ptr (&branch)[2])
   34354             :          {
   34355        6457 :             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
   34356        6457 :             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
   34357             : 
   34358             :             #define batch_eqineq_logic_case                 \
   34359             :             case_stmt(details::e_lt    , details::lt_op   ) \
   34360             :             case_stmt(details::e_lte   , details::lte_op  ) \
   34361             :             case_stmt(details::e_gt    , details::gt_op   ) \
   34362             :             case_stmt(details::e_gte   , details::gte_op  ) \
   34363             :             case_stmt(details::e_eq    , details::eq_op   ) \
   34364             :             case_stmt(details::e_ne    , details::ne_op   ) \
   34365             :             case_stmt(details::e_equal , details::equal_op) \
   34366             :             case_stmt(details::e_and   , details::and_op  ) \
   34367             :             case_stmt(details::e_nand  , details::nand_op ) \
   34368             :             case_stmt(details::e_or    , details::or_op   ) \
   34369             :             case_stmt(details::e_nor   , details::nor_op  ) \
   34370             :             case_stmt(details::e_xor   , details::xor_op  ) \
   34371             :             case_stmt(details::e_xnor  , details::xnor_op ) \
   34372             : 
   34373        6457 :             expression_node_ptr result = error_node();
   34374        6457 :             std::string node_name = "Unknown";
   34375             : 
   34376        6457 :             if (is_b0_ivec && is_b1_ivec)
   34377             :             {
   34378        5577 :                switch (operation)
   34379             :                {
   34380             :                   #define case_stmt(op0, op1)                                                                    \
   34381             :                   case op0 : result = node_allocator_->                                                          \
   34382             :                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
   34383             :                                    (operation, branch[0], branch[1]);                                            \
   34384             :                              node_name = "vec_binop_vecvec_node";                                                \
   34385             :                              break;                                                                              \
   34386             : 
   34387        5577 :                   batch_eqineq_logic_case
   34388             :                   #undef case_stmt
   34389           0 :                   default : return error_node();
   34390             :                }
   34391             :             }
   34392         880 :             else if (is_b0_ivec && !is_b1_ivec)
   34393             :             {
   34394         400 :                switch (operation)
   34395             :                {
   34396             :                   #define case_stmt(op0, op1)                                                                    \
   34397             :                   case op0 : result = node_allocator_->                                                          \
   34398             :                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
   34399             :                                    (operation, branch[0], branch[1]);                                            \
   34400             :                              node_name = "vec_binop_vecval_node";                                                \
   34401             :                              break;                                                                              \
   34402             : 
   34403         400 :                   batch_eqineq_logic_case
   34404             :                   #undef case_stmt
   34405           0 :                   default : return error_node();
   34406             :                }
   34407             :             }
   34408         480 :             else if (!is_b0_ivec && is_b1_ivec)
   34409             :             {
   34410         480 :                switch (operation)
   34411             :                {
   34412             :                   #define case_stmt(op0, op1)                                                                    \
   34413             :                   case op0 : result = node_allocator_->                                                          \
   34414             :                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
   34415             :                                    (operation, branch[0], branch[1]);                                            \
   34416             :                              node_name = "vec_binop_valvec_node";                                                \
   34417             :                              break;                                                                              \
   34418             : 
   34419         480 :                   batch_eqineq_logic_case
   34420             :                   #undef case_stmt
   34421           0 :                   default : return error_node();
   34422             :                }
   34423             :             }
   34424             :             else
   34425           0 :                return error_node();
   34426             : 
   34427        6457 :             if (result && result->valid())
   34428             :             {
   34429        6457 :                return result;
   34430             :             }
   34431             : 
   34432           0 :             parser_->set_error(parser_error::make_error(
   34433             :                parser_error::e_synthesis,
   34434           0 :                token_t(),
   34435             :                "ERR270 - Failed to synthesize node: " + node_name,
   34436             :                exprtk_error_location));
   34437             : 
   34438           0 :             details::free_node(*node_allocator_, result);
   34439           0 :             return error_node();
   34440             : 
   34441             :             #undef batch_eqineq_logic_case
   34442        6457 :          }
   34443             : 
   34444       12299 :          inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
   34445             :                                                                                   expression_node_ptr (&branch)[2])
   34446             :          {
   34447       12299 :             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
   34448       12299 :             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
   34449             : 
   34450             :             #define vector_ops                          \
   34451             :             case_stmt(details::e_add , details::add_op) \
   34452             :             case_stmt(details::e_sub , details::sub_op) \
   34453             :             case_stmt(details::e_mul , details::mul_op) \
   34454             :             case_stmt(details::e_div , details::div_op) \
   34455             :             case_stmt(details::e_mod , details::mod_op) \
   34456             : 
   34457       12299 :             expression_node_ptr result = error_node();
   34458       12299 :             std::string node_name = "Unknown";
   34459             : 
   34460       12299 :             if (is_b0_ivec && is_b1_ivec)
   34461             :             {
   34462        4978 :                switch (operation)
   34463             :                {
   34464             :                   #define case_stmt(op0, op1)                                                                    \
   34465             :                   case op0 : result = node_allocator_->                                                          \
   34466             :                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
   34467             :                                    (operation, branch[0], branch[1]);                                            \
   34468             :                              node_name = "vec_binop_vecvec_node";                                                \
   34469             :                              break;                                                                              \
   34470             : 
   34471        4978 :                   vector_ops
   34472           0 :                   case_stmt(details::e_pow,details:: pow_op)
   34473             :                   #undef case_stmt
   34474           0 :                   default : return error_node();
   34475             :                }
   34476             :             }
   34477        7321 :             else if (is_b0_ivec && !is_b1_ivec)
   34478             :             {
   34479        3599 :                switch (operation)
   34480             :                {
   34481             :                   #define case_stmt(op0, op1)                                                                    \
   34482             :                   case op0 : result = node_allocator_->                                                          \
   34483             :                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
   34484             :                                    (operation, branch[0], branch[1]);                                            \
   34485             :                              node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)";                                \
   34486             :                              break;                                                                              \
   34487             : 
   34488        3559 :                   vector_ops
   34489          40 :                   case_stmt(details::e_pow,details:: pow_op)
   34490             :                   #undef case_stmt
   34491           0 :                   default : return error_node();
   34492             :                }
   34493             :             }
   34494        3722 :             else if (!is_b0_ivec && is_b1_ivec)
   34495             :             {
   34496        3722 :                switch (operation)
   34497             :                {
   34498             :                   #define case_stmt(op0, op1)                                                                    \
   34499             :                   case op0 : result = node_allocator_->                                                          \
   34500             :                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
   34501             :                                    (operation, branch[0], branch[1]);                                            \
   34502             :                              node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)";                                \
   34503             :                              break;                                                                              \
   34504             : 
   34505        3722 :                   vector_ops
   34506             :                   #undef case_stmt
   34507           0 :                   default : return error_node();
   34508             :                }
   34509             :             }
   34510             :             else
   34511           0 :                return error_node();
   34512             : 
   34513       12299 :             if (result && result->valid())
   34514             :             {
   34515       12299 :                return result;
   34516             :             }
   34517             : 
   34518           0 :             parser_->set_error(parser_error::make_error(
   34519             :                parser_error::e_synthesis,
   34520           0 :                token_t(),
   34521             :                "ERR271 - Failed to synthesize node: " + node_name,
   34522             :                exprtk_error_location));
   34523             : 
   34524           0 :             details::free_node(*node_allocator_, result);
   34525           0 :             return error_node();
   34526             : 
   34527             :             #undef vector_ops
   34528       12299 :          }
   34529             : 
   34530        2728 :          inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
   34531             :          {
   34532        2728 :             const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
   34533        2728 :             const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
   34534             : 
   34535        2728 :             const bool v0_is_ivec = details::is_ivector_node  (branch[0]);
   34536        2728 :             const bool v1_is_ivec = details::is_ivector_node  (branch[1]);
   34537             : 
   34538             :             #ifndef exprtk_disable_string_capabilities
   34539        2728 :             const bool v0_is_str = details::is_generally_string_node(branch[0]);
   34540        2728 :             const bool v1_is_str = details::is_generally_string_node(branch[1]);
   34541             :             #endif
   34542             : 
   34543        2728 :             expression_node_ptr result = error_node();
   34544        2728 :             std::string node_name      = "Unknown";
   34545             : 
   34546        2728 :             if (v0_is_ivar && v1_is_ivar)
   34547             :             {
   34548             :                typedef details::variable_node<T>* variable_node_ptr;
   34549             : 
   34550         566 :                variable_node_ptr v0 = variable_node_ptr(0);
   34551         566 :                variable_node_ptr v1 = variable_node_ptr(0);
   34552             : 
   34553         566 :                if (
   34554         886 :                     (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
   34555         320 :                     (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
   34556             :                   )
   34557             :                {
   34558         240 :                   result    = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
   34559         240 :                   node_name = "swap_node";
   34560             :                }
   34561             :                else
   34562             :                {
   34563         326 :                   result    = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
   34564         326 :                   node_name = "swap_generic_node";
   34565             :                }
   34566         566 :             }
   34567        2162 :             else if (v0_is_ivec && v1_is_ivec)
   34568             :             {
   34569         662 :                result    = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
   34570         662 :                node_name = "swap_vecvec_node";
   34571             :             }
   34572             :             #ifndef exprtk_disable_string_capabilities
   34573        1500 :             else if (v0_is_str && v1_is_str)
   34574             :             {
   34575        3000 :                if (is_string_node(branch[0]) && is_string_node(branch[1]))
   34576             :                {
   34577           0 :                   result = node_allocator_->allocate<details::swap_string_node<T> >
   34578           0 :                                                (branch[0], branch[1]);
   34579           0 :                   node_name = "swap_string_node";
   34580             :                }
   34581             :                else
   34582             :                {
   34583        3000 :                   result = node_allocator_->allocate<details::swap_genstrings_node<T> >
   34584        1500 :                                                (branch[0], branch[1]);
   34585        1500 :                   node_name = "swap_genstrings_node";
   34586             :                }
   34587             :             }
   34588             :             #endif
   34589             :             else
   34590             :             {
   34591           0 :                parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
   34592           0 :                return error_node();
   34593             :             }
   34594             : 
   34595        2728 :             if (result && result->valid())
   34596             :             {
   34597        5456 :                parser_->state_.activate_side_effect("synthesize_swap_expression()");
   34598        2728 :                return result;
   34599             :             }
   34600             : 
   34601           0 :             parser_->set_error(parser_error::make_error(
   34602             :                parser_error::e_synthesis,
   34603           0 :                token_t(),
   34604             :                "ERR272 - Failed to synthesize node: " + node_name,
   34605             :                exprtk_error_location));
   34606             : 
   34607           0 :             details::free_node(*node_allocator_, result);
   34608           0 :             return error_node();
   34609        2728 :          }
   34610             : 
   34611             :          #ifndef exprtk_disable_sc_andor
   34612         856 :          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   34613             :          {
   34614         856 :             expression_node_ptr result = error_node();
   34615             : 
   34616         856 :             if (details::is_constant_node(branch[0]))
   34617             :             {
   34618         843 :                if (
   34619        1266 :                     (details::e_scand == operation) &&
   34620        1266 :                     std::equal_to<T>()(T(0),branch[0]->value())
   34621             :                   )
   34622         210 :                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
   34623         633 :                else if (
   34624        1053 :                          (details::e_scor == operation) &&
   34625        1053 :                          std::not_equal_to<T>()(T(0),branch[0]->value())
   34626             :                        )
   34627         210 :                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
   34628             :             }
   34629             : 
   34630         856 :             if (details::is_constant_node(branch[1]) && (0 == result))
   34631             :             {
   34632         430 :                if (
   34633         650 :                     (details::e_scand == operation) &&
   34634         650 :                     std::equal_to<T>()(T(0),branch[1]->value())
   34635             :                   )
   34636         106 :                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
   34637         324 :                else if (
   34638         534 :                          (details::e_scor == operation) &&
   34639         534 :                          std::not_equal_to<T>()(T(0),branch[1]->value())
   34640             :                        )
   34641         105 :                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
   34642             :             }
   34643             : 
   34644         856 :             if (result)
   34645             :             {
   34646         631 :                details::free_node(*node_allocator_, branch[0]);
   34647         631 :                details::free_node(*node_allocator_, branch[1]);
   34648             : 
   34649         631 :                return result;
   34650             :             }
   34651         225 :             else if (details::e_scand == operation)
   34652             :             {
   34653         120 :                return synthesize_expression<scand_node_t,2>(operation, branch);
   34654             :             }
   34655         105 :             else if (details::e_scor == operation)
   34656             :             {
   34657         105 :                return synthesize_expression<scor_node_t,2>(operation, branch);
   34658             :             }
   34659             :             else
   34660           0 :                return error_node();
   34661             :          }
   34662             :          #else
   34663             :          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
   34664             :          {
   34665             :             return error_node();
   34666             :          }
   34667             :          #endif
   34668             : 
   34669             :          #define basic_opr_switch_statements         \
   34670             :          case_stmt(details::e_add , details::add_op) \
   34671             :          case_stmt(details::e_sub , details::sub_op) \
   34672             :          case_stmt(details::e_mul , details::mul_op) \
   34673             :          case_stmt(details::e_div , details::div_op) \
   34674             :          case_stmt(details::e_mod , details::mod_op) \
   34675             :          case_stmt(details::e_pow , details::pow_op) \
   34676             : 
   34677             :          #define extended_opr_switch_statements        \
   34678             :          case_stmt(details::e_lt   , details::lt_op  ) \
   34679             :          case_stmt(details::e_lte  , details::lte_op ) \
   34680             :          case_stmt(details::e_gt   , details::gt_op  ) \
   34681             :          case_stmt(details::e_gte  , details::gte_op ) \
   34682             :          case_stmt(details::e_eq   , details::eq_op  ) \
   34683             :          case_stmt(details::e_ne   , details::ne_op  ) \
   34684             :          case_stmt(details::e_and  , details::and_op ) \
   34685             :          case_stmt(details::e_nand , details::nand_op) \
   34686             :          case_stmt(details::e_or   , details::or_op  ) \
   34687             :          case_stmt(details::e_nor  , details::nor_op ) \
   34688             :          case_stmt(details::e_xor  , details::xor_op ) \
   34689             :          case_stmt(details::e_xnor , details::xnor_op) \
   34690             : 
   34691             :          #ifndef exprtk_disable_cardinal_pow_optimisation
   34692             :          template <typename TType, template <typename, typename> class IPowNode>
   34693       62113 :          inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
   34694             :          {
   34695       62113 :             switch (p)
   34696             :             {
   34697             :                #define case_stmt(cp)                                                     \
   34698             :                case cp : return node_allocator_->                                        \
   34699             :                             allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
   34700             : 
   34701       20138 :                case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
   34702       27770 :                case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
   34703       11085 :                case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
   34704         960 :                case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
   34705         960 :                case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
   34706         960 :                case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
   34707         240 :                case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
   34708           0 :                case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
   34709           0 :                case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
   34710           0 :                case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
   34711           0 :                case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
   34712           0 :                case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
   34713           0 :                case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
   34714           0 :                case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
   34715           0 :                case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
   34716             :                #undef case_stmt
   34717           0 :                default : return error_node();
   34718             :             }
   34719             :          }
   34720             : 
   34721       73697 :          inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
   34722             :          {
   34723       73697 :             const bool not_recipricol = (c >= T(0));
   34724       73697 :             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
   34725             : 
   34726       73697 :             if (0 == p)
   34727         240 :                return node_allocator_->allocate_c<literal_node_t>(T(1));
   34728       73457 :             else if (std::equal_to<T>()(T(2),c))
   34729             :             {
   34730       11345 :                return node_allocator_->
   34731       11345 :                   template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
   34732             :             }
   34733             :             else
   34734             :             {
   34735       62112 :                if (not_recipricol)
   34736       59062 :                   return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
   34737             :                else
   34738        3050 :                   return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
   34739             :             }
   34740             :          }
   34741             : 
   34742      653422 :          inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
   34743             :          {
   34744      653422 :             return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
   34745             :          }
   34746             : 
   34747           1 :          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
   34748             :          {
   34749           1 :             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   34750           1 :             const bool not_recipricol = (c >= T(0));
   34751           1 :             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
   34752             : 
   34753           1 :             node_allocator_->free(branch[1]);
   34754             : 
   34755           1 :             if (0 == p)
   34756             :             {
   34757           0 :                details::free_all_nodes(*node_allocator_, branch);
   34758             : 
   34759           0 :                return node_allocator_->allocate_c<literal_node_t>(T(1));
   34760             :             }
   34761           1 :             else if (not_recipricol)
   34762           1 :                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
   34763             :             else
   34764           0 :                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p);
   34765             :          }
   34766             :          #else
   34767             :          inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
   34768             :          {
   34769             :             return error_node();
   34770             :          }
   34771             : 
   34772             :          inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
   34773             :          {
   34774             :             return false;
   34775             :          }
   34776             : 
   34777             :          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
   34778             :          {
   34779             :             return error_node();
   34780             :          }
   34781             :          #endif
   34782             : 
   34783             :          struct synthesize_binary_ext_expression
   34784             :          {
   34785      407007 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34786             :                                                       const details::operator_type& operation,
   34787             :                                                       expression_node_ptr (&branch)[2])
   34788             :             {
   34789      407007 :                const bool left_neg  = is_neg_unary_node(branch[0]);
   34790      407007 :                const bool right_neg = is_neg_unary_node(branch[1]);
   34791             : 
   34792      407007 :                if (left_neg && right_neg)
   34793             :                {
   34794         200 :                   if (
   34795         200 :                        (details::e_add == operation) ||
   34796         200 :                        (details::e_sub == operation) ||
   34797         200 :                        (details::e_mul == operation) ||
   34798          80 :                        (details::e_div == operation)
   34799             :                      )
   34800             :                   {
   34801         200 :                      if (
   34802         400 :                           !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
   34803         200 :                           !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
   34804             :                         )
   34805             :                      {
   34806           0 :                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
   34807             : 
   34808           0 :                         return error_node();
   34809             :                      }
   34810             :                   }
   34811             : 
   34812         200 :                   switch (operation)
   34813             :                   {
   34814             :                                            // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
   34815           0 :                      case details::e_add : return expr_gen(details::e_neg,
   34816           0 :                                               expr_gen.node_allocator_->
   34817             :                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
   34818           0 :                                                     (branch[0],branch[1]));
   34819             : 
   34820             :                                            // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
   34821           0 :                      case details::e_sub : return expr_gen.node_allocator_->
   34822             :                                               template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
   34823           0 :                                                  (branch[1],branch[0]);
   34824             : 
   34825         200 :                      default             : break;
   34826             :                   }
   34827             :                }
   34828      406807 :                else if (left_neg && !right_neg)
   34829             :                {
   34830         540 :                   if (
   34831         540 :                        (details::e_add == operation) ||
   34832         360 :                        (details::e_sub == operation) ||
   34833         200 :                        (details::e_mul == operation) ||
   34834          80 :                        (details::e_div == operation)
   34835             :                      )
   34836             :                   {
   34837         540 :                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
   34838             :                      {
   34839           0 :                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
   34840             : 
   34841           0 :                         return error_node();
   34842             :                      }
   34843             : 
   34844         540 :                      switch (operation)
   34845             :                      {
   34846             :                                               // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
   34847         180 :                         case details::e_add : return expr_gen.node_allocator_->
   34848             :                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
   34849         180 :                                                    (branch[1], branch[0]);
   34850             : 
   34851             :                                               // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
   34852         320 :                         case details::e_sub : return expr_gen(details::e_neg,
   34853         160 :                                                  expr_gen.node_allocator_->
   34854             :                                                     template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
   34855         320 :                                                        (branch[0], branch[1]));
   34856             : 
   34857             :                                               // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
   34858         240 :                         case details::e_mul : return expr_gen(details::e_neg,
   34859         120 :                                                  expr_gen.node_allocator_->
   34860             :                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
   34861         240 :                                                        (branch[0], branch[1]));
   34862             : 
   34863             :                                               // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
   34864         160 :                         case details::e_div : return expr_gen(details::e_neg,
   34865          80 :                                                  expr_gen.node_allocator_->
   34866             :                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
   34867         160 :                                                        (branch[0], branch[1]));
   34868             : 
   34869           0 :                         default             : return error_node();
   34870             :                      }
   34871             :                   }
   34872             :                }
   34873      406267 :                else if (!left_neg && right_neg)
   34874             :                {
   34875         688 :                   if (
   34876         688 :                        (details::e_add == operation) ||
   34877         688 :                        (details::e_sub == operation) ||
   34878         688 :                        (details::e_mul == operation) ||
   34879         568 :                        (details::e_div == operation)
   34880             :                      )
   34881             :                   {
   34882         200 :                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
   34883             :                      {
   34884           0 :                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
   34885             : 
   34886           0 :                         return error_node();
   34887             :                      }
   34888             : 
   34889         200 :                      switch (operation)
   34890             :                      {
   34891             :                                               // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
   34892           0 :                         case details::e_add : return expr_gen.node_allocator_->
   34893             :                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
   34894           0 :                                                    (branch[0], branch[1]);
   34895             : 
   34896             :                                               // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
   34897           0 :                         case details::e_sub : return expr_gen.node_allocator_->
   34898             :                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
   34899           0 :                                                    (branch[0], branch[1]);
   34900             : 
   34901             :                                               // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
   34902         240 :                         case details::e_mul : return expr_gen(details::e_neg,
   34903         120 :                                                  expr_gen.node_allocator_->
   34904             :                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
   34905         240 :                                                        (branch[0], branch[1]));
   34906             : 
   34907             :                                               // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
   34908         160 :                         case details::e_div : return expr_gen(details::e_neg,
   34909          80 :                                                  expr_gen.node_allocator_->
   34910             :                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
   34911         160 :                                                        (branch[0], branch[1]));
   34912             : 
   34913           0 :                         default             : return error_node();
   34914             :                      }
   34915             :                   }
   34916             :                }
   34917             : 
   34918      406267 :                switch (operation)
   34919             :                {
   34920             :                   #define case_stmt(op0, op1)                                                          \
   34921             :                   case op0 : return expr_gen.node_allocator_->                                         \
   34922             :                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
   34923             :                                    (branch[0], branch[1]);                                             \
   34924             : 
   34925      397270 :                   basic_opr_switch_statements
   34926        8997 :                   extended_opr_switch_statements
   34927             :                   #undef case_stmt
   34928           0 :                   default : return error_node();
   34929             :                }
   34930             :             }
   34931             :          };
   34932             : 
   34933             :          struct synthesize_vob_expression
   34934             :          {
   34935       52659 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34936             :                                                       const details::operator_type& operation,
   34937             :                                                       expression_node_ptr (&branch)[2])
   34938             :             {
   34939       52659 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   34940             : 
   34941             :                #ifndef exprtk_disable_enhanced_features
   34942       52659 :                if (details::is_sf3ext_node(branch[1]))
   34943             :                {
   34944       37060 :                   expression_node_ptr result = error_node();
   34945             : 
   34946             :                   const bool synthesis_result =
   34947             :                      synthesize_sf4ext_expression::template compile_right<vtype>
   34948       37060 :                         (expr_gen, v, operation, branch[1], result);
   34949             : 
   34950       37060 :                   if (synthesis_result)
   34951             :                   {
   34952       18860 :                      details::free_node(*expr_gen.node_allocator_,branch[1]);
   34953       18860 :                      return result;
   34954             :                   }
   34955             :                }
   34956             :                #endif
   34957             : 
   34958       33799 :                if (
   34959       33799 :                     (details::e_mul == operation) ||
   34960       26875 :                     (details::e_div == operation)
   34961             :                   )
   34962             :                {
   34963       21217 :                   if (details::is_uv_node(branch[1]))
   34964             :                   {
   34965             :                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
   34966             : 
   34967         290 :                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
   34968             : 
   34969         290 :                      if (details::e_neg == o)
   34970             :                      {
   34971          40 :                         const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
   34972             : 
   34973          40 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34974             : 
   34975          40 :                         switch (operation)
   34976             :                         {
   34977          80 :                            case details::e_mul : return expr_gen(details::e_neg,
   34978          40 :                                                     expr_gen.node_allocator_->
   34979             :                                                        template allocate_rr<typename details::
   34980          40 :                                                           vov_node<Type,details::mul_op<Type> > >(v,v1));
   34981             : 
   34982           0 :                            case details::e_div : return expr_gen(details::e_neg,
   34983           0 :                                                     expr_gen.node_allocator_->
   34984             :                                                        template allocate_rr<typename details::
   34985           0 :                                                           vov_node<Type,details::div_op<Type> > >(v,v1));
   34986             : 
   34987           0 :                            default             : break;
   34988             :                         }
   34989             :                      }
   34990             :                   }
   34991             :                }
   34992             : 
   34993       33759 :                switch (operation)
   34994             :                {
   34995             :                   #define case_stmt(op0, op1)                                                      \
   34996             :                   case op0 : return expr_gen.node_allocator_->                                     \
   34997             :                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
   34998             :                                    (v, branch[1]);                                                 \
   34999             : 
   35000       33722 :                   basic_opr_switch_statements
   35001          37 :                   extended_opr_switch_statements
   35002             :                   #undef case_stmt
   35003           0 :                   default : return error_node();
   35004             :                }
   35005             :             }
   35006             :          };
   35007             : 
   35008             :          struct synthesize_bov_expression
   35009             :          {
   35010      361546 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35011             :                                                       const details::operator_type& operation,
   35012             :                                                       expression_node_ptr (&branch)[2])
   35013             :             {
   35014      361546 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   35015             : 
   35016             :                #ifndef exprtk_disable_enhanced_features
   35017      361546 :                if (details::is_sf3ext_node(branch[0]))
   35018             :                {
   35019       67662 :                   expression_node_ptr result = error_node();
   35020             : 
   35021             :                   const bool synthesis_result =
   35022             :                      synthesize_sf4ext_expression::template compile_left<vtype>
   35023       67662 :                         (expr_gen, v, operation, branch[0], result);
   35024             : 
   35025       67662 :                   if (synthesis_result)
   35026             :                   {
   35027        8575 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35028             : 
   35029        8575 :                      return result;
   35030             :                   }
   35031             :                }
   35032             :                #endif
   35033             : 
   35034      352971 :                if (
   35035      352971 :                     (details::e_add == operation) ||
   35036      175405 :                     (details::e_sub == operation) ||
   35037      107504 :                     (details::e_mul == operation) ||
   35038       23049 :                     (details::e_div == operation)
   35039             :                   )
   35040             :                {
   35041      352108 :                   if (details::is_uv_node(branch[0]))
   35042             :                   {
   35043             :                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
   35044             : 
   35045         256 :                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
   35046             : 
   35047         256 :                      if (details::e_neg == o)
   35048             :                      {
   35049         200 :                         const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
   35050             : 
   35051         200 :                         details::free_node(*expr_gen.node_allocator_,branch[0]);
   35052             : 
   35053         200 :                         switch (operation)
   35054             :                         {
   35055          80 :                            case details::e_add : return expr_gen.node_allocator_->
   35056             :                                                     template allocate_rr<typename details::
   35057          80 :                                                        vov_node<Type,details::sub_op<Type> > >(v,v0);
   35058             : 
   35059         160 :                            case details::e_sub : return expr_gen(details::e_neg,
   35060          80 :                                                     expr_gen.node_allocator_->
   35061             :                                                        template allocate_rr<typename details::
   35062          80 :                                                           vov_node<Type,details::add_op<Type> > >(v0,v));
   35063             : 
   35064          80 :                            case details::e_mul : return expr_gen(details::e_neg,
   35065          40 :                                                     expr_gen.node_allocator_->
   35066             :                                                        template allocate_rr<typename details::
   35067          40 :                                                           vov_node<Type,details::mul_op<Type> > >(v0,v));
   35068             : 
   35069           0 :                            case details::e_div : return expr_gen(details::e_neg,
   35070           0 :                                                     expr_gen.node_allocator_->
   35071             :                                                        template allocate_rr<typename details::
   35072           0 :                                                           vov_node<Type,details::div_op<Type> > >(v0,v));
   35073           0 :                            default : break;
   35074             :                         }
   35075             :                      }
   35076             :                   }
   35077             :                }
   35078             : 
   35079      352771 :                switch (operation)
   35080             :                {
   35081             :                   #define case_stmt(op0, op1)                                                      \
   35082             :                   case op0 : return expr_gen.node_allocator_->                                     \
   35083             :                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
   35084             :                                    (branch[0], v);                                                 \
   35085             : 
   35086      351914 :                   basic_opr_switch_statements
   35087         857 :                   extended_opr_switch_statements
   35088             :                   #undef case_stmt
   35089           0 :                   default : return error_node();
   35090             :                }
   35091             :             }
   35092             :          };
   35093             : 
   35094             :          struct synthesize_cob_expression
   35095             :          {
   35096       99132 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35097             :                                                       const details::operator_type& operation,
   35098             :                                                       expression_node_ptr (&branch)[2])
   35099             :             {
   35100       99132 :                const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   35101             : 
   35102       99132 :                details::free_node(*expr_gen.node_allocator_,branch[0]);
   35103             : 
   35104       99132 :                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   35105             :                {
   35106         650 :                   details::free_node(*expr_gen.node_allocator_,branch[1]);
   35107             : 
   35108         650 :                   return expr_gen(T(0));
   35109             :                }
   35110       98482 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   35111             :                {
   35112         100 :                   details::free_node(*expr_gen.node_allocator_, branch[1]);
   35113             : 
   35114         100 :                   return expr_gen(T(0));
   35115             :                }
   35116       98382 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   35117           0 :                   return branch[1];
   35118       98382 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   35119           0 :                   return branch[1];
   35120             : 
   35121       98382 :                if (details::is_cob_node(branch[1]))
   35122             :                {
   35123             :                   // Simplify expressions of the form:
   35124             :                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
   35125             :                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
   35126        1461 :                   if (
   35127        1461 :                        (details::e_mul == operation) ||
   35128        1211 :                        (details::e_add == operation)
   35129             :                      )
   35130             :                   {
   35131         841 :                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   35132             : 
   35133         841 :                      if (operation == cobnode->operation())
   35134             :                      {
   35135           0 :                         switch (operation)
   35136             :                         {
   35137           0 :                            case details::e_add : cobnode->set_c(c + cobnode->c()); break;
   35138           0 :                            case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
   35139           0 :                            default             : return error_node();
   35140             :                         }
   35141             : 
   35142           0 :                         return cobnode;
   35143             :                      }
   35144             :                   }
   35145             : 
   35146        1461 :                   if (operation == details::e_mul)
   35147             :                   {
   35148         250 :                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   35149         250 :                      details::operator_type cob_opr = cobnode->operation();
   35150             : 
   35151         250 :                      if (
   35152         250 :                           (details::e_div == cob_opr) ||
   35153             :                           (details::e_mul == cob_opr)
   35154             :                         )
   35155             :                      {
   35156           0 :                         switch (cob_opr)
   35157             :                         {
   35158           0 :                            case details::e_div : cobnode->set_c(c * cobnode->c()); break;
   35159           0 :                            case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
   35160           0 :                            default             : return error_node();
   35161             :                         }
   35162             : 
   35163           0 :                         return cobnode;
   35164             :                      }
   35165             :                   }
   35166        1211 :                   else if (operation == details::e_div)
   35167             :                   {
   35168         250 :                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   35169         250 :                      details::operator_type cob_opr = cobnode->operation();
   35170             : 
   35171         250 :                      if (
   35172         250 :                           (details::e_div == cob_opr) ||
   35173             :                           (details::e_mul == cob_opr)
   35174             :                         )
   35175             :                      {
   35176           0 :                         details::expression_node<Type>* new_cobnode = error_node();
   35177             : 
   35178           0 :                         switch (cob_opr)
   35179             :                         {
   35180           0 :                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
   35181             :                                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
   35182           0 :                                                        (c / cobnode->c(), cobnode->move_branch(0));
   35183           0 :                                                  break;
   35184             : 
   35185           0 :                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
   35186             :                                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   35187           0 :                                                        (c / cobnode->c(), cobnode->move_branch(0));
   35188           0 :                                                  break;
   35189             : 
   35190           0 :                            default             : return error_node();
   35191             :                         }
   35192             : 
   35193           0 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35194             : 
   35195           0 :                         return new_cobnode;
   35196             :                      }
   35197             :                   }
   35198             :                }
   35199             :                #ifndef exprtk_disable_enhanced_features
   35200       96921 :                else if (details::is_sf3ext_node(branch[1]))
   35201             :                {
   35202       28475 :                   expression_node_ptr result = error_node();
   35203             : 
   35204             :                   const bool synthesis_result =
   35205             :                      synthesize_sf4ext_expression::template compile_right<ctype>
   35206       28475 :                         (expr_gen, c, operation, branch[1], result);
   35207             : 
   35208       28475 :                   if (synthesis_result)
   35209             :                   {
   35210       10324 :                      details::free_node(*expr_gen.node_allocator_,branch[1]);
   35211             : 
   35212       10324 :                      return result;
   35213             :                   }
   35214             :                }
   35215             :                #endif
   35216             : 
   35217       88058 :                switch (operation)
   35218             :                {
   35219             :                   #define case_stmt(op0, op1)                                                      \
   35220             :                   case op0 : return expr_gen.node_allocator_->                                     \
   35221             :                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
   35222             :                                    (c,  branch[1]);                                                \
   35223             : 
   35224       87426 :                   basic_opr_switch_statements
   35225         632 :                   extended_opr_switch_statements
   35226             :                   #undef case_stmt
   35227           0 :                   default : return error_node();
   35228             :                }
   35229             :             }
   35230             :          };
   35231             : 
   35232             :          struct synthesize_boc_expression
   35233             :          {
   35234      147008 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35235             :                                                       const details::operator_type& operation,
   35236             :                                                       expression_node_ptr (&branch)[2])
   35237             :             {
   35238      147008 :                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   35239             : 
   35240      147008 :                details::free_node(*(expr_gen.node_allocator_), branch[1]);
   35241             : 
   35242      147008 :                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   35243             :                {
   35244         189 :                   details::free_node(*expr_gen.node_allocator_, branch[0]);
   35245             : 
   35246         189 :                   return expr_gen(T(0));
   35247             :                }
   35248      146819 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   35249             :                {
   35250           1 :                   details::free_node(*expr_gen.node_allocator_, branch[0]);
   35251             : 
   35252           1 :                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
   35253             :                }
   35254      146818 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   35255           1 :                   return branch[0];
   35256      146817 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   35257         104 :                   return branch[0];
   35258             : 
   35259      146713 :                if (details::is_boc_node(branch[0]))
   35260             :                {
   35261             :                   // Simplify expressions of the form:
   35262             :                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
   35263             :                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
   35264        2175 :                   if (
   35265        2175 :                        (details::e_mul == operation) ||
   35266        1857 :                        (details::e_add == operation)
   35267             :                      )
   35268             :                   {
   35269         983 :                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   35270             : 
   35271         983 :                      if (operation == bocnode->operation())
   35272             :                      {
   35273           0 :                         switch (operation)
   35274             :                         {
   35275           0 :                            case details::e_add : bocnode->set_c(c + bocnode->c()); break;
   35276           0 :                            case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
   35277           0 :                            default             : return error_node();
   35278             :                         }
   35279             : 
   35280           0 :                         return bocnode;
   35281             :                      }
   35282         983 :                   }
   35283        1192 :                   else if (operation == details::e_div)
   35284             :                   {
   35285         250 :                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   35286         250 :                      details::operator_type        boc_opr = bocnode->operation();
   35287             : 
   35288         250 :                      if (
   35289         250 :                           (details::e_div == boc_opr) ||
   35290             :                           (details::e_mul == boc_opr)
   35291             :                         )
   35292             :                      {
   35293           0 :                         switch (boc_opr)
   35294             :                         {
   35295           0 :                            case details::e_div : bocnode->set_c(c * bocnode->c()); break;
   35296           0 :                            case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
   35297           0 :                            default             : return error_node();
   35298             :                         }
   35299             : 
   35300           0 :                         return bocnode;
   35301             :                      }
   35302             :                   }
   35303         942 :                   else if (operation == details::e_pow)
   35304             :                   {
   35305             :                      // (v ^ c0) ^ c1 --> v ^(c0 * c1)
   35306           0 :                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   35307           0 :                      details::operator_type        boc_opr = bocnode->operation();
   35308             : 
   35309           0 :                      if (details::e_pow == boc_opr)
   35310             :                      {
   35311           0 :                         bocnode->set_c(bocnode->c() * c);
   35312             : 
   35313           0 :                         return bocnode;
   35314             :                      }
   35315             :                   }
   35316             :                }
   35317             : 
   35318             :                #ifndef exprtk_disable_enhanced_features
   35319      146713 :                if (details::is_sf3ext_node(branch[0]))
   35320             :                {
   35321       48002 :                   expression_node_ptr result = error_node();
   35322             : 
   35323             :                   const bool synthesis_result =
   35324             :                      synthesize_sf4ext_expression::template compile_left<ctype>
   35325       48002 :                         (expr_gen, c, operation, branch[0], result);
   35326             : 
   35327       48002 :                   if (synthesis_result)
   35328             :                   {
   35329        4521 :                      free_node(*expr_gen.node_allocator_, branch[0]);
   35330             : 
   35331        4521 :                      return result;
   35332             :                   }
   35333             :                }
   35334             :                #endif
   35335             : 
   35336      142192 :                switch (operation)
   35337             :                {
   35338             :                   #define case_stmt(op0, op1)                                                      \
   35339             :                   case op0 : return expr_gen.node_allocator_->                                     \
   35340             :                                 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
   35341             :                                    (branch[0], c);                                                 \
   35342             : 
   35343      132439 :                   basic_opr_switch_statements
   35344        9753 :                   extended_opr_switch_statements
   35345             :                   #undef case_stmt
   35346           0 :                   default : return error_node();
   35347             :                }
   35348             :             }
   35349             :          };
   35350             : 
   35351             :          struct synthesize_cocob_expression
   35352             :          {
   35353        7958 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35354             :                                                       const details::operator_type& operation,
   35355             :                                                       expression_node_ptr (&branch)[2])
   35356             :             {
   35357        7958 :                expression_node_ptr result = error_node();
   35358             : 
   35359             :                // (cob) o c --> cob
   35360        7958 :                if (details::is_cob_node(branch[0]))
   35361             :                {
   35362        4757 :                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
   35363             : 
   35364        4757 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   35365             : 
   35366        4757 :                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   35367             :                   {
   35368           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35369           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35370             : 
   35371           0 :                      return expr_gen(T(0));
   35372             :                   }
   35373        4757 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   35374             :                   {
   35375           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35376           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35377             : 
   35378           0 :                      return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
   35379             :                   }
   35380        4757 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   35381             :                   {
   35382           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35383             : 
   35384           0 :                      return branch[0];
   35385             :                   }
   35386        4757 :                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   35387             :                   {
   35388           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35389             : 
   35390           0 :                      return branch[0];
   35391             :                   }
   35392        4757 :                   else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
   35393             :                   {
   35394           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35395             : 
   35396           0 :                      return branch[0];
   35397             :                   }
   35398             : 
   35399        7659 :                   const bool op_addsub = (details::e_add == cobnode->operation()) ||
   35400        2902 :                                          (details::e_sub == cobnode->operation()) ;
   35401             : 
   35402        4757 :                   if (op_addsub)
   35403             :                   {
   35404        2285 :                      switch (operation)
   35405             :                      {
   35406         495 :                         case details::e_add : cobnode->set_c(cobnode->c() + c); break;
   35407        1770 :                         case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
   35408          20 :                         default             : return error_node();
   35409             :                      }
   35410             : 
   35411        2265 :                      result = cobnode;
   35412             :                   }
   35413        2472 :                   else if (details::e_mul == cobnode->operation())
   35414             :                   {
   35415        1822 :                      switch (operation)
   35416             :                      {
   35417         215 :                         case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
   35418        1290 :                         case details::e_div : cobnode->set_c(cobnode->c() / c); break;
   35419         317 :                         default             : return error_node();
   35420             :                      }
   35421             : 
   35422        1505 :                      result = cobnode;
   35423             :                   }
   35424         650 :                   else if (details::e_div == cobnode->operation())
   35425             :                   {
   35426         650 :                      if (details::e_mul == operation)
   35427             :                      {
   35428         215 :                         cobnode->set_c(cobnode->c() * c);
   35429         215 :                         result = cobnode;
   35430             :                      }
   35431         435 :                      else if (details::e_div == operation)
   35432             :                      {
   35433         195 :                         result = expr_gen.node_allocator_->
   35434             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   35435         195 :                                        (cobnode->c() / c, cobnode->move_branch(0));
   35436             : 
   35437         195 :                         details::free_node(*expr_gen.node_allocator_, branch[0]);
   35438             :                      }
   35439             :                   }
   35440             : 
   35441        4420 :                   if (result)
   35442             :                   {
   35443        4180 :                      details::free_node(*expr_gen.node_allocator_,branch[1]);
   35444             :                   }
   35445             :                }
   35446             : 
   35447             :                // c o (cob) --> cob
   35448        3201 :                else if (details::is_cob_node(branch[1]))
   35449             :                {
   35450        3201 :                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   35451             : 
   35452        3201 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   35453             : 
   35454        3201 :                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   35455             :                   {
   35456           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35457           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35458             : 
   35459           0 :                      return expr_gen(T(0));
   35460             :                   }
   35461        3201 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   35462             :                   {
   35463           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35464           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35465             : 
   35466           0 :                      return expr_gen(T(0));
   35467             :                   }
   35468        3201 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   35469             :                   {
   35470           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35471             : 
   35472           0 :                      return branch[1];
   35473             :                   }
   35474        3201 :                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   35475             :                   {
   35476           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   35477             : 
   35478           0 :                      return branch[1];
   35479             :                   }
   35480             : 
   35481        3201 :                   if (details::e_add == cobnode->operation())
   35482             :                   {
   35483         580 :                      if (details::e_add == operation)
   35484             :                      {
   35485         165 :                         cobnode->set_c(c + cobnode->c());
   35486         165 :                         result = cobnode;
   35487             :                      }
   35488         415 :                      else if (details::e_sub == operation)
   35489             :                      {
   35490         165 :                         result = expr_gen.node_allocator_->
   35491             :                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
   35492         165 :                                        (c - cobnode->c(), cobnode->move_branch(0));
   35493             : 
   35494         165 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35495             :                      }
   35496             :                   }
   35497        2621 :                   else if (details::e_sub == cobnode->operation())
   35498             :                   {
   35499         540 :                      if (details::e_add == operation)
   35500             :                      {
   35501         165 :                         cobnode->set_c(c + cobnode->c());
   35502         165 :                         result = cobnode;
   35503             :                      }
   35504         375 :                      else if (details::e_sub == operation)
   35505             :                      {
   35506         125 :                         result = expr_gen.node_allocator_->
   35507             :                                     template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
   35508         125 :                                        (c - cobnode->c(), cobnode->move_branch(0));
   35509             : 
   35510         125 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35511             :                      }
   35512             :                   }
   35513        2081 :                   else if (details::e_mul == cobnode->operation())
   35514             :                   {
   35515        1041 :                      if (details::e_mul == operation)
   35516             :                      {
   35517         335 :                         cobnode->set_c(c * cobnode->c());
   35518         335 :                         result = cobnode;
   35519             :                      }
   35520         706 :                      else if (details::e_div == operation)
   35521             :                      {
   35522         225 :                         result = expr_gen.node_allocator_->
   35523             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   35524         225 :                                        (c / cobnode->c(), cobnode->move_branch(0));
   35525             : 
   35526         225 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35527             :                      }
   35528             :                   }
   35529        1040 :                   else if (details::e_div == cobnode->operation())
   35530             :                   {
   35531        1040 :                      if (details::e_mul == operation)
   35532             :                      {
   35533         335 :                         cobnode->set_c(c * cobnode->c());
   35534         335 :                         result = cobnode;
   35535             :                      }
   35536         705 :                      else if (details::e_div == operation)
   35537             :                      {
   35538         225 :                         result = expr_gen.node_allocator_->
   35539             :                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
   35540         225 :                                        (c / cobnode->c(), cobnode->move_branch(0));
   35541             : 
   35542         225 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35543             :                      }
   35544             :                   }
   35545             : 
   35546        3201 :                   if (result)
   35547             :                   {
   35548        1740 :                      details::free_node(*expr_gen.node_allocator_,branch[0]);
   35549             :                   }
   35550             :                }
   35551             : 
   35552        7621 :                return result;
   35553             :             }
   35554             :          };
   35555             : 
   35556             :          struct synthesize_coboc_expression
   35557             :          {
   35558       24432 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35559             :                                                       const details::operator_type& operation,
   35560             :                                                       expression_node_ptr (&branch)[2])
   35561             :             {
   35562       24432 :                expression_node_ptr result = error_node();
   35563             : 
   35564             :                // (boc) o c --> boc
   35565       24432 :                if (details::is_boc_node(branch[0]))
   35566             :                {
   35567       22177 :                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   35568             : 
   35569       22177 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   35570             : 
   35571       22177 :                   if (details::e_add == bocnode->operation())
   35572             :                   {
   35573        8689 :                      switch (operation)
   35574             :                      {
   35575        4925 :                         case details::e_add : bocnode->set_c(bocnode->c() + c); break;
   35576        3514 :                         case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
   35577         250 :                         default             : return error_node();
   35578             :                      }
   35579             : 
   35580        8439 :                      result = bocnode;
   35581             :                   }
   35582       13488 :                   else if (details::e_mul == bocnode->operation())
   35583             :                   {
   35584        3635 :                      switch (operation)
   35585             :                      {
   35586        1720 :                         case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
   35587        1395 :                         case details::e_div : bocnode->set_c(bocnode->c() / c); break;
   35588         520 :                         default             : return error_node();
   35589             :                      }
   35590             : 
   35591        3115 :                      result = bocnode;
   35592             :                   }
   35593        9853 :                   else if (details::e_sub == bocnode->operation())
   35594             :                   {
   35595        5963 :                      if (details::e_add == operation)
   35596             :                      {
   35597        2339 :                         result = expr_gen.node_allocator_->
   35598             :                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
   35599        2339 :                                        (bocnode->move_branch(0), c - bocnode->c());
   35600             : 
   35601        2339 :                         details::free_node(*expr_gen.node_allocator_,branch[0]);
   35602             :                      }
   35603        3624 :                      else if (details::e_sub == operation)
   35604             :                      {
   35605        3304 :                         bocnode->set_c(bocnode->c() + c);
   35606        3304 :                         result = bocnode;
   35607             :                      }
   35608             :                   }
   35609        3890 :                   else if (details::e_div == bocnode->operation())
   35610             :                   {
   35611        3890 :                      switch (operation)
   35612             :                      {
   35613        2175 :                         case details::e_div : bocnode->set_c(bocnode->c() * c); break;
   35614        1240 :                         case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
   35615         475 :                         default             : return error_node();
   35616             :                      }
   35617             : 
   35618        3415 :                      result = bocnode;
   35619             :                   }
   35620             : 
   35621       20932 :                   if (result)
   35622             :                   {
   35623       20612 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   35624             :                   }
   35625             :                }
   35626             : 
   35627             :                // c o (boc) --> boc
   35628        2255 :                else if (details::is_boc_node(branch[1]))
   35629             :                {
   35630        2255 :                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
   35631             : 
   35632        2255 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   35633             : 
   35634        2255 :                   if (details::e_add == bocnode->operation())
   35635             :                   {
   35636         260 :                      if (details::e_add == operation)
   35637             :                      {
   35638         205 :                         bocnode->set_c(c + bocnode->c());
   35639         205 :                         result = bocnode;
   35640             :                      }
   35641          55 :                      else if (details::e_sub == operation)
   35642             :                      {
   35643          45 :                         result = expr_gen.node_allocator_->
   35644             :                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
   35645          45 :                                        (c - bocnode->c(), bocnode->move_branch(0));
   35646             : 
   35647          45 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35648             :                      }
   35649             :                   }
   35650        1995 :                   else if (details::e_sub == bocnode->operation())
   35651             :                   {
   35652         190 :                      if (details::e_add == operation)
   35653             :                      {
   35654          45 :                         result = expr_gen.node_allocator_->
   35655             :                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
   35656          45 :                                        (bocnode->move_branch(0), c - bocnode->c());
   35657             : 
   35658          45 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35659             :                      }
   35660         145 :                      else if (details::e_sub == operation)
   35661             :                      {
   35662          65 :                         result = expr_gen.node_allocator_->
   35663             :                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
   35664          65 :                                        (c + bocnode->c(), bocnode->move_branch(0));
   35665             : 
   35666          65 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35667             :                      }
   35668             :                   }
   35669        1805 :                   else if (details::e_mul == bocnode->operation())
   35670             :                   {
   35671         895 :                      if (details::e_mul == operation)
   35672             :                      {
   35673         125 :                         bocnode->set_c(c * bocnode->c());
   35674         125 :                         result = bocnode;
   35675             :                      }
   35676         770 :                      else if (details::e_div == operation)
   35677             :                      {
   35678          45 :                         result = expr_gen.node_allocator_->
   35679             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   35680          45 :                                        (c / bocnode->c(), bocnode->move_branch(0));
   35681             : 
   35682          45 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35683             :                      }
   35684             :                   }
   35685         910 :                   else if (details::e_div == bocnode->operation())
   35686             :                   {
   35687         910 :                      if (details::e_mul == operation)
   35688             :                      {
   35689         120 :                         bocnode->set_c(bocnode->c() / c);
   35690         120 :                         result = bocnode;
   35691             :                      }
   35692         790 :                      else if (details::e_div == operation)
   35693             :                      {
   35694         120 :                         result = expr_gen.node_allocator_->
   35695             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   35696         120 :                                        (c * bocnode->c(), bocnode->move_branch(0));
   35697             : 
   35698         120 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   35699             :                      }
   35700             :                   }
   35701             : 
   35702        2255 :                   if (result)
   35703             :                   {
   35704         770 :                      details::free_node(*expr_gen.node_allocator_,branch[0]);
   35705             :                   }
   35706             :                }
   35707             : 
   35708       23187 :                return result;
   35709             :             }
   35710             :          };
   35711             : 
   35712             :          #ifndef exprtk_disable_enhanced_features
   35713     2857634 :          inline bool synthesize_expression(const details::operator_type& operation,
   35714             :                                            expression_node_ptr (&branch)[2],
   35715             :                                            expression_node_ptr& result)
   35716             :          {
   35717     2857634 :             result = error_node();
   35718             : 
   35719     2857634 :             if (!operation_optimisable(operation))
   35720      266483 :                return false;
   35721             : 
   35722     2591151 :             const std::string node_id = branch_to_id(branch);
   35723             : 
   35724     2591151 :             const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
   35725             : 
   35726     2591151 :             if (synthesize_map_.end() != itr)
   35727             :             {
   35728     1313530 :                result = itr->second((*this), operation, branch);
   35729             : 
   35730     1313530 :                return true;
   35731             :             }
   35732             :             else
   35733     1277621 :                return false;
   35734     2591151 :          }
   35735             : 
   35736             :          struct synthesize_vov_expression
   35737             :          {
   35738      253882 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35739             :                                                       const details::operator_type& operation,
   35740             :                                                       expression_node_ptr (&branch)[2])
   35741             :             {
   35742      253882 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   35743      253882 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   35744             : 
   35745      253882 :                switch (operation)
   35746             :                {
   35747             :                   #define case_stmt(op0, op1)                                                      \
   35748             :                   case op0 : return expr_gen.node_allocator_->                                     \
   35749             :                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
   35750             :                                    (v1, v2);                                                       \
   35751             : 
   35752      246637 :                   basic_opr_switch_statements
   35753        7245 :                   extended_opr_switch_statements
   35754             :                   #undef case_stmt
   35755           0 :                   default : return error_node();
   35756             :                }
   35757             :             }
   35758             :          };
   35759             : 
   35760             :          struct synthesize_cov_expression
   35761             :          {
   35762      207749 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35763             :                                                       const details::operator_type& operation,
   35764             :                                                       expression_node_ptr (&branch)[2])
   35765             :             {
   35766      207749 :                const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
   35767      207749 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref  ();
   35768             : 
   35769      207749 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35770             : 
   35771      207749 :                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   35772         191 :                   return expr_gen(T(0));
   35773      207558 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   35774          60 :                   return expr_gen(T(0));
   35775      207498 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   35776          61 :                   return static_cast<details::variable_node<Type>*>(branch[1]);
   35777      207437 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   35778         202 :                   return static_cast<details::variable_node<Type>*>(branch[1]);
   35779             : 
   35780      207235 :                switch (operation)
   35781             :                {
   35782             :                   #define case_stmt(op0, op1)                                                      \
   35783             :                   case op0 : return expr_gen.node_allocator_->                                     \
   35784             :                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
   35785             :                                    (c, v);                                                         \
   35786             : 
   35787      207127 :                   basic_opr_switch_statements
   35788         108 :                   extended_opr_switch_statements
   35789             :                   #undef case_stmt
   35790           0 :                   default : return error_node();
   35791             :                }
   35792             :             }
   35793             :          };
   35794             : 
   35795             :          struct synthesize_voc_expression
   35796             :          {
   35797      356546 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35798             :                                                       const details::operator_type& operation,
   35799             :                                                       expression_node_ptr (&branch)[2])
   35800             :             {
   35801      356546 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref  ();
   35802      356546 :                const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
   35803             : 
   35804      356546 :                details::free_node(*(expr_gen.node_allocator_), branch[1]);
   35805             : 
   35806      356546 :                if (expr_gen.cardinal_pow_optimisable(operation,c))
   35807             :                {
   35808       85877 :                   if (std::equal_to<T>()(T(1),c))
   35809       12180 :                      return branch[0];
   35810             :                   else
   35811       73697 :                      return expr_gen.cardinal_pow_optimisation(v,c);
   35812             :                }
   35813      270669 :                else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   35814         180 :                   return expr_gen(T(0));
   35815      270489 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   35816           0 :                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
   35817      270489 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   35818         541 :                   return static_cast<details::variable_node<Type>*>(branch[0]);
   35819      269948 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   35820         193 :                   return static_cast<details::variable_node<Type>*>(branch[0]);
   35821      269755 :                else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
   35822          60 :                   return static_cast<details::variable_node<Type>*>(branch[0]);
   35823             : 
   35824      269695 :                switch (operation)
   35825             :                {
   35826             :                   #define case_stmt(op0, op1)                                                      \
   35827             :                   case op0 : return expr_gen.node_allocator_->                                     \
   35828             :                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
   35829             :                                    (v, c);                                                         \
   35830             : 
   35831      257499 :                   basic_opr_switch_statements
   35832       12196 :                   extended_opr_switch_statements
   35833             :                   #undef case_stmt
   35834           0 :                   default : return error_node();
   35835             :                }
   35836             :             }
   35837             :          };
   35838             : 
   35839             :          struct synthesize_sf3ext_expression
   35840             :          {
   35841             :             template <typename T0, typename T1, typename T2>
   35842      371080 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35843             :                                                       const details::operator_type& sf3opr,
   35844             :                                                       T0 t0, T1 t1, T2 t2)
   35845             :             {
   35846      371080 :                switch (sf3opr)
   35847             :                {
   35848             :                   #define case_stmt(op)                                                                              \
   35849             :                   case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
   35850             :                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2);                                   \
   35851             : 
   35852       37586 :                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   35853       36683 :                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   35854       98389 :                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   35855       44413 :                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   35856       52190 :                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   35857       42972 :                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   35858       38570 :                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   35859       20277 :                   case_stmt(28) case_stmt(29) case_stmt(30)
   35860             :                   #undef case_stmt
   35861           0 :                   default : return error_node();
   35862             :                }
   35863             :             }
   35864             : 
   35865             :             template <typename T0, typename T1, typename T2>
   35866      377040 :             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
   35867             :                                        T0 t0, T1 t1, T2 t2,
   35868             :                                        expression_node_ptr& result)
   35869             :             {
   35870             :                details::operator_type sf3opr;
   35871             : 
   35872      377040 :                if (!expr_gen.sf3_optimisable(id,sf3opr))
   35873        5960 :                   return false;
   35874             :                else
   35875      371080 :                   result = synthesize_sf3ext_expression::template process<T0, T1, T2>
   35876      371080 :                               (expr_gen, sf3opr, t0, t1, t2);
   35877             : 
   35878      371080 :                return true;
   35879             :             }
   35880             :          };
   35881             : 
   35882             :          struct synthesize_sf4ext_expression
   35883             :          {
   35884             :             template <typename T0, typename T1, typename T2, typename T3>
   35885       97884 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35886             :                                                       const details::operator_type& sf4opr,
   35887             :                                                       T0 t0, T1 t1, T2 t2, T3 t3)
   35888             :             {
   35889       97884 :                switch (sf4opr)
   35890             :                {
   35891             :                   #define case_stmt0(op)                                                                                      \
   35892             :                   case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
   35893             :                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                        \
   35894             : 
   35895             :                   #define case_stmt1(op)                                                                                             \
   35896             :                   case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
   35897             :                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                               \
   35898             : 
   35899        3540 :                   case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
   35900        5065 :                   case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
   35901        4399 :                   case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
   35902        4475 :                   case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
   35903        4711 :                   case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
   35904        4810 :                   case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
   35905        4733 :                   case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
   35906        5911 :                   case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
   35907        3470 :                   case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
   35908             : 
   35909        6670 :                   case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
   35910        6550 :                   case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
   35911        2725 :                   case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
   35912        3770 :                   case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
   35913        3385 :                   case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
   35914        3340 :                   case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
   35915        3500 :                   case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
   35916        3115 :                   case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
   35917        3560 :                   case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
   35918        2630 :                   case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
   35919        1990 :                   case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
   35920        6400 :                   case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
   35921         640 :                   case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
   35922        1590 :                   case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
   35923        1720 :                   case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
   35924        5185 :                   case_stmt1(60) case_stmt1(61)
   35925             : 
   35926             :                   #undef case_stmt0
   35927             :                   #undef case_stmt1
   35928           0 :                   default : return error_node();
   35929             :                }
   35930             :             }
   35931             : 
   35932             :             template <typename T0, typename T1, typename T2, typename T3>
   35933      243720 :             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
   35934             :                                        T0 t0, T1 t1, T2 t2, T3 t3,
   35935             :                                        expression_node_ptr& result)
   35936             :             {
   35937             :                details::operator_type sf4opr;
   35938             : 
   35939      243720 :                if (!expr_gen.sf4_optimisable(id,sf4opr))
   35940      145836 :                   return false;
   35941             :                else
   35942       97884 :                   result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
   35943       97884 :                               (expr_gen, sf4opr, t0, t1, t2, t3);
   35944             : 
   35945       97884 :                return true;
   35946             :             }
   35947             : 
   35948             :             // T o (sf3ext)
   35949             :             template <typename ExternalType>
   35950       65535 :             static inline bool compile_right(expression_generator<Type>& expr_gen,
   35951             :                                              ExternalType t,
   35952             :                                              const details::operator_type& operation,
   35953             :                                              expression_node_ptr& sf3node,
   35954             :                                              expression_node_ptr& result)
   35955             :             {
   35956       65535 :                if (!details::is_sf3ext_node(sf3node))
   35957           0 :                   return false;
   35958             : 
   35959             :                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
   35960             : 
   35961       65535 :                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
   35962       65535 :                const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
   35963             : 
   35964       65535 :                switch (n->type())
   35965             :                {
   35966        2785 :                   case details::expression_node<Type>::e_covoc : return compile_right_impl
   35967             :                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
   35968        2785 :                                                                        (expr_gen, id, t, sf3node, result);
   35969             : 
   35970       14845 :                   case details::expression_node<Type>::e_covov : return compile_right_impl
   35971             :                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
   35972       14845 :                                                                        (expr_gen, id, t, sf3node, result);
   35973             : 
   35974       15450 :                   case details::expression_node<Type>::e_vocov : return compile_right_impl
   35975             :                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
   35976       15450 :                                                                        (expr_gen, id, t, sf3node, result);
   35977             : 
   35978       15375 :                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
   35979             :                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
   35980       15375 :                                                                        (expr_gen, id, t, sf3node, result);
   35981             : 
   35982       17080 :                   case details::expression_node<Type>::e_vovov : return compile_right_impl
   35983             :                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
   35984       17080 :                                                                        (expr_gen, id, t, sf3node, result);
   35985             : 
   35986           0 :                   default                                      : return false;
   35987             :                }
   35988       65535 :             }
   35989             : 
   35990             :             // (sf3ext) o T
   35991             :             template <typename ExternalType>
   35992      115664 :             static inline bool compile_left(expression_generator<Type>& expr_gen,
   35993             :                                             ExternalType t,
   35994             :                                             const details::operator_type& operation,
   35995             :                                             expression_node_ptr& sf3node,
   35996             :                                             expression_node_ptr& result)
   35997             :             {
   35998      115664 :                if (!details::is_sf3ext_node(sf3node))
   35999           0 :                   return false;
   36000             : 
   36001             :                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
   36002             : 
   36003      115664 :                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
   36004             : 
   36005      115664 :                const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
   36006             : 
   36007      115664 :                switch (n->type())
   36008             :                {
   36009        4480 :                   case details::expression_node<Type>::e_covoc : return compile_left_impl
   36010             :                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
   36011        4480 :                                                                        (expr_gen, id, t, sf3node, result);
   36012             : 
   36013       27465 :                   case details::expression_node<Type>::e_covov : return compile_left_impl
   36014             :                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
   36015       27465 :                                                                        (expr_gen, id, t, sf3node, result);
   36016             : 
   36017       24883 :                   case details::expression_node<Type>::e_vocov : return compile_left_impl
   36018             :                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
   36019       24883 :                                                                        (expr_gen, id, t, sf3node, result);
   36020             : 
   36021       25960 :                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
   36022             :                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
   36023       25960 :                                                                        (expr_gen, id, t, sf3node, result);
   36024             : 
   36025       32876 :                   case details::expression_node<Type>::e_vovov : return compile_left_impl
   36026             :                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
   36027       32876 :                                                                        (expr_gen, id, t, sf3node, result);
   36028             : 
   36029           0 :                   default                                      : return false;
   36030             :                }
   36031      115664 :             }
   36032             : 
   36033             :             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
   36034       65535 :             static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
   36035             :                                                   const std::string& id,
   36036             :                                                   ExternalType t,
   36037             :                                                   expression_node_ptr& node,
   36038             :                                                   expression_node_ptr& result)
   36039             :             {
   36040       65535 :                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
   36041             : 
   36042       65535 :                if (n)
   36043             :                {
   36044       65535 :                   T0 t0 = n->t0();
   36045       65535 :                   T1 t1 = n->t1();
   36046       65535 :                   T2 t2 = n->t2();
   36047             : 
   36048             :                   return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
   36049       65535 :                             (expr_gen, id, t, t0, t1, t2, result);
   36050             :                }
   36051             :                else
   36052           0 :                   return false;
   36053             :             }
   36054             : 
   36055             :             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
   36056      115664 :             static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
   36057             :                                                  const std::string& id,
   36058             :                                                  ExternalType t,
   36059             :                                                  expression_node_ptr& node,
   36060             :                                                  expression_node_ptr& result)
   36061             :             {
   36062      115664 :                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
   36063             : 
   36064      115664 :                if (n)
   36065             :                {
   36066      115664 :                   T0 t0 = n->t0();
   36067      115664 :                   T1 t1 = n->t1();
   36068      115664 :                   T2 t2 = n->t2();
   36069             : 
   36070             :                   return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
   36071      115664 :                             (expr_gen, id, t0, t1, t2, t, result);
   36072             :                }
   36073             :                else
   36074           0 :                   return false;
   36075             :             }
   36076             :          };
   36077             : 
   36078             :          struct synthesize_vovov_expression0
   36079             :          {
   36080             :             typedef typename vovov_t::type0 node_type;
   36081             :             typedef typename vovov_t::sf3_type sf3_type;
   36082             : 
   36083       58637 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36084             :                                                       const details::operator_type& operation,
   36085             :                                                       expression_node_ptr (&branch)[2])
   36086             :             {
   36087             :                // (v0 o0 v1) o1 (v2)
   36088       58637 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   36089       58637 :                const Type& v0 = vov->v0();
   36090       58637 :                const Type& v1 = vov->v1();
   36091       58637 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   36092       58637 :                const details::operator_type o0 = vov->operation();
   36093       58637 :                const details::operator_type o1 = operation;
   36094             : 
   36095       58637 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36096             : 
   36097       58637 :                expression_node_ptr result = error_node();
   36098             : 
   36099       58637 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36100             :                {
   36101             :                   // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
   36102       58637 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36103             :                   {
   36104             :                      const bool synthesis_result =
   36105             :                         synthesize_sf3ext_expression::
   36106        8265 :                            template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
   36107             : 
   36108             :                      exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
   36109             : 
   36110        8265 :                      return (synthesis_result) ? result : error_node();
   36111             :                   }
   36112             :                }
   36113             : 
   36114             :                const bool synthesis_result =
   36115             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
   36116       50372 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
   36117             : 
   36118       50372 :                if (synthesis_result)
   36119       49577 :                   return result;
   36120             : 
   36121         795 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36122         795 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36123             : 
   36124         795 :                if (!expr_gen.valid_operator(o0,f0))
   36125           0 :                   return error_node();
   36126         795 :                else if (!expr_gen.valid_operator(o1,f1))
   36127           0 :                   return error_node();
   36128             :                else
   36129         795 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
   36130             :             }
   36131             : 
   36132       50372 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36133             :                                          const details::operator_type o0,
   36134             :                                          const details::operator_type o1)
   36135             :             {
   36136      100744 :                return details::build_string()
   36137      100744 :                   << "(t" << expr_gen.to_str(o0)
   36138      100744 :                   << "t)" << expr_gen.to_str(o1)
   36139      100744 :                   << "t";
   36140             :             }
   36141             :          };
   36142             : 
   36143             :          struct synthesize_vovov_expression1
   36144             :          {
   36145             :             typedef typename vovov_t::type1 node_type;
   36146             :             typedef typename vovov_t::sf3_type sf3_type;
   36147             : 
   36148       21729 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36149             :                                                       const details::operator_type& operation,
   36150             :                                                       expression_node_ptr (&branch)[2])
   36151             :             {
   36152             :                // (v0) o0 (v1 o1 v2)
   36153       21729 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   36154       21729 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   36155       21729 :                const Type& v1 = vov->v0();
   36156       21729 :                const Type& v2 = vov->v1();
   36157       21729 :                const details::operator_type o0 = operation;
   36158       21729 :                const details::operator_type o1 = vov->operation();
   36159             : 
   36160       21729 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36161             : 
   36162       21729 :                expression_node_ptr result = error_node();
   36163             : 
   36164       21729 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36165             :                {
   36166             :                   // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
   36167       21729 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36168             :                   {
   36169             :                      const bool synthesis_result =
   36170             :                         synthesize_sf3ext_expression::
   36171        1190 :                            template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
   36172             : 
   36173             :                      exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
   36174             : 
   36175        1190 :                      return (synthesis_result) ? result : error_node();
   36176             :                   }
   36177             :                }
   36178             : 
   36179             :                const bool synthesis_result =
   36180             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
   36181       20539 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
   36182             : 
   36183       20539 :                if (synthesis_result)
   36184       20409 :                   return result;
   36185             : 
   36186         130 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36187         130 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36188             : 
   36189         130 :                if (!expr_gen.valid_operator(o0,f0))
   36190           0 :                   return error_node();
   36191         130 :                else if (!expr_gen.valid_operator(o1,f1))
   36192           0 :                   return error_node();
   36193             :                else
   36194         130 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
   36195             :             }
   36196             : 
   36197       20539 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36198             :                                          const details::operator_type o0,
   36199             :                                          const details::operator_type o1)
   36200             :             {
   36201       41078 :                return details::build_string()
   36202       41078 :                   << "t"  << expr_gen.to_str(o0)
   36203       41078 :                   << "(t" << expr_gen.to_str(o1)
   36204       41078 :                   << "t)";
   36205             :             }
   36206             :          };
   36207             : 
   36208             :          struct synthesize_vovoc_expression0
   36209             :          {
   36210             :             typedef typename vovoc_t::type0 node_type;
   36211             :             typedef typename vovoc_t::sf3_type sf3_type;
   36212             : 
   36213       47502 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36214             :                                                       const details::operator_type& operation,
   36215             :                                                       expression_node_ptr (&branch)[2])
   36216             :             {
   36217             :                // (v0 o0 v1) o1 (c)
   36218       47502 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   36219       47502 :                const Type& v0 = vov->v0();
   36220       47502 :                const Type& v1 = vov->v1();
   36221       47502 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   36222       47502 :                const details::operator_type o0 = vov->operation();
   36223       47502 :                const details::operator_type o1 = operation;
   36224             : 
   36225       47502 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36226       47502 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36227             : 
   36228       47502 :                expression_node_ptr result = error_node();
   36229             : 
   36230       47502 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36231             :                {
   36232             :                   // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
   36233       47502 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36234             :                   {
   36235             :                      const bool synthesis_result =
   36236             :                         synthesize_sf3ext_expression::
   36237        6705 :                            template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
   36238             : 
   36239             :                      exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
   36240             : 
   36241        6705 :                      return (synthesis_result) ? result : error_node();
   36242             :                   }
   36243             :                }
   36244             : 
   36245             :                const bool synthesis_result =
   36246             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
   36247       40797 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
   36248             : 
   36249       40797 :                if (synthesis_result)
   36250       40033 :                   return result;
   36251             : 
   36252         764 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36253         764 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36254             : 
   36255         764 :                if (!expr_gen.valid_operator(o0,f0))
   36256           0 :                   return error_node();
   36257         764 :                else if (!expr_gen.valid_operator(o1,f1))
   36258           0 :                   return error_node();
   36259             :                else
   36260         764 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
   36261             :             }
   36262             : 
   36263       40797 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36264             :                                          const details::operator_type o0,
   36265             :                                          const details::operator_type o1)
   36266             :             {
   36267       81594 :                return details::build_string()
   36268       81594 :                   << "(t" << expr_gen.to_str(o0)
   36269       81594 :                   << "t)" << expr_gen.to_str(o1)
   36270       81594 :                   << "t";
   36271             :             }
   36272             :          };
   36273             : 
   36274             :          struct synthesize_vovoc_expression1
   36275             :          {
   36276             :             typedef typename vovoc_t::type1 node_type;
   36277             :             typedef typename vovoc_t::sf3_type sf3_type;
   36278             : 
   36279       24765 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36280             :                                                       const details::operator_type& operation,
   36281             :                                                       expression_node_ptr (&branch)[2])
   36282             :             {
   36283             :                // (v0) o0 (v1 o1 c)
   36284       24765 :                const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
   36285       24765 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   36286       24765 :                const Type& v1 = voc->v();
   36287       24765 :                const Type   c = voc->c();
   36288       24765 :                const details::operator_type o0 = operation;
   36289       24765 :                const details::operator_type o1 = voc->operation();
   36290             : 
   36291       24765 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36292             : 
   36293       24765 :                expression_node_ptr result = error_node();
   36294             : 
   36295       24765 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36296             :                {
   36297             :                   // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
   36298       24765 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36299             :                   {
   36300             :                      const bool synthesis_result =
   36301             :                         synthesize_sf3ext_expression::
   36302        1365 :                            template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
   36303             : 
   36304             :                      exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
   36305             : 
   36306        1365 :                      return (synthesis_result) ? result : error_node();
   36307             :                   }
   36308             :                }
   36309             : 
   36310             :                const bool synthesis_result =
   36311             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
   36312       23400 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
   36313             : 
   36314       23400 :                if (synthesis_result)
   36315       23190 :                   return result;
   36316             : 
   36317         210 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36318         210 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36319             : 
   36320         210 :                if (!expr_gen.valid_operator(o0,f0))
   36321           0 :                   return error_node();
   36322         210 :                else if (!expr_gen.valid_operator(o1,f1))
   36323           0 :                   return error_node();
   36324             :                else
   36325         210 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
   36326             :             }
   36327             : 
   36328       23400 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36329             :                                          const details::operator_type o0,
   36330             :                                          const details::operator_type o1)
   36331             :             {
   36332       46800 :                return details::build_string()
   36333       46800 :                   << "t"  << expr_gen.to_str(o0)
   36334       46800 :                   << "(t" << expr_gen.to_str(o1)
   36335       46800 :                   << "t)";
   36336             :             }
   36337             :          };
   36338             : 
   36339             :          struct synthesize_vocov_expression0
   36340             :          {
   36341             :             typedef typename vocov_t::type0 node_type;
   36342             :             typedef typename vocov_t::sf3_type sf3_type;
   36343             : 
   36344       52969 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36345             :                                                       const details::operator_type& operation,
   36346             :                                                       expression_node_ptr (&branch)[2])
   36347             :             {
   36348             :                // (v0 o0 c) o1 (v1)
   36349       52969 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   36350       52969 :                const Type& v0 = voc->v();
   36351       52969 :                const Type   c = voc->c();
   36352       52969 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   36353       52969 :                const details::operator_type o0 = voc->operation();
   36354       52969 :                const details::operator_type o1 = operation;
   36355             : 
   36356       52969 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36357             : 
   36358       52969 :                expression_node_ptr result = error_node();
   36359             : 
   36360       52969 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36361             :                {
   36362             :                   // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
   36363       52969 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36364             :                   {
   36365             :                      const bool synthesis_result =
   36366             :                         synthesize_sf3ext_expression::
   36367        7400 :                            template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
   36368             : 
   36369             :                      exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
   36370             : 
   36371        7400 :                      return (synthesis_result) ? result : error_node();
   36372             :                   }
   36373             :                }
   36374             : 
   36375             :                const bool synthesis_result =
   36376             :                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
   36377       45569 :                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
   36378             : 
   36379       45569 :                if (synthesis_result)
   36380       45539 :                   return result;
   36381             : 
   36382          30 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36383          30 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36384             : 
   36385          30 :                if (!expr_gen.valid_operator(o0,f0))
   36386           0 :                   return error_node();
   36387          30 :                else if (!expr_gen.valid_operator(o1,f1))
   36388           0 :                   return error_node();
   36389             :                else
   36390          30 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
   36391             :             }
   36392             : 
   36393       45569 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36394             :                                          const details::operator_type o0,
   36395             :                                          const details::operator_type o1)
   36396             :             {
   36397       91138 :                return details::build_string()
   36398       91138 :                   << "(t" << expr_gen.to_str(o0)
   36399       91138 :                   << "t)" << expr_gen.to_str(o1)
   36400       91138 :                   << "t";
   36401             :             }
   36402             :          };
   36403             : 
   36404             :          struct synthesize_vocov_expression1
   36405             :          {
   36406             :             typedef typename vocov_t::type1 node_type;
   36407             :             typedef typename vocov_t::sf3_type sf3_type;
   36408             : 
   36409       28421 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36410             :                                                       const details::operator_type& operation,
   36411             :                                                       expression_node_ptr (&branch)[2])
   36412             :             {
   36413             :                // (v0) o0 (c o1 v1)
   36414       28421 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   36415       28421 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   36416       28421 :                const Type   c = cov->c();
   36417       28421 :                const Type& v1 = cov->v();
   36418       28421 :                const details::operator_type o0 = operation;
   36419       28421 :                const details::operator_type o1 = cov->operation();
   36420             : 
   36421       28421 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36422             : 
   36423       28421 :                expression_node_ptr result = error_node();
   36424             : 
   36425       28421 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36426             :                {
   36427             :                   // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
   36428       28421 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36429             :                   {
   36430             :                      const bool synthesis_result =
   36431             :                         synthesize_sf3ext_expression::
   36432        1565 :                            template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
   36433             : 
   36434             :                      exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
   36435             : 
   36436        1565 :                      return (synthesis_result) ? result : error_node();
   36437             :                   }
   36438             :                }
   36439             : 
   36440             :                const bool synthesis_result =
   36441             :                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
   36442       26856 :                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
   36443             : 
   36444       26856 :                if (synthesis_result)
   36445       26765 :                   return result;
   36446             : 
   36447          91 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36448          91 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36449             : 
   36450          91 :                if (!expr_gen.valid_operator(o0,f0))
   36451           0 :                   return error_node();
   36452          91 :                else if (!expr_gen.valid_operator(o1,f1))
   36453           0 :                   return error_node();
   36454             :                else
   36455          91 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
   36456             :             }
   36457             : 
   36458       26856 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36459             :                                          const details::operator_type o0,
   36460             :                                          const details::operator_type o1)
   36461             :             {
   36462       53712 :                return details::build_string()
   36463       53712 :                   << "t"  << expr_gen.to_str(o0)
   36464       53712 :                   << "(t" << expr_gen.to_str(o1)
   36465       53712 :                   << "t)";
   36466             :             }
   36467             :          };
   36468             : 
   36469             :          struct synthesize_covov_expression0
   36470             :          {
   36471             :             typedef typename covov_t::type0 node_type;
   36472             :             typedef typename covov_t::sf3_type sf3_type;
   36473             : 
   36474       57476 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36475             :                                                       const details::operator_type& operation,
   36476             :                                                       expression_node_ptr (&branch)[2])
   36477             :             {
   36478             :                // (c o0 v0) o1 (v1)
   36479       57476 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   36480       57476 :                const Type   c = cov->c();
   36481       57476 :                const Type& v0 = cov->v();
   36482       57476 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   36483       57476 :                const details::operator_type o0 = cov->operation();
   36484       57476 :                const details::operator_type o1 = operation;
   36485             : 
   36486       57476 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36487             : 
   36488       57476 :                expression_node_ptr result = error_node();
   36489             : 
   36490       57476 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36491             :                {
   36492             :                   // (c / v0) / v1 --> (covov) c / (v0 * v1)
   36493       57476 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36494             :                   {
   36495             :                      const bool synthesis_result =
   36496             :                         synthesize_sf3ext_expression::
   36497        8415 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
   36498             : 
   36499             :                      exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
   36500             : 
   36501        8415 :                      return (synthesis_result) ? result : error_node();
   36502             :                   }
   36503             :                }
   36504             : 
   36505             :                const bool synthesis_result =
   36506             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
   36507       49061 :                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
   36508             : 
   36509       49061 :                if (synthesis_result)
   36510       49061 :                   return result;
   36511             : 
   36512           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36513           0 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36514             : 
   36515           0 :                if (!expr_gen.valid_operator(o0,f0))
   36516           0 :                   return error_node();
   36517           0 :                else if (!expr_gen.valid_operator(o1,f1))
   36518           0 :                   return error_node();
   36519             :                else
   36520           0 :                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
   36521             :             }
   36522             : 
   36523       49061 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36524             :                                          const details::operator_type o0,
   36525             :                                          const details::operator_type o1)
   36526             :             {
   36527       98122 :                return details::build_string()
   36528       98122 :                   << "(t" << expr_gen.to_str(o0)
   36529       98122 :                   << "t)" << expr_gen.to_str(o1)
   36530       98122 :                   << "t";
   36531             :             }
   36532             :          };
   36533             : 
   36534             :          struct synthesize_covov_expression1
   36535             :          {
   36536             :             typedef typename covov_t::type1 node_type;
   36537             :             typedef typename covov_t::sf3_type sf3_type;
   36538             : 
   36539       35209 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36540             :                                                       const details::operator_type& operation,
   36541             :                                                       expression_node_ptr (&branch)[2])
   36542             :             {
   36543             :                // (c) o0 (v0 o1 v1)
   36544       35209 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   36545       35209 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   36546       35209 :                const Type& v0 = vov->v0();
   36547       35209 :                const Type& v1 = vov->v1();
   36548       35209 :                const details::operator_type o0 = operation;
   36549       35209 :                const details::operator_type o1 = vov->operation();
   36550             : 
   36551       35209 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36552       35209 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36553             : 
   36554       35209 :                expression_node_ptr result = error_node();
   36555             : 
   36556       35209 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36557             :                {
   36558             :                   // c / (v0 / v1) --> (covov) (c * v1) / v0
   36559       35209 :                   if ((details::e_div == o0) && (details::e_div == o1))
   36560             :                   {
   36561             :                      const bool synthesis_result =
   36562             :                         synthesize_sf3ext_expression::
   36563        1325 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
   36564             : 
   36565             :                      exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
   36566             : 
   36567        1325 :                      return (synthesis_result) ? result : error_node();
   36568             :                   }
   36569             :                }
   36570             : 
   36571             :                const bool synthesis_result =
   36572             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
   36573       33884 :                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
   36574             : 
   36575       33884 :                if (synthesis_result)
   36576       33823 :                   return result;
   36577             : 
   36578          61 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36579          61 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36580             : 
   36581          61 :                if (!expr_gen.valid_operator(o0,f0))
   36582           0 :                   return error_node();
   36583          61 :                else if (!expr_gen.valid_operator(o1,f1))
   36584           0 :                   return error_node();
   36585             :                else
   36586          61 :                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
   36587             :             }
   36588             : 
   36589       33884 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36590             :                                          const details::operator_type o0,
   36591             :                                          const details::operator_type o1)
   36592             :             {
   36593       67768 :                return details::build_string()
   36594       67768 :                   << "t"  << expr_gen.to_str(o0)
   36595       67768 :                   << "(t" << expr_gen.to_str(o1)
   36596       67768 :                   << "t)";
   36597             :             }
   36598             :          };
   36599             : 
   36600             :          struct synthesize_covoc_expression0
   36601             :          {
   36602             :             typedef typename covoc_t::type0 node_type;
   36603             :             typedef typename covoc_t::sf3_type sf3_type;
   36604             : 
   36605       40734 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36606             :                                                       const details::operator_type& operation,
   36607             :                                                       expression_node_ptr (&branch)[2])
   36608             :             {
   36609             :                // (c0 o0 v) o1 (c1)
   36610       40734 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   36611       40734 :                const Type  c0 = cov->c();
   36612       40734 :                const Type&  v = cov->v();
   36613       40734 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   36614       40734 :                const details::operator_type o0 = cov->operation();
   36615       40734 :                const details::operator_type o1 = operation;
   36616             : 
   36617       40734 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36618       40734 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36619             : 
   36620       40734 :                expression_node_ptr result = error_node();
   36621             : 
   36622       40734 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36623             :                {
   36624             :                   // (c0 + v) + c1 --> (cov) (c0 + c1) + v
   36625       40734 :                   if ((details::e_add == o0) && (details::e_add == o1))
   36626             :                   {
   36627             :                      exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
   36628             : 
   36629        2727 :                      return expr_gen.node_allocator_->
   36630        2727 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
   36631             :                   }
   36632             :                   // (c0 + v) - c1 --> (cov) (c0 - c1) + v
   36633       38007 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   36634             :                   {
   36635             :                      exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
   36636             : 
   36637        2206 :                      return expr_gen.node_allocator_->
   36638        2206 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
   36639             :                   }
   36640             :                   // (c0 - v) + c1 --> (cov) (c0 + c1) - v
   36641       35801 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   36642             :                   {
   36643             :                      exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
   36644             : 
   36645        1760 :                      return expr_gen.node_allocator_->
   36646        1760 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
   36647             :                   }
   36648             :                   // (c0 - v) - c1 --> (cov) (c0 - c1) - v
   36649       34041 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   36650             :                   {
   36651             :                      exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
   36652             : 
   36653        1991 :                      return expr_gen.node_allocator_->
   36654        1991 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
   36655             :                   }
   36656             :                   // (c0 * v) * c1 --> (cov) (c0 * c1) * v
   36657       32050 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   36658             :                   {
   36659             :                      exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
   36660             : 
   36661        3375 :                      return expr_gen.node_allocator_->
   36662        3375 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
   36663             :                   }
   36664             :                   // (c0 * v) / c1 --> (cov) (c0 / c1) * v
   36665       28675 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   36666             :                   {
   36667             :                      exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
   36668             : 
   36669        3097 :                      return expr_gen.node_allocator_->
   36670        3097 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
   36671             :                   }
   36672             :                   // (c0 / v) * c1 --> (cov) (c0 * c1) / v
   36673       25578 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   36674             :                   {
   36675             :                      exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
   36676             : 
   36677        3290 :                      return expr_gen.node_allocator_->
   36678        3290 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
   36679             :                   }
   36680             :                   // (c0 / v) / c1 --> (cov) (c0 / c1) / v
   36681       22288 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   36682             :                   {
   36683             :                      exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
   36684             : 
   36685        3845 :                      return expr_gen.node_allocator_->
   36686        3845 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
   36687             :                   }
   36688             :                }
   36689             : 
   36690             :                const bool synthesis_result =
   36691             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
   36692       18443 :                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
   36693             : 
   36694       18443 :                if (synthesis_result)
   36695       16833 :                   return result;
   36696             : 
   36697        1610 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36698        1610 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36699             : 
   36700        1610 :                if (!expr_gen.valid_operator(o0,f0))
   36701           0 :                   return error_node();
   36702        1610 :                else if (!expr_gen.valid_operator(o1,f1))
   36703           0 :                   return error_node();
   36704             :                else
   36705        1610 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
   36706             :             }
   36707             : 
   36708       18443 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36709             :                                          const details::operator_type o0,
   36710             :                                          const details::operator_type o1)
   36711             :             {
   36712       36886 :                return details::build_string()
   36713       36886 :                   << "(t" << expr_gen.to_str(o0)
   36714       36886 :                   << "t)" << expr_gen.to_str(o1)
   36715       36886 :                   << "t";
   36716             :             }
   36717             :          };
   36718             : 
   36719             :          struct synthesize_covoc_expression1
   36720             :          {
   36721             :             typedef typename covoc_t::type1 node_type;
   36722             :             typedef typename covoc_t::sf3_type sf3_type;
   36723             : 
   36724       14571 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36725             :                                                       const details::operator_type& operation,
   36726             :                                                       expression_node_ptr (&branch)[2])
   36727             :             {
   36728             :                // (c0) o0 (v o1 c1)
   36729       14571 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
   36730       14571 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   36731       14571 :                const Type&  v = voc->v();
   36732       14571 :                const Type  c1 = voc->c();
   36733       14571 :                const details::operator_type o0 = operation;
   36734       14571 :                const details::operator_type o1 = voc->operation();
   36735             : 
   36736       14571 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36737       14571 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36738             : 
   36739       14571 :                expression_node_ptr result = error_node();
   36740             : 
   36741       14571 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36742             :                {
   36743             :                   // (c0) + (v + c1) --> (cov) (c0 + c1) + v
   36744       14571 :                   if ((details::e_add == o0) && (details::e_add == o1))
   36745             :                   {
   36746             :                      exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
   36747             : 
   36748         885 :                      return expr_gen.node_allocator_->
   36749         885 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
   36750             :                   }
   36751             :                   // (c0) + (v - c1) --> (cov) (c0 - c1) + v
   36752       13686 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   36753             :                   {
   36754             :                      exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
   36755             : 
   36756         865 :                      return expr_gen.node_allocator_->
   36757         865 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
   36758             :                   }
   36759             :                   // (c0) - (v + c1) --> (cov) (c0 - c1) - v
   36760       12821 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   36761             :                   {
   36762             :                      exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
   36763             : 
   36764         855 :                      return expr_gen.node_allocator_->
   36765         855 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
   36766             :                   }
   36767             :                   // (c0) - (v - c1) --> (cov) (c0 + c1) - v
   36768       11966 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   36769             :                   {
   36770             :                      exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
   36771             : 
   36772         835 :                      return expr_gen.node_allocator_->
   36773         835 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
   36774             :                   }
   36775             :                   // (c0) * (v * c1) --> (voc) v * (c0 * c1)
   36776       11131 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   36777             :                   {
   36778             :                      exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
   36779             : 
   36780         875 :                      return expr_gen.node_allocator_->
   36781         875 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
   36782             :                   }
   36783             :                   // (c0) * (v / c1) --> (cov) (c0 / c1) * v
   36784       10256 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   36785             :                   {
   36786             :                      exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
   36787             : 
   36788         865 :                      return expr_gen.node_allocator_->
   36789         865 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
   36790             :                   }
   36791             :                   // (c0) / (v * c1) --> (cov) (c0 / c1) / v
   36792        9391 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   36793             :                   {
   36794             :                      exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
   36795             : 
   36796         845 :                      return expr_gen.node_allocator_->
   36797         845 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
   36798             :                   }
   36799             :                   // (c0) / (v / c1) --> (cov) (c0 * c1) / v
   36800        8546 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   36801             :                   {
   36802             :                      exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
   36803             : 
   36804         835 :                      return expr_gen.node_allocator_->
   36805         835 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
   36806             :                   }
   36807             :                }
   36808             : 
   36809             :                const bool synthesis_result =
   36810             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
   36811        7711 :                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
   36812             : 
   36813        7711 :                if (synthesis_result)
   36814        7630 :                   return result;
   36815             : 
   36816          81 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36817          81 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36818             : 
   36819          81 :                if (!expr_gen.valid_operator(o0,f0))
   36820           0 :                   return error_node();
   36821          81 :                else if (!expr_gen.valid_operator(o1,f1))
   36822           0 :                   return error_node();
   36823             :                else
   36824          81 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
   36825             :             }
   36826             : 
   36827        7711 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36828             :                                          const details::operator_type o0,
   36829             :                                          const details::operator_type o1)
   36830             :             {
   36831       15422 :                return details::build_string()
   36832       15422 :                   << "t"  << expr_gen.to_str(o0)
   36833       15422 :                   << "(t" << expr_gen.to_str(o1)
   36834       15422 :                   << "t)";
   36835             :             }
   36836             :          };
   36837             : 
   36838             :          struct synthesize_cocov_expression0
   36839             :          {
   36840             :             typedef typename cocov_t::type0 node_type;
   36841             :             static inline expression_node_ptr process(expression_generator<Type>&,
   36842             :                                                       const details::operator_type&,
   36843             :                                                       expression_node_ptr (&)[2])
   36844             :             {
   36845             :                // (c0 o0 c1) o1 (v) - Not possible.
   36846             :                return error_node();
   36847             :             }
   36848             :          };
   36849             : 
   36850             :          struct synthesize_cocov_expression1
   36851             :          {
   36852             :             typedef typename cocov_t::type1 node_type;
   36853             :             typedef typename cocov_t::sf3_type sf3_type;
   36854             : 
   36855       16245 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36856             :                                                       const details::operator_type& operation,
   36857             :                                                       expression_node_ptr (&branch)[2])
   36858             :             {
   36859             :                // (c0) o0 (c1 o1 v)
   36860       16245 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   36861       16245 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   36862       16245 :                const Type  c1 = cov->c();
   36863       16245 :                const Type&  v = cov->v();
   36864       16245 :                const details::operator_type o0 = operation;
   36865       16245 :                const details::operator_type o1 = cov->operation();
   36866             : 
   36867       16245 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36868       16245 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36869             : 
   36870       16245 :                expression_node_ptr result = error_node();
   36871             : 
   36872       16245 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36873             :                {
   36874             :                   // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
   36875       16245 :                   if ((details::e_add == o0) && (details::e_add == o1))
   36876             :                   {
   36877             :                      exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
   36878             : 
   36879        1045 :                      return expr_gen.node_allocator_->
   36880        1045 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
   36881             :                   }
   36882             :                   // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
   36883       15200 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   36884             :                   {
   36885             :                      exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
   36886             : 
   36887        1025 :                      return expr_gen.node_allocator_->
   36888        1025 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
   36889             :                   }
   36890             :                   // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
   36891       14175 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   36892             :                   {
   36893             :                      exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
   36894             : 
   36895        1010 :                      return expr_gen.node_allocator_->
   36896        1010 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
   36897             :                   }
   36898             :                   // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
   36899       13165 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   36900             :                   {
   36901             :                      exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
   36902             : 
   36903        1010 :                      return expr_gen.node_allocator_->
   36904        1010 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
   36905             :                   }
   36906             :                   // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
   36907       12155 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   36908             :                   {
   36909             :                      exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
   36910             : 
   36911         885 :                      return expr_gen.node_allocator_->
   36912         885 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
   36913             :                   }
   36914             :                   // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
   36915       11270 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   36916             :                   {
   36917             :                      exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
   36918             : 
   36919         875 :                      return expr_gen.node_allocator_->
   36920         875 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
   36921             :                   }
   36922             :                   // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
   36923       10395 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   36924             :                   {
   36925             :                      exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
   36926             : 
   36927         840 :                      return expr_gen.node_allocator_->
   36928         840 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
   36929             :                   }
   36930             :                   // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
   36931        9555 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   36932             :                   {
   36933             :                      exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
   36934             : 
   36935         850 :                      return expr_gen.node_allocator_->
   36936         850 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
   36937             :                   }
   36938             :                }
   36939             : 
   36940             :                const bool synthesis_result =
   36941             :                   synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
   36942        8705 :                      (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
   36943             : 
   36944        8705 :                if (synthesis_result)
   36945        8642 :                   return result;
   36946             : 
   36947          63 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36948          63 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36949             : 
   36950          63 :                if (!expr_gen.valid_operator(o0,f0))
   36951           0 :                   return error_node();
   36952          63 :                else if (!expr_gen.valid_operator(o1,f1))
   36953           0 :                   return error_node();
   36954             :                else
   36955          63 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
   36956             :             }
   36957             : 
   36958        8705 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36959             :                                          const details::operator_type o0,
   36960             :                                          const details::operator_type o1)
   36961             :             {
   36962       17410 :                return details::build_string()
   36963       17410 :                   << "t"  << expr_gen.to_str(o0)
   36964       17410 :                   << "(t" << expr_gen.to_str(o1)
   36965       17410 :                   << "t)";
   36966             :             }
   36967             :          };
   36968             : 
   36969             :          struct synthesize_vococ_expression0
   36970             :          {
   36971             :             typedef typename vococ_t::type0 node_type;
   36972             :             typedef typename vococ_t::sf3_type sf3_type;
   36973             : 
   36974       28769 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36975             :                                                       const details::operator_type& operation,
   36976             :                                                       expression_node_ptr (&branch)[2])
   36977             :             {
   36978             :                // (v o0 c0) o1 (c1)
   36979       28769 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   36980       28769 :                const Type&  v = voc->v();
   36981       28769 :                const Type& c0 = voc->c();
   36982       28769 :                const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   36983       28769 :                const details::operator_type o0 = voc->operation();
   36984       28769 :                const details::operator_type o1 = operation;
   36985             : 
   36986       28769 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36987       28769 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36988             : 
   36989       28769 :                expression_node_ptr result = error_node();
   36990             : 
   36991       28769 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36992             :                {
   36993             :                   // (v + c0) + c1 --> (voc) v + (c0 + c1)
   36994       28769 :                   if ((details::e_add == o0) && (details::e_add == o1))
   36995             :                   {
   36996             :                      exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
   36997             : 
   36998        2430 :                      return expr_gen.node_allocator_->
   36999        2430 :                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
   37000             :                   }
   37001             :                   // (v + c0) - c1 --> (voc) v + (c0 - c1)
   37002       26339 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   37003             :                   {
   37004             :                      exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
   37005             : 
   37006        2065 :                      return expr_gen.node_allocator_->
   37007        2065 :                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
   37008             :                   }
   37009             :                   // (v - c0) + c1 --> (voc) v - (c0 + c1)
   37010       24274 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   37011             :                   {
   37012             :                      exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
   37013             : 
   37014        1810 :                      return expr_gen.node_allocator_->
   37015        1810 :                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
   37016             :                   }
   37017             :                   // (v - c0) - c1 --> (voc) v - (c0 + c1)
   37018       22464 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   37019             :                   {
   37020             :                      exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
   37021             : 
   37022        1745 :                      return expr_gen.node_allocator_->
   37023        1745 :                                template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
   37024             :                   }
   37025             :                   // (v * c0) * c1 --> (voc) v * (c0 * c1)
   37026       20719 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   37027             :                   {
   37028             :                      exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
   37029             : 
   37030        2915 :                      return expr_gen.node_allocator_->
   37031        2915 :                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
   37032             :                   }
   37033             :                   // (v * c0) / c1 --> (voc) v * (c0 / c1)
   37034       17804 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   37035             :                   {
   37036             :                      exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
   37037             : 
   37038        2220 :                      return expr_gen.node_allocator_->
   37039        2220 :                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
   37040             :                   }
   37041             :                   // (v / c0) * c1 --> (voc) v * (c1 / c0)
   37042       15584 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   37043             :                   {
   37044             :                      exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
   37045             : 
   37046        2726 :                      return expr_gen.node_allocator_->
   37047        2726 :                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
   37048             :                   }
   37049             :                   // (v / c0) / c1 --> (voc) v / (c0 * c1)
   37050       12858 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   37051             :                   {
   37052             :                      exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
   37053             : 
   37054        3150 :                      return expr_gen.node_allocator_->
   37055        3150 :                                template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
   37056             :                   }
   37057             :                   // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
   37058        9708 :                   else if ((details::e_pow == o0) && (details::e_pow == o1))
   37059             :                   {
   37060             :                      exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
   37061             : 
   37062          40 :                      return expr_gen.node_allocator_->
   37063          40 :                                template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
   37064             :                   }
   37065             :                }
   37066             : 
   37067             :                const bool synthesis_result =
   37068             :                   synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
   37069        9668 :                      (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
   37070             : 
   37071        9668 :                if (synthesis_result)
   37072        7543 :                   return result;
   37073             : 
   37074        2125 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37075        2125 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37076             : 
   37077        2125 :                if (!expr_gen.valid_operator(o0,f0))
   37078           0 :                   return error_node();
   37079        2125 :                else if (!expr_gen.valid_operator(o1,f1))
   37080           0 :                   return error_node();
   37081             :                else
   37082        2125 :                   return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
   37083             :             }
   37084             : 
   37085        9668 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37086             :                                          const details::operator_type o0,
   37087             :                                          const details::operator_type o1)
   37088             :             {
   37089       19336 :                return details::build_string()
   37090       19336 :                   << "(t" << expr_gen.to_str(o0)
   37091       19336 :                   << "t)" << expr_gen.to_str(o1)
   37092       19336 :                   << "t";
   37093             :             }
   37094             :          };
   37095             : 
   37096             :          struct synthesize_vococ_expression1
   37097             :          {
   37098             :             typedef typename vococ_t::type0 node_type;
   37099             : 
   37100             :             static inline expression_node_ptr process(expression_generator<Type>&,
   37101             :                                                       const details::operator_type&,
   37102             :                                                       expression_node_ptr (&)[2])
   37103             :             {
   37104             :                // (v) o0 (c0 o1 c1) - Not possible.
   37105             :                exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
   37106             :                return error_node();
   37107             :             }
   37108             :          };
   37109             : 
   37110             :          struct synthesize_vovovov_expression0
   37111             :          {
   37112             :             typedef typename vovovov_t::type0 node_type;
   37113             :             typedef typename vovovov_t::sf4_type sf4_type;
   37114             :             typedef typename node_type::T0 T0;
   37115             :             typedef typename node_type::T1 T1;
   37116             :             typedef typename node_type::T2 T2;
   37117             :             typedef typename node_type::T3 T3;
   37118             : 
   37119       10110 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37120             :                                                       const details::operator_type& operation,
   37121             :                                                       expression_node_ptr (&branch)[2])
   37122             :             {
   37123             :                // (v0 o0 v1) o1 (v2 o2 v3)
   37124       10110 :                const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
   37125       10110 :                const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
   37126       10110 :                const Type& v0 = vov0->v0();
   37127       10110 :                const Type& v1 = vov0->v1();
   37128       10110 :                const Type& v2 = vov1->v0();
   37129       10110 :                const Type& v3 = vov1->v1();
   37130       10110 :                const details::operator_type o0 = vov0->operation();
   37131       10110 :                const details::operator_type o1 = operation;
   37132       10110 :                const details::operator_type o2 = vov1->operation();
   37133             : 
   37134       10110 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37135       10110 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37136             : 
   37137       10110 :                expression_node_ptr result = error_node();
   37138             : 
   37139       10110 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37140             :                {
   37141             :                   // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
   37142       10110 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37143             :                   {
   37144             :                      const bool synthesis_result =
   37145             :                         synthesize_sf4ext_expression::
   37146          80 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
   37147             : 
   37148             :                      exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
   37149             : 
   37150          80 :                      return (synthesis_result) ? result : error_node();
   37151             :                   }
   37152             :                   // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
   37153       10030 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37154             :                   {
   37155             :                      const bool synthesis_result =
   37156             :                         synthesize_sf4ext_expression::
   37157          80 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
   37158             : 
   37159             :                      exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
   37160             : 
   37161          80 :                      return (synthesis_result) ? result : error_node();
   37162             :                   }
   37163             :                   // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
   37164        9950 :                   else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
   37165             :                   {
   37166             :                      const bool synthesis_result =
   37167             :                         synthesize_sf4ext_expression::
   37168         155 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
   37169             : 
   37170             :                      exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
   37171             : 
   37172         155 :                      return (synthesis_result) ? result : error_node();
   37173             :                   }
   37174             :                   // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
   37175        9795 :                   else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
   37176             :                   {
   37177             :                      const bool synthesis_result =
   37178             :                         synthesize_sf4ext_expression::
   37179         155 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
   37180             : 
   37181             :                      exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
   37182             : 
   37183         155 :                      return (synthesis_result) ? result : error_node();
   37184             :                   }
   37185             :                   // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
   37186        9640 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   37187             :                   {
   37188             :                      const bool synthesis_result =
   37189             :                         synthesize_sf4ext_expression::
   37190          80 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
   37191             : 
   37192             :                      exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
   37193             : 
   37194          80 :                      return (synthesis_result) ? result : error_node();
   37195             :                   }
   37196             :                }
   37197             : 
   37198             :                const bool synthesis_result =
   37199             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37200        9560 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   37201             : 
   37202        9560 :                if (synthesis_result)
   37203        7806 :                   return result;
   37204             : 
   37205        1754 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37206        1754 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37207        1754 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   37208             : 
   37209        1754 :                if (!expr_gen.valid_operator(o0,f0))
   37210           0 :                   return error_node();
   37211        1754 :                else if (!expr_gen.valid_operator(o1,f1))
   37212           0 :                   return error_node();
   37213        1754 :                else if (!expr_gen.valid_operator(o2,f2))
   37214           0 :                   return error_node();
   37215             :                else
   37216        1754 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   37217             :             }
   37218             : 
   37219        9560 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37220             :                                          const details::operator_type o0,
   37221             :                                          const details::operator_type o1,
   37222             :                                          const details::operator_type o2)
   37223             :             {
   37224       19120 :                return details::build_string()
   37225       19120 :                   << "(t" << expr_gen.to_str(o0)
   37226       19120 :                   << "t)" << expr_gen.to_str(o1)
   37227       19120 :                   << "(t" << expr_gen.to_str(o2)
   37228       19120 :                   << "t)";
   37229             :             }
   37230             :          };
   37231             : 
   37232             :          struct synthesize_vovovoc_expression0
   37233             :          {
   37234             :             typedef typename vovovoc_t::type0 node_type;
   37235             :             typedef typename vovovoc_t::sf4_type sf4_type;
   37236             :             typedef typename node_type::T0 T0;
   37237             :             typedef typename node_type::T1 T1;
   37238             :             typedef typename node_type::T2 T2;
   37239             :             typedef typename node_type::T3 T3;
   37240             : 
   37241        7710 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37242             :                                                       const details::operator_type& operation,
   37243             :                                                       expression_node_ptr (&branch)[2])
   37244             :             {
   37245             :                // (v0 o0 v1) o1 (v2 o2 c)
   37246        7710 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   37247        7710 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
   37248        7710 :                const Type& v0 = vov->v0();
   37249        7710 :                const Type& v1 = vov->v1();
   37250        7710 :                const Type& v2 = voc->v ();
   37251        7710 :                const Type   c = voc->c ();
   37252        7710 :                const details::operator_type o0 = vov->operation();
   37253        7710 :                const details::operator_type o1 = operation;
   37254        7710 :                const details::operator_type o2 = voc->operation();
   37255             : 
   37256        7710 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37257        7710 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37258             : 
   37259        7710 :                expression_node_ptr result = error_node();
   37260             : 
   37261        7710 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37262             :                {
   37263             :                   // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
   37264        7710 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37265             :                   {
   37266             :                      const bool synthesis_result =
   37267             :                         synthesize_sf4ext_expression::
   37268          80 :                            template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
   37269             : 
   37270             :                      exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
   37271             : 
   37272          80 :                      return (synthesis_result) ? result : error_node();
   37273             :                   }
   37274             :                   // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
   37275        7630 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37276             :                   {
   37277             :                      const bool synthesis_result =
   37278             :                         synthesize_sf4ext_expression::
   37279          80 :                            template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
   37280             : 
   37281             :                      exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
   37282             : 
   37283          80 :                      return (synthesis_result) ? result : error_node();
   37284             :                   }
   37285             :                }
   37286             : 
   37287             :                const bool synthesis_result =
   37288             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37289        7550 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   37290             : 
   37291        7550 :                if (synthesis_result)
   37292        7010 :                   return result;
   37293             : 
   37294         540 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37295         540 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37296         540 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   37297             : 
   37298         540 :                if (!expr_gen.valid_operator(o0,f0))
   37299           0 :                   return error_node();
   37300         540 :                else if (!expr_gen.valid_operator(o1,f1))
   37301           0 :                   return error_node();
   37302         540 :                else if (!expr_gen.valid_operator(o2,f2))
   37303           0 :                   return error_node();
   37304             :                else
   37305         540 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   37306             :             }
   37307             : 
   37308        7550 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37309             :                                          const details::operator_type o0,
   37310             :                                          const details::operator_type o1,
   37311             :                                          const details::operator_type o2)
   37312             :             {
   37313       15100 :                return details::build_string()
   37314       15100 :                   << "(t" << expr_gen.to_str(o0)
   37315       15100 :                   << "t)" << expr_gen.to_str(o1)
   37316       15100 :                   << "(t" << expr_gen.to_str(o2)
   37317       15100 :                   << "t)";
   37318             :             }
   37319             :          };
   37320             : 
   37321             :          struct synthesize_vovocov_expression0
   37322             :          {
   37323             :             typedef typename vovocov_t::type0 node_type;
   37324             :             typedef typename vovocov_t::sf4_type sf4_type;
   37325             :             typedef typename node_type::T0 T0;
   37326             :             typedef typename node_type::T1 T1;
   37327             :             typedef typename node_type::T2 T2;
   37328             :             typedef typename node_type::T3 T3;
   37329             : 
   37330       11647 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37331             :                                                       const details::operator_type& operation,
   37332             :                                                       expression_node_ptr (&branch)[2])
   37333             :             {
   37334             :                // (v0 o0 v1) o1 (c o2 v2)
   37335       11647 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   37336       11647 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   37337       11647 :                const Type& v0 = vov->v0();
   37338       11647 :                const Type& v1 = vov->v1();
   37339       11647 :                const Type& v2 = cov->v ();
   37340       11647 :                const Type   c = cov->c ();
   37341       11647 :                const details::operator_type o0 = vov->operation();
   37342       11647 :                const details::operator_type o1 = operation;
   37343       11647 :                const details::operator_type o2 = cov->operation();
   37344             : 
   37345       11647 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37346       11647 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37347             : 
   37348       11647 :                expression_node_ptr result = error_node();
   37349             : 
   37350       11647 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37351             :                {
   37352             :                   // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
   37353       11647 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37354             :                   {
   37355             :                      const bool synthesis_result =
   37356             :                         synthesize_sf4ext_expression::
   37357          80 :                            template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
   37358             : 
   37359             :                      exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
   37360             : 
   37361          80 :                      return (synthesis_result) ? result : error_node();
   37362             :                   }
   37363             :                   // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
   37364       11567 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37365             :                   {
   37366             :                      const bool synthesis_result =
   37367             :                         synthesize_sf4ext_expression::
   37368          80 :                            template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
   37369             : 
   37370             :                      exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
   37371             : 
   37372          80 :                      return (synthesis_result) ? result : error_node();
   37373             :                   }
   37374             :                }
   37375             : 
   37376             :                const bool synthesis_result =
   37377             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37378       11487 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   37379             : 
   37380       11487 :                if (synthesis_result)
   37381       11092 :                   return result;
   37382             : 
   37383         395 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37384         395 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37385         395 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   37386             : 
   37387         395 :                if (!expr_gen.valid_operator(o0,f0))
   37388           0 :                   return error_node();
   37389         395 :                else if (!expr_gen.valid_operator(o1,f1))
   37390           0 :                   return error_node();
   37391         395 :                else if (!expr_gen.valid_operator(o2,f2))
   37392           0 :                   return error_node();
   37393             :                else
   37394         395 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   37395             :             }
   37396             : 
   37397       11487 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37398             :                                          const details::operator_type o0,
   37399             :                                          const details::operator_type o1,
   37400             :                                          const details::operator_type o2)
   37401             :             {
   37402       22974 :                return details::build_string()
   37403       22974 :                   << "(t" << expr_gen.to_str(o0)
   37404       22974 :                   << "t)" << expr_gen.to_str(o1)
   37405       22974 :                   << "(t" << expr_gen.to_str(o2)
   37406       22974 :                   << "t)";
   37407             :             }
   37408             :          };
   37409             : 
   37410             :          struct synthesize_vocovov_expression0
   37411             :          {
   37412             :             typedef typename vocovov_t::type0 node_type;
   37413             :             typedef typename vocovov_t::sf4_type sf4_type;
   37414             :             typedef typename node_type::T0 T0;
   37415             :             typedef typename node_type::T1 T1;
   37416             :             typedef typename node_type::T2 T2;
   37417             :             typedef typename node_type::T3 T3;
   37418             : 
   37419        7695 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37420             :                                                       const details::operator_type& operation,
   37421             :                                                       expression_node_ptr (&branch)[2])
   37422             :             {
   37423             :                // (v0 o0 c) o1 (v1 o2 v2)
   37424        7695 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   37425        7695 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   37426        7695 :                const Type   c = voc->c ();
   37427        7695 :                const Type& v0 = voc->v ();
   37428        7695 :                const Type& v1 = vov->v0();
   37429        7695 :                const Type& v2 = vov->v1();
   37430        7695 :                const details::operator_type o0 = voc->operation();
   37431        7695 :                const details::operator_type o1 = operation;
   37432        7695 :                const details::operator_type o2 = vov->operation();
   37433             : 
   37434        7695 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37435        7695 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37436             : 
   37437        7695 :                expression_node_ptr result = error_node();
   37438             : 
   37439        7695 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37440             :                {
   37441             :                   // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
   37442        7695 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37443             :                   {
   37444             :                      const bool synthesis_result =
   37445             :                         synthesize_sf4ext_expression::
   37446          80 :                            template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
   37447             : 
   37448             :                      exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
   37449             : 
   37450          80 :                      return (synthesis_result) ? result : error_node();
   37451             :                   }
   37452             :                   // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
   37453        7615 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37454             :                   {
   37455             :                      const bool synthesis_result =
   37456             :                         synthesize_sf4ext_expression::
   37457          80 :                            template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
   37458             : 
   37459             :                      exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
   37460             : 
   37461          80 :                      return (synthesis_result) ? result : error_node();
   37462             :                   }
   37463             :                }
   37464             : 
   37465             :                const bool synthesis_result =
   37466             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37467        7535 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   37468             : 
   37469        7535 :                if (synthesis_result)
   37470        7100 :                   return result;
   37471             : 
   37472         435 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37473         435 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37474         435 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   37475             : 
   37476         435 :                if (!expr_gen.valid_operator(o0,f0))
   37477           0 :                   return error_node();
   37478         435 :                else if (!expr_gen.valid_operator(o1,f1))
   37479           0 :                   return error_node();
   37480         435 :                else if (!expr_gen.valid_operator(o2,f2))
   37481           0 :                   return error_node();
   37482             :                else
   37483         435 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   37484             :             }
   37485             : 
   37486        7535 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37487             :                                          const details::operator_type o0,
   37488             :                                          const details::operator_type o1,
   37489             :                                          const details::operator_type o2)
   37490             :             {
   37491       15070 :                return details::build_string()
   37492       15070 :                   << "(t" << expr_gen.to_str(o0)
   37493       15070 :                   << "t)" << expr_gen.to_str(o1)
   37494       15070 :                   << "(t" << expr_gen.to_str(o2)
   37495       15070 :                   << "t)";
   37496             :             }
   37497             :          };
   37498             : 
   37499             :          struct synthesize_covovov_expression0
   37500             :          {
   37501             :             typedef typename covovov_t::type0 node_type;
   37502             :             typedef typename covovov_t::sf4_type sf4_type;
   37503             :             typedef typename node_type::T0 T0;
   37504             :             typedef typename node_type::T1 T1;
   37505             :             typedef typename node_type::T2 T2;
   37506             :             typedef typename node_type::T3 T3;
   37507             : 
   37508        7520 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37509             :                                                       const details::operator_type& operation,
   37510             :                                                       expression_node_ptr (&branch)[2])
   37511             :             {
   37512             :                // (c o0 v0) o1 (v1 o2 v2)
   37513        7520 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   37514        7520 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   37515        7520 :                const Type   c = cov->c ();
   37516        7520 :                const Type& v0 = cov->v ();
   37517        7520 :                const Type& v1 = vov->v0();
   37518        7520 :                const Type& v2 = vov->v1();
   37519        7520 :                const details::operator_type o0 = cov->operation();
   37520        7520 :                const details::operator_type o1 = operation;
   37521        7520 :                const details::operator_type o2 = vov->operation();
   37522             : 
   37523        7520 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37524        7520 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37525             : 
   37526        7520 :                expression_node_ptr result = error_node();
   37527             : 
   37528        7520 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37529             :                {
   37530             :                   // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
   37531        7520 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37532             :                   {
   37533             :                      const bool synthesis_result =
   37534             :                         synthesize_sf4ext_expression::
   37535          80 :                            template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
   37536             : 
   37537             :                      exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
   37538             : 
   37539          80 :                      return (synthesis_result) ? result : error_node();
   37540             :                   }
   37541             :                   // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
   37542        7440 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37543             :                   {
   37544             :                      const bool synthesis_result =
   37545             :                         synthesize_sf4ext_expression::
   37546          80 :                            template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
   37547             : 
   37548             :                      exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
   37549             : 
   37550          80 :                      return (synthesis_result) ? result : error_node();
   37551             :                   }
   37552             :                }
   37553             : 
   37554             :                const bool synthesis_result =
   37555             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37556        7360 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   37557             : 
   37558        7360 :                if (synthesis_result)
   37559        7045 :                   return result;
   37560             : 
   37561         315 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37562         315 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37563         315 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   37564             : 
   37565         315 :                if (!expr_gen.valid_operator(o0,f0))
   37566           0 :                   return error_node();
   37567         315 :                else if (!expr_gen.valid_operator(o1,f1))
   37568           0 :                   return error_node();
   37569         315 :                else if (!expr_gen.valid_operator(o2,f2))
   37570           0 :                   return error_node();
   37571             :                else
   37572         315 :                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   37573             :             }
   37574             : 
   37575        7360 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37576             :                                          const details::operator_type o0,
   37577             :                                          const details::operator_type o1,
   37578             :                                          const details::operator_type o2)
   37579             :             {
   37580       14720 :                return details::build_string()
   37581       14720 :                   << "(t" << expr_gen.to_str(o0)
   37582       14720 :                   << "t)" << expr_gen.to_str(o1)
   37583       14720 :                   << "(t" << expr_gen.to_str(o2)
   37584       14720 :                   << "t)";
   37585             :             }
   37586             :          };
   37587             : 
   37588             :          struct synthesize_covocov_expression0
   37589             :          {
   37590             :             typedef typename covocov_t::type0 node_type;
   37591             :             typedef typename covocov_t::sf4_type sf4_type;
   37592             :             typedef typename node_type::T0 T0;
   37593             :             typedef typename node_type::T1 T1;
   37594             :             typedef typename node_type::T2 T2;
   37595             :             typedef typename node_type::T3 T3;
   37596             : 
   37597        6351 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37598             :                                                       const details::operator_type& operation,
   37599             :                                                       expression_node_ptr (&branch)[2])
   37600             :             {
   37601             :                // (c0 o0 v0) o1 (c1 o2 v1)
   37602        6351 :                const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
   37603        6351 :                const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
   37604        6351 :                const Type  c0 = cov0->c();
   37605        6351 :                const Type& v0 = cov0->v();
   37606        6351 :                const Type  c1 = cov1->c();
   37607        6351 :                const Type& v1 = cov1->v();
   37608        6351 :                const details::operator_type o0 = cov0->operation();
   37609        6351 :                const details::operator_type o1 = operation;
   37610        6351 :                const details::operator_type o2 = cov1->operation();
   37611             : 
   37612        6351 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37613        6351 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37614             : 
   37615        6351 :                expression_node_ptr result = error_node();
   37616             : 
   37617        6351 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37618             :                {
   37619             :                   // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
   37620        6351 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   37621             :                   {
   37622             :                      const bool synthesis_result =
   37623             :                         synthesize_sf3ext_expression::
   37624         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   37625             : 
   37626             :                      exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
   37627             : 
   37628         140 :                      return (synthesis_result) ? result : error_node();
   37629             :                   }
   37630             :                   // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
   37631        6211 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   37632             :                   {
   37633             :                      const bool synthesis_result =
   37634             :                         synthesize_sf3ext_expression::
   37635         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   37636             : 
   37637             :                      exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
   37638             : 
   37639         140 :                      return (synthesis_result) ? result : error_node();
   37640             :                   }
   37641             :                   // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
   37642        6071 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   37643             :                   {
   37644             :                      const bool synthesis_result =
   37645             :                         synthesize_sf3ext_expression::
   37646         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
   37647             : 
   37648             :                      exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
   37649             : 
   37650         140 :                      return (synthesis_result) ? result : error_node();
   37651             :                   }
   37652             :                   // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
   37653        5931 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   37654             :                   {
   37655             :                      const bool synthesis_result =
   37656             :                         synthesize_sf3ext_expression::
   37657         640 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   37658             : 
   37659             :                      exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
   37660             : 
   37661         320 :                      return (synthesis_result) ? result : error_node();
   37662             :                   }
   37663             :                   // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
   37664        5611 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   37665             :                   {
   37666             :                      const bool synthesis_result =
   37667             :                         synthesize_sf3ext_expression::
   37668         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   37669             : 
   37670             :                      exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
   37671             : 
   37672         140 :                      return (synthesis_result) ? result : error_node();
   37673             :                   }
   37674             :                   // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
   37675        5471 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37676             :                   {
   37677             :                      const bool synthesis_result =
   37678             :                         synthesize_sf3ext_expression::
   37679         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
   37680             : 
   37681             :                      exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
   37682             : 
   37683         140 :                      return (synthesis_result) ? result : error_node();
   37684             :                   }
   37685             :                   // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
   37686        5331 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37687             :                   {
   37688             :                      const bool synthesis_result =
   37689             :                         synthesize_sf3ext_expression::
   37690         170 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
   37691             : 
   37692             :                      exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
   37693             : 
   37694          85 :                      return (synthesis_result) ? result : error_node();
   37695             :                   }
   37696             :                   // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
   37697        5246 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   37698             :                   {
   37699             :                      const bool synthesis_result =
   37700             :                         synthesize_sf3ext_expression::
   37701         300 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
   37702             : 
   37703             :                      exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
   37704             : 
   37705         150 :                      return (synthesis_result) ? result : error_node();
   37706             :                   }
   37707             :                   // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
   37708        5096 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   37709             :                   {
   37710             :                      const bool synthesis_result =
   37711             :                         synthesize_sf3ext_expression::
   37712         310 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
   37713             : 
   37714             :                      exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
   37715             : 
   37716         155 :                      return (synthesis_result) ? result : error_node();
   37717             :                   }
   37718             :                   // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
   37719        4941 :                   else if (
   37720        4941 :                             (std::equal_to<T>()(c0,c1)) &&
   37721         800 :                             (details::e_mul == o0)      &&
   37722        6541 :                             (details::e_mul == o2)      &&
   37723             :                             (
   37724         800 :                               (details::e_add == o1) ||
   37725         460 :                               (details::e_sub == o1)
   37726             :                             )
   37727             :                           )
   37728             :                   {
   37729         440 :                      std::string specfunc;
   37730             : 
   37731         440 :                      switch (o1)
   37732             :                      {
   37733         340 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   37734         100 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   37735           0 :                         default             : return error_node();
   37736             :                      }
   37737             : 
   37738             :                      const bool synthesis_result =
   37739             :                         synthesize_sf3ext_expression::
   37740         440 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   37741             : 
   37742             :                      exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
   37743             : 
   37744         440 :                      return (synthesis_result) ? result : error_node();
   37745         440 :                   }
   37746             :                }
   37747             : 
   37748             :                const bool synthesis_result =
   37749             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37750        4501 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   37751             : 
   37752        4501 :                if (synthesis_result)
   37753        4011 :                   return result;
   37754             : 
   37755         490 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37756         490 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   37757         490 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   37758             : 
   37759         490 :                if (!expr_gen.valid_operator(o0,f0))
   37760           0 :                   return error_node();
   37761         490 :                else if (!expr_gen.valid_operator(o1,f1))
   37762           0 :                   return error_node();
   37763         490 :                else if (!expr_gen.valid_operator(o2,f2))
   37764           0 :                   return error_node();
   37765             :                else
   37766         490 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   37767             :             }
   37768             : 
   37769        4501 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37770             :                                          const details::operator_type o0,
   37771             :                                          const details::operator_type o1,
   37772             :                                          const details::operator_type o2)
   37773             :             {
   37774        9002 :                return details::build_string()
   37775        9002 :                   << "(t" << expr_gen.to_str(o0)
   37776        9002 :                   << "t)" << expr_gen.to_str(o1)
   37777        9002 :                   << "(t" << expr_gen.to_str(o2)
   37778        9002 :                   << "t)";
   37779             :             }
   37780             :          };
   37781             : 
   37782             :          struct synthesize_vocovoc_expression0
   37783             :          {
   37784             :             typedef typename vocovoc_t::type0 node_type;
   37785             :             typedef typename vocovoc_t::sf4_type sf4_type;
   37786             :             typedef typename node_type::T0 T0;
   37787             :             typedef typename node_type::T1 T1;
   37788             :             typedef typename node_type::T2 T2;
   37789             :             typedef typename node_type::T3 T3;
   37790             : 
   37791        7443 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37792             :                                                       const details::operator_type& operation,
   37793             :                                                       expression_node_ptr (&branch)[2])
   37794             :             {
   37795             :                // (v0 o0 c0) o1 (v1 o2 c1)
   37796        7443 :                const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
   37797        7443 :                const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
   37798        7443 :                const Type  c0 = voc0->c();
   37799        7443 :                const Type& v0 = voc0->v();
   37800        7443 :                const Type  c1 = voc1->c();
   37801        7443 :                const Type& v1 = voc1->v();
   37802        7443 :                const details::operator_type o0 = voc0->operation();
   37803        7443 :                const details::operator_type o1 = operation;
   37804        7443 :                const details::operator_type o2 = voc1->operation();
   37805             : 
   37806        7443 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37807        7443 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37808             : 
   37809        7443 :                expression_node_ptr result = error_node();
   37810             : 
   37811        7443 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   37812             :                {
   37813             :                   // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
   37814        7443 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   37815             :                   {
   37816             :                      const bool synthesis_result =
   37817             :                         synthesize_sf3ext_expression::
   37818         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   37819             : 
   37820             :                      exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
   37821             : 
   37822         140 :                      return (synthesis_result) ? result : error_node();
   37823             :                   }
   37824             :                   // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
   37825        7303 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   37826             :                   {
   37827             :                      const bool synthesis_result =
   37828             :                         synthesize_sf3ext_expression::
   37829         300 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   37830             : 
   37831             :                      exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
   37832             : 
   37833         150 :                      return (synthesis_result) ? result : error_node();
   37834             :                   }
   37835             :                   // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
   37836        7153 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   37837             :                   {
   37838             :                      const bool synthesis_result =
   37839             :                         synthesize_sf3ext_expression::
   37840         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
   37841             : 
   37842             :                      exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
   37843             : 
   37844         140 :                      return (synthesis_result) ? result : error_node();
   37845             :                   }
   37846             :                   // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
   37847        7013 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   37848             :                   {
   37849             :                      const bool synthesis_result =
   37850             :                         synthesize_sf3ext_expression::
   37851         170 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   37852             : 
   37853             :                      exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
   37854             : 
   37855          85 :                      return (synthesis_result) ? result : error_node();
   37856             :                   }
   37857             :                   // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
   37858        6928 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   37859             :                   {
   37860             :                      const bool synthesis_result =
   37861             :                         synthesize_sf3ext_expression::
   37862         300 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   37863             : 
   37864             :                      exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
   37865             : 
   37866         150 :                      return (synthesis_result) ? result : error_node();
   37867             :                   }
   37868             :                   // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
   37869        6778 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   37870             :                   {
   37871             :                      const bool synthesis_result =
   37872             :                         synthesize_sf3ext_expression::
   37873         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
   37874             : 
   37875             :                      exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
   37876             : 
   37877         140 :                      return (synthesis_result) ? result : error_node();
   37878             :                   }
   37879             :                   // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
   37880        6638 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   37881             :                   {
   37882             :                      const bool synthesis_result =
   37883             :                         synthesize_sf3ext_expression::
   37884         160 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
   37885             : 
   37886             :                      exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
   37887             : 
   37888          80 :                      return (synthesis_result) ? result : error_node();
   37889             :                   }
   37890             :                   // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
   37891        6558 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   37892             :                   {
   37893             :                      const bool synthesis_result =
   37894             :                         synthesize_sf3ext_expression::
   37895         320 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
   37896             : 
   37897             :                      exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
   37898             : 
   37899         160 :                      return (synthesis_result) ? result : error_node();
   37900             :                   }
   37901             :                   // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
   37902        6398 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   37903             :                   {
   37904             :                      const bool synthesis_result =
   37905             :                         synthesize_sf3ext_expression::
   37906         290 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
   37907             : 
   37908             :                      exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
   37909             : 
   37910         145 :                      return (synthesis_result) ? result : error_node();
   37911             :                   }
   37912             :                   // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
   37913        6253 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
   37914             :                   {
   37915             :                      const bool synthesis_result =
   37916             :                         synthesize_sf4ext_expression::
   37917         170 :                            template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
   37918             : 
   37919             :                      exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
   37920             : 
   37921          85 :                      return (synthesis_result) ? result : error_node();
   37922             :                   }
   37923             :                   // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
   37924        6168 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
   37925             :                   {
   37926             :                      const bool synthesis_result =
   37927             :                         synthesize_sf4ext_expression::
   37928         170 :                            template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
   37929             : 
   37930             :                      exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
   37931             : 
   37932          85 :                      return (synthesis_result) ? result : error_node();
   37933             :                   }
   37934             :                   // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
   37935        6083 :                   else if (
   37936        6083 :                             (std::equal_to<T>()(c0,c1)) &&
   37937         710 :                             (details::e_mul == o0)      &&
   37938        7293 :                             (details::e_mul == o2)      &&
   37939             :                             (
   37940         500 :                               (details::e_add == o1) ||
   37941         460 :                               (details::e_sub == o1)
   37942             :                             )
   37943             :                           )
   37944             :                   {
   37945         140 :                      std::string specfunc;
   37946             : 
   37947         140 :                      switch (o1)
   37948             :                      {
   37949          40 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   37950         100 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   37951           0 :                         default             : return error_node();
   37952             :                      }
   37953             : 
   37954             :                      const bool synthesis_result =
   37955             :                         synthesize_sf3ext_expression::
   37956         140 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   37957             : 
   37958             :                      exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
   37959             : 
   37960         140 :                      return (synthesis_result) ? result : error_node();
   37961         140 :                   }
   37962             :                   // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
   37963        5943 :                   else if (
   37964        5943 :                             (std::equal_to<T>()(c0,c1)) &&
   37965         570 :                             (details::e_div == o0)      &&
   37966        6593 :                             (details::e_div == o2)      &&
   37967             :                             (
   37968          80 :                               (details::e_add == o1) ||
   37969          40 :                               (details::e_sub == o1)
   37970             :                             )
   37971             :                           )
   37972             :                   {
   37973          80 :                      std::string specfunc;
   37974             : 
   37975          80 :                      switch (o1)
   37976             :                      {
   37977          40 :                         case details::e_add : specfunc = "(t+t)/t"; break;
   37978          40 :                         case details::e_sub : specfunc = "(t-t)/t"; break;
   37979           0 :                         default             : return error_node();
   37980             :                      }
   37981             : 
   37982             :                      const bool synthesis_result =
   37983             :                         synthesize_sf3ext_expression::
   37984          80 :                            template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result);
   37985             : 
   37986             :                      exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
   37987             : 
   37988          80 :                      return (synthesis_result) ? result : error_node();
   37989          80 :                   }
   37990             :                }
   37991             : 
   37992             :                const bool synthesis_result =
   37993             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37994        5863 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   37995             : 
   37996        5863 :                if (synthesis_result)
   37997        3250 :                   return result;
   37998             : 
   37999        2613 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38000        2613 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   38001        2613 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38002             : 
   38003        2613 :                if (!expr_gen.valid_operator(o0,f0))
   38004           0 :                   return error_node();
   38005        2613 :                else if (!expr_gen.valid_operator(o1,f1))
   38006           0 :                   return error_node();
   38007        2613 :                else if (!expr_gen.valid_operator(o2,f2))
   38008           0 :                   return error_node();
   38009             :                else
   38010        2613 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   38011             :             }
   38012             : 
   38013        5863 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38014             :                                          const details::operator_type o0,
   38015             :                                          const details::operator_type o1,
   38016             :                                          const details::operator_type o2)
   38017             :             {
   38018       11726 :                return details::build_string()
   38019       11726 :                   << "(t" << expr_gen.to_str(o0)
   38020       11726 :                   << "t)" << expr_gen.to_str(o1)
   38021       11726 :                   << "(t" << expr_gen.to_str(o2)
   38022       11726 :                   << "t)";
   38023             :             }
   38024             :          };
   38025             : 
   38026             :          struct synthesize_covovoc_expression0
   38027             :          {
   38028             :             typedef typename covovoc_t::type0 node_type;
   38029             :             typedef typename covovoc_t::sf4_type sf4_type;
   38030             :             typedef typename node_type::T0 T0;
   38031             :             typedef typename node_type::T1 T1;
   38032             :             typedef typename node_type::T2 T2;
   38033             :             typedef typename node_type::T3 T3;
   38034             : 
   38035        5100 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38036             :                                                       const details::operator_type& operation,
   38037             :                                                       expression_node_ptr (&branch)[2])
   38038             :             {
   38039             :                // (c0 o0 v0) o1 (v1 o2 c1)
   38040        5100 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   38041        5100 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
   38042        5100 :                const Type  c0 = cov->c();
   38043        5100 :                const Type& v0 = cov->v();
   38044        5100 :                const Type  c1 = voc->c();
   38045        5100 :                const Type& v1 = voc->v();
   38046        5100 :                const details::operator_type o0 = cov->operation();
   38047        5100 :                const details::operator_type o1 = operation;
   38048        5100 :                const details::operator_type o2 = voc->operation();
   38049             : 
   38050        5100 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38051        5100 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38052             : 
   38053        5100 :                expression_node_ptr result = error_node();
   38054             : 
   38055        5100 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   38056             :                {
   38057             :                   // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
   38058        5100 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   38059             :                   {
   38060             :                      const bool synthesis_result =
   38061             :                         synthesize_sf3ext_expression::
   38062         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   38063             : 
   38064             :                      exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
   38065             : 
   38066         140 :                      return (synthesis_result) ? result : error_node();
   38067             :                   }
   38068             :                   // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
   38069        4960 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   38070             :                   {
   38071             :                      const bool synthesis_result =
   38072             :                         synthesize_sf3ext_expression::
   38073         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   38074             : 
   38075             :                      exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
   38076             : 
   38077         140 :                      return (synthesis_result) ? result : error_node();
   38078             :                   }
   38079             :                   // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
   38080        4820 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   38081             :                   {
   38082             :                      const bool synthesis_result =
   38083             :                         synthesize_sf3ext_expression::
   38084         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
   38085             : 
   38086             :                      exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
   38087             : 
   38088         140 :                      return (synthesis_result) ? result : error_node();
   38089             :                   }
   38090             :                   // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
   38091        4680 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   38092             :                   {
   38093             :                      const bool synthesis_result =
   38094             :                         synthesize_sf3ext_expression::
   38095         160 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   38096             : 
   38097             :                      exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
   38098             : 
   38099          80 :                      return (synthesis_result) ? result : error_node();
   38100             :                   }
   38101             :                   // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
   38102        4600 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   38103             :                   {
   38104             :                      const bool synthesis_result =
   38105             :                         synthesize_sf3ext_expression::
   38106         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   38107             : 
   38108             :                      exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
   38109             : 
   38110         140 :                      return (synthesis_result) ? result : error_node();
   38111             :                   }
   38112             :                   // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
   38113        4460 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   38114             :                   {
   38115             :                      const bool synthesis_result =
   38116             :                         synthesize_sf3ext_expression::
   38117         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
   38118             : 
   38119             :                      exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
   38120             : 
   38121         140 :                      return (synthesis_result) ? result : error_node();
   38122             :                   }
   38123             :                   // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
   38124        4320 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   38125             :                   {
   38126             :                      const bool synthesis_result =
   38127             :                         synthesize_sf3ext_expression::
   38128         160 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
   38129             : 
   38130             :                      exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
   38131             : 
   38132          80 :                      return (synthesis_result) ? result : error_node();
   38133             :                   }
   38134             :                   // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
   38135        4240 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   38136             :                   {
   38137             :                      const bool synthesis_result =
   38138             :                         synthesize_sf3ext_expression::
   38139         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
   38140             : 
   38141             :                      exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
   38142             : 
   38143         140 :                      return (synthesis_result) ? result : error_node();
   38144             :                   }
   38145             :                   // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
   38146        4100 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   38147             :                   {
   38148             :                      const bool synthesis_result =
   38149             :                         synthesize_sf3ext_expression::
   38150         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
   38151             : 
   38152             :                      exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
   38153             : 
   38154         140 :                      return (synthesis_result) ? result : error_node();
   38155             :                   }
   38156             :                   // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
   38157        3960 :                   else if (
   38158        3960 :                             (std::equal_to<T>()(c0,c1)) &&
   38159         320 :                             (details::e_mul == o0)      &&
   38160        4465 :                             (details::e_mul == o2)      &&
   38161             :                             (
   38162         185 :                               (details::e_add == o1) ||
   38163          55 :                               (details::e_sub == o1)
   38164             :                             )
   38165             :                           )
   38166             :                   {
   38167         185 :                      std::string specfunc;
   38168             : 
   38169         185 :                      switch (o1)
   38170             :                      {
   38171         130 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   38172          55 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   38173           0 :                         default             : return error_node();
   38174             :                      }
   38175             : 
   38176             :                      const bool synthesis_result =
   38177             :                         synthesize_sf3ext_expression::
   38178         185 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   38179             : 
   38180             :                      exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
   38181             : 
   38182         185 :                      return (synthesis_result) ? result : error_node();
   38183         185 :                   }
   38184             :                }
   38185             : 
   38186             :                const bool synthesis_result =
   38187             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38188        3775 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   38189             : 
   38190        3775 :                if (synthesis_result)
   38191        3645 :                   return result;
   38192             : 
   38193         130 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38194         130 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   38195         130 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38196             : 
   38197         130 :                if (!expr_gen.valid_operator(o0,f0))
   38198           0 :                   return error_node();
   38199         130 :                else if (!expr_gen.valid_operator(o1,f1))
   38200           0 :                   return error_node();
   38201         130 :                else if (!expr_gen.valid_operator(o2,f2))
   38202           0 :                   return error_node();
   38203             :                else
   38204         130 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   38205             :             }
   38206             : 
   38207        3775 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38208             :                                          const details::operator_type o0,
   38209             :                                          const details::operator_type o1,
   38210             :                                          const details::operator_type o2)
   38211             :             {
   38212        7550 :                return details::build_string()
   38213        7550 :                   << "(t" << expr_gen.to_str(o0)
   38214        7550 :                   << "t)" << expr_gen.to_str(o1)
   38215        7550 :                   << "(t" << expr_gen.to_str(o2)
   38216        7550 :                   << "t)";
   38217             :             }
   38218             :          };
   38219             : 
   38220             :          struct synthesize_vococov_expression0
   38221             :          {
   38222             :             typedef typename vococov_t::type0 node_type;
   38223             :             typedef typename vococov_t::sf4_type sf4_type;
   38224             :             typedef typename node_type::T0 T0;
   38225             :             typedef typename node_type::T1 T1;
   38226             :             typedef typename node_type::T2 T2;
   38227             :             typedef typename node_type::T3 T3;
   38228             : 
   38229        4750 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38230             :                                                       const details::operator_type& operation,
   38231             :                                                       expression_node_ptr (&branch)[2])
   38232             :             {
   38233             :                // (v0 o0 c0) o1 (c1 o2 v1)
   38234        4750 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   38235        4750 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   38236        4750 :                const Type  c0 = voc->c();
   38237        4750 :                const Type& v0 = voc->v();
   38238        4750 :                const Type  c1 = cov->c();
   38239        4750 :                const Type& v1 = cov->v();
   38240        4750 :                const details::operator_type o0 = voc->operation();
   38241        4750 :                const details::operator_type o1 = operation;
   38242        4750 :                const details::operator_type o2 = cov->operation();
   38243             : 
   38244        4750 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38245        4750 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38246             : 
   38247        4750 :                expression_node_ptr result = error_node();
   38248             : 
   38249        4750 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   38250             :                {
   38251             :                   // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
   38252        4750 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   38253             :                   {
   38254             :                      const bool synthesis_result =
   38255             :                         synthesize_sf3ext_expression::
   38256         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   38257             : 
   38258             :                      exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
   38259             : 
   38260         140 :                      return (synthesis_result) ? result : error_node();
   38261             :                   }
   38262             :                   // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
   38263        4610 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   38264             :                   {
   38265             :                      const bool synthesis_result =
   38266             :                         synthesize_sf3ext_expression::
   38267         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   38268             : 
   38269             :                      exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
   38270             : 
   38271         140 :                      return (synthesis_result) ? result : error_node();
   38272             :                   }
   38273             :                   // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
   38274        4470 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   38275             :                   {
   38276             :                      const bool synthesis_result =
   38277             :                         synthesize_sf3ext_expression::
   38278         280 :                            template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
   38279             : 
   38280             :                      exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
   38281             : 
   38282         140 :                      return (synthesis_result) ? result : error_node();
   38283             :                   }
   38284             :                   // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
   38285        4330 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   38286             :                   {
   38287             :                      const bool synthesis_result =
   38288             :                         synthesize_sf3ext_expression::
   38289         160 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   38290             : 
   38291             :                      exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
   38292             : 
   38293          80 :                      return (synthesis_result) ? result : error_node();
   38294             :                   }
   38295             :                   // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
   38296        4250 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   38297             :                   {
   38298             :                      const bool synthesis_result =
   38299             :                         synthesize_sf3ext_expression::
   38300         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   38301             : 
   38302             :                      exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
   38303             : 
   38304         140 :                      return (synthesis_result) ? result : error_node();
   38305             :                   }
   38306             :                   // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
   38307        4110 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   38308             :                   {
   38309             :                      const bool synthesis_result =
   38310             :                         synthesize_sf3ext_expression::
   38311         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
   38312             : 
   38313             :                      exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
   38314             : 
   38315         140 :                      return (synthesis_result) ? result : error_node();
   38316             :                   }
   38317             :                   // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
   38318        3970 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   38319             :                   {
   38320             :                      const bool synthesis_result =
   38321             :                         synthesize_sf3ext_expression::
   38322         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
   38323             : 
   38324             :                      exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
   38325             : 
   38326         140 :                      return (synthesis_result) ? result : error_node();
   38327             :                   }
   38328             :                   // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
   38329        3830 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   38330             :                   {
   38331             :                      const bool synthesis_result =
   38332             :                         synthesize_sf3ext_expression::
   38333         280 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
   38334             : 
   38335             :                      exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
   38336             : 
   38337         140 :                      return (synthesis_result) ? result : error_node();
   38338             :                   }
   38339             :                   // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
   38340        3690 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   38341             :                   {
   38342             :                      const bool synthesis_result =
   38343             :                         synthesize_sf3ext_expression::
   38344         160 :                            template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
   38345             : 
   38346             :                      exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
   38347             : 
   38348          80 :                      return (synthesis_result) ? result : error_node();
   38349             :                   }
   38350             :                   // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
   38351        3610 :                   else if (
   38352        3610 :                             (std::equal_to<T>()(c0,c1)) &&
   38353         200 :                             (details::e_mul == o0)      &&
   38354        3890 :                             (details::e_mul == o2)      &&
   38355             :                             (
   38356          80 :                               (details::e_add == o1) || (details::e_sub == o1)
   38357             :                             )
   38358             :                           )
   38359             :                   {
   38360          80 :                      std::string specfunc;
   38361             : 
   38362          80 :                      switch (o1)
   38363             :                      {
   38364          40 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   38365          40 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   38366           0 :                         default             : return error_node();
   38367             :                      }
   38368             : 
   38369             :                      const bool synthesis_result =
   38370             :                         synthesize_sf3ext_expression::
   38371          80 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   38372             : 
   38373             :                      exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
   38374             : 
   38375          80 :                      return (synthesis_result) ? result : error_node();
   38376          80 :                   }
   38377             :                }
   38378             : 
   38379             :                const bool synthesis_result =
   38380             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38381        3530 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
   38382             : 
   38383        3530 :                if (synthesis_result)
   38384        3285 :                   return result;
   38385             : 
   38386         245 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38387         245 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   38388         245 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38389             : 
   38390         245 :                if (!expr_gen.valid_operator(o0,f0))
   38391           0 :                   return error_node();
   38392         245 :                else if (!expr_gen.valid_operator(o1,f1))
   38393           0 :                   return error_node();
   38394         245 :                else if (!expr_gen.valid_operator(o2,f2))
   38395           0 :                   return error_node();
   38396             :                else
   38397         245 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
   38398             :             }
   38399             : 
   38400        3530 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38401             :                                          const details::operator_type o0,
   38402             :                                          const details::operator_type o1,
   38403             :                                          const details::operator_type o2)
   38404             :             {
   38405        7060 :                return details::build_string()
   38406        7060 :                   << "(t" << expr_gen.to_str(o0)
   38407        7060 :                   << "t)" << expr_gen.to_str(o1)
   38408        7060 :                   << "(t" << expr_gen.to_str(o2)
   38409        7060 :                   << "t)";
   38410             :             }
   38411             :          };
   38412             : 
   38413             :          struct synthesize_vovovov_expression1
   38414             :          {
   38415             :             typedef typename vovovov_t::type1 node_type;
   38416             :             typedef typename vovovov_t::sf4_type sf4_type;
   38417             :             typedef typename node_type::T0 T0;
   38418             :             typedef typename node_type::T1 T1;
   38419             :             typedef typename node_type::T2 T2;
   38420             :             typedef typename node_type::T3 T3;
   38421             : 
   38422           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38423             :                                                       const details::operator_type& operation,
   38424             :                                                       expression_node_ptr (&branch)[2])
   38425             :             {
   38426             :                // v0 o0 (v1 o1 (v2 o2 v3))
   38427             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   38428             : 
   38429           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   38430           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38431           0 :                const Type& v1 = vovov->t0();
   38432           0 :                const Type& v2 = vovov->t1();
   38433           0 :                const Type& v3 = vovov->t2();
   38434           0 :                const details::operator_type o0 = operation;
   38435           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   38436           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   38437             : 
   38438           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38439           0 :                binary_functor_t f1 = vovov->f0();
   38440           0 :                binary_functor_t f2 = vovov->f1();
   38441             : 
   38442           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38443             : 
   38444           0 :                expression_node_ptr result = error_node();
   38445             : 
   38446             :                const bool synthesis_result =
   38447             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38448           0 :                      (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   38449             : 
   38450           0 :                if (synthesis_result)
   38451           0 :                   return result;
   38452           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38453           0 :                   return error_node();
   38454             : 
   38455             :                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
   38456             : 
   38457           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   38458             :             }
   38459             : 
   38460           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38461             :                                          const details::operator_type o0,
   38462             :                                          const details::operator_type o1,
   38463             :                                          const details::operator_type o2)
   38464             :             {
   38465           0 :                return details::build_string()
   38466           0 :                   << "t"  << expr_gen.to_str(o0)
   38467           0 :                   << "(t" << expr_gen.to_str(o1)
   38468           0 :                   << "(t" << expr_gen.to_str(o2)
   38469           0 :                   << "t))";
   38470             :             }
   38471             :          };
   38472             : 
   38473             :          struct synthesize_vovovoc_expression1
   38474             :          {
   38475             :             typedef typename vovovoc_t::type1 node_type;
   38476             :             typedef typename vovovoc_t::sf4_type sf4_type;
   38477             :             typedef typename node_type::T0 T0;
   38478             :             typedef typename node_type::T1 T1;
   38479             :             typedef typename node_type::T2 T2;
   38480             :             typedef typename node_type::T3 T3;
   38481             : 
   38482           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38483             :                                                       const details::operator_type& operation,
   38484             :                                                       expression_node_ptr (&branch)[2])
   38485             :             {
   38486             :                // v0 o0 (v1 o1 (v2 o2 c))
   38487             :                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
   38488             : 
   38489           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   38490           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38491           0 :                const Type& v1 = vovoc->t0();
   38492           0 :                const Type& v2 = vovoc->t1();
   38493           0 :                const Type   c = vovoc->t2();
   38494           0 :                const details::operator_type o0 = operation;
   38495           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   38496           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   38497             : 
   38498           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38499           0 :                binary_functor_t f1 = vovoc->f0();
   38500           0 :                binary_functor_t f2 = vovoc->f1();
   38501             : 
   38502           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38503             : 
   38504           0 :                expression_node_ptr result = error_node();
   38505             : 
   38506             :                const bool synthesis_result =
   38507             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38508           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   38509             : 
   38510           0 :                if (synthesis_result)
   38511           0 :                   return result;
   38512           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38513           0 :                   return error_node();
   38514             : 
   38515             :                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
   38516             : 
   38517           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   38518             :             }
   38519             : 
   38520           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38521             :                                          const details::operator_type o0,
   38522             :                                          const details::operator_type o1,
   38523             :                                          const details::operator_type o2)
   38524             :             {
   38525           0 :                return details::build_string()
   38526           0 :                   << "t"  << expr_gen.to_str(o0)
   38527           0 :                   << "(t" << expr_gen.to_str(o1)
   38528           0 :                   << "(t" << expr_gen.to_str(o2)
   38529           0 :                   << "t))";
   38530             :             }
   38531             :          };
   38532             : 
   38533             :          struct synthesize_vovocov_expression1
   38534             :          {
   38535             :             typedef typename vovocov_t::type1 node_type;
   38536             :             typedef typename vovocov_t::sf4_type sf4_type;
   38537             :             typedef typename node_type::T0 T0;
   38538             :             typedef typename node_type::T1 T1;
   38539             :             typedef typename node_type::T2 T2;
   38540             :             typedef typename node_type::T3 T3;
   38541             : 
   38542           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38543             :                                                       const details::operator_type& operation,
   38544             :                                                       expression_node_ptr (&branch)[2])
   38545             :             {
   38546             :                // v0 o0 (v1 o1 (c o2 v2))
   38547             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   38548             : 
   38549           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   38550           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38551           0 :                const Type& v1 = vocov->t0();
   38552           0 :                const Type   c = vocov->t1();
   38553           0 :                const Type& v2 = vocov->t2();
   38554           0 :                const details::operator_type o0 = operation;
   38555           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   38556           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   38557             : 
   38558           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38559           0 :                binary_functor_t f1 = vocov->f0();
   38560           0 :                binary_functor_t f2 = vocov->f1();
   38561             : 
   38562           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38563             : 
   38564           0 :                expression_node_ptr result = error_node();
   38565             : 
   38566             :                const bool synthesis_result =
   38567             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38568           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   38569             : 
   38570           0 :                if (synthesis_result)
   38571           0 :                   return result;
   38572           0 :                if (!expr_gen.valid_operator(o0,f0))
   38573           0 :                   return error_node();
   38574             : 
   38575             :                exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
   38576             : 
   38577           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   38578             :             }
   38579             : 
   38580           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38581             :                                          const details::operator_type o0,
   38582             :                                          const details::operator_type o1,
   38583             :                                          const details::operator_type o2)
   38584             :             {
   38585           0 :                return details::build_string()
   38586           0 :                   << "t"  << expr_gen.to_str(o0)
   38587           0 :                   << "(t" << expr_gen.to_str(o1)
   38588           0 :                   << "(t" << expr_gen.to_str(o2)
   38589           0 :                   << "t))";
   38590             :             }
   38591             :          };
   38592             : 
   38593             :          struct synthesize_vocovov_expression1
   38594             :          {
   38595             :             typedef typename vocovov_t::type1 node_type;
   38596             :             typedef typename vocovov_t::sf4_type sf4_type;
   38597             :             typedef typename node_type::T0 T0;
   38598             :             typedef typename node_type::T1 T1;
   38599             :             typedef typename node_type::T2 T2;
   38600             :             typedef typename node_type::T3 T3;
   38601             : 
   38602           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38603             :                                                       const details::operator_type& operation,
   38604             :                                                       expression_node_ptr (&branch)[2])
   38605             :             {
   38606             :                // v0 o0 (c o1 (v1 o2 v2))
   38607             :                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
   38608             : 
   38609           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
   38610           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38611           0 :                const Type   c = covov->t0();
   38612           0 :                const Type& v1 = covov->t1();
   38613           0 :                const Type& v2 = covov->t2();
   38614           0 :                const details::operator_type o0 = operation;
   38615           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
   38616           0 :                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
   38617             : 
   38618           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38619           0 :                binary_functor_t f1 = covov->f0();
   38620           0 :                binary_functor_t f2 = covov->f1();
   38621             : 
   38622           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38623             : 
   38624           0 :                expression_node_ptr result = error_node();
   38625             : 
   38626             :                const bool synthesis_result =
   38627             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38628           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   38629             : 
   38630           0 :                if (synthesis_result)
   38631           0 :                   return result;
   38632           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38633           0 :                   return error_node();
   38634             : 
   38635             :                exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
   38636             : 
   38637           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   38638             :             }
   38639             : 
   38640           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38641             :                                          const details::operator_type o0,
   38642             :                                          const details::operator_type o1,
   38643             :                                          const details::operator_type o2)
   38644             :             {
   38645           0 :                return details::build_string()
   38646           0 :                   << "t"  << expr_gen.to_str(o0)
   38647           0 :                   << "(t" << expr_gen.to_str(o1)
   38648           0 :                   << "(t" << expr_gen.to_str(o2)
   38649           0 :                   << "t))";
   38650             :             }
   38651             :          };
   38652             : 
   38653             :          struct synthesize_covovov_expression1
   38654             :          {
   38655             :             typedef typename covovov_t::type1 node_type;
   38656             :             typedef typename covovov_t::sf4_type sf4_type;
   38657             :             typedef typename node_type::T0 T0;
   38658             :             typedef typename node_type::T1 T1;
   38659             :             typedef typename node_type::T2 T2;
   38660             :             typedef typename node_type::T3 T3;
   38661             : 
   38662           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38663             :                                                       const details::operator_type& operation,
   38664             :                                                       expression_node_ptr (&branch)[2])
   38665             :             {
   38666             :                // c o0 (v0 o1 (v1 o2 v2))
   38667             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   38668             : 
   38669           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   38670           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   38671           0 :                const Type& v0 = vovov->t0();
   38672           0 :                const Type& v1 = vovov->t1();
   38673           0 :                const Type& v2 = vovov->t2();
   38674           0 :                const details::operator_type o0 = operation;
   38675           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   38676           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   38677             : 
   38678           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38679           0 :                binary_functor_t f1 = vovov->f0();
   38680           0 :                binary_functor_t f2 = vovov->f1();
   38681             : 
   38682           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38683           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38684             : 
   38685           0 :                expression_node_ptr result = error_node();
   38686             : 
   38687             :                const bool synthesis_result =
   38688             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38689           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   38690             : 
   38691           0 :                if (synthesis_result)
   38692           0 :                   return result;
   38693           0 :                if (!expr_gen.valid_operator(o0,f0))
   38694           0 :                   return error_node();
   38695             : 
   38696             :                exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
   38697             : 
   38698           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   38699             :             }
   38700             : 
   38701           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38702             :                                          const details::operator_type o0,
   38703             :                                          const details::operator_type o1,
   38704             :                                          const details::operator_type o2)
   38705             :             {
   38706           0 :                return details::build_string()
   38707           0 :                   << "t"  << expr_gen.to_str(o0)
   38708           0 :                   << "(t" << expr_gen.to_str(o1)
   38709           0 :                   << "(t" << expr_gen.to_str(o2)
   38710           0 :                   << "t))";
   38711             :             }
   38712             :          };
   38713             : 
   38714             :          struct synthesize_covocov_expression1
   38715             :          {
   38716             :             typedef typename covocov_t::type1 node_type;
   38717             :             typedef typename covocov_t::sf4_type sf4_type;
   38718             :             typedef typename node_type::T0 T0;
   38719             :             typedef typename node_type::T1 T1;
   38720             :             typedef typename node_type::T2 T2;
   38721             :             typedef typename node_type::T3 T3;
   38722             : 
   38723           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38724             :                                                       const details::operator_type& operation,
   38725             :                                                       expression_node_ptr (&branch)[2])
   38726             :             {
   38727             :                // c0 o0 (v0 o1 (c1 o2 v1))
   38728             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   38729             : 
   38730           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   38731           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   38732           0 :                const Type& v0 = vocov->t0();
   38733           0 :                const Type  c1 = vocov->t1();
   38734           0 :                const Type& v1 = vocov->t2();
   38735           0 :                const details::operator_type o0 = operation;
   38736           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   38737           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   38738             : 
   38739           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38740           0 :                binary_functor_t f1 = vocov->f0();
   38741           0 :                binary_functor_t f2 = vocov->f1();
   38742             : 
   38743           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38744           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38745             : 
   38746           0 :                expression_node_ptr result = error_node();
   38747             : 
   38748             :                const bool synthesis_result =
   38749             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38750           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   38751             : 
   38752           0 :                if (synthesis_result)
   38753           0 :                   return result;
   38754           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38755           0 :                   return error_node();
   38756             : 
   38757             :                exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
   38758             : 
   38759           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   38760             :             }
   38761             : 
   38762           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38763             :                                          const details::operator_type o0,
   38764             :                                          const details::operator_type o1,
   38765             :                                          const details::operator_type o2)
   38766             :             {
   38767           0 :                return details::build_string()
   38768           0 :                   << "t"  << expr_gen.to_str(o0)
   38769           0 :                   << "(t" << expr_gen.to_str(o1)
   38770           0 :                   << "(t" << expr_gen.to_str(o2)
   38771           0 :                   << "t))";
   38772             :             }
   38773             :          };
   38774             : 
   38775             :          struct synthesize_vocovoc_expression1
   38776             :          {
   38777             :             typedef typename vocovoc_t::type1 node_type;
   38778             :             typedef typename vocovoc_t::sf4_type sf4_type;
   38779             :             typedef typename node_type::T0 T0;
   38780             :             typedef typename node_type::T1 T1;
   38781             :             typedef typename node_type::T2 T2;
   38782             :             typedef typename node_type::T3 T3;
   38783             : 
   38784           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38785             :                                                       const details::operator_type& operation,
   38786             :                                                       expression_node_ptr (&branch)[2])
   38787             :             {
   38788             :                // v0 o0 (c0 o1 (v1 o2 c2))
   38789             :                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
   38790             : 
   38791           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
   38792           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38793           0 :                const Type  c0 = covoc->t0();
   38794           0 :                const Type& v1 = covoc->t1();
   38795           0 :                const Type  c1 = covoc->t2();
   38796           0 :                const details::operator_type o0 = operation;
   38797           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
   38798           0 :                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
   38799             : 
   38800           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38801           0 :                binary_functor_t f1 = covoc->f0();
   38802           0 :                binary_functor_t f2 = covoc->f1();
   38803             : 
   38804           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38805             : 
   38806           0 :                expression_node_ptr result = error_node();
   38807             : 
   38808             :                const bool synthesis_result =
   38809             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38810           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   38811             : 
   38812           0 :                if (synthesis_result)
   38813           0 :                   return result;
   38814           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38815           0 :                   return error_node();
   38816             : 
   38817             :                exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
   38818             : 
   38819           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   38820             :             }
   38821             : 
   38822           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38823             :                                          const details::operator_type o0,
   38824             :                                          const details::operator_type o1,
   38825             :                                          const details::operator_type o2)
   38826             :             {
   38827           0 :                return details::build_string()
   38828           0 :                   << "t"  << expr_gen.to_str(o0)
   38829           0 :                   << "(t" << expr_gen.to_str(o1)
   38830           0 :                   << "(t" << expr_gen.to_str(o2)
   38831           0 :                   << "t))";
   38832             :             }
   38833             :          };
   38834             : 
   38835             :          struct synthesize_covovoc_expression1
   38836             :          {
   38837             :             typedef typename covovoc_t::type1 node_type;
   38838             :             typedef typename covovoc_t::sf4_type sf4_type;
   38839             :             typedef typename node_type::T0 T0;
   38840             :             typedef typename node_type::T1 T1;
   38841             :             typedef typename node_type::T2 T2;
   38842             :             typedef typename node_type::T3 T3;
   38843           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38844             :                                                       const details::operator_type& operation,
   38845             :                                                       expression_node_ptr (&branch)[2])
   38846             :             {
   38847             :                // c0 o0 (v0 o1 (v1 o2 c1))
   38848             :                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
   38849             : 
   38850           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   38851           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   38852           0 :                const Type& v0 = vovoc->t0();
   38853           0 :                const Type& v1 = vovoc->t1();
   38854           0 :                const Type  c1 = vovoc->t2();
   38855           0 :                const details::operator_type o0 = operation;
   38856           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   38857           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   38858             : 
   38859           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38860           0 :                binary_functor_t f1 = vovoc->f0();
   38861           0 :                binary_functor_t f2 = vovoc->f1();
   38862             : 
   38863           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38864           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38865             : 
   38866           0 :                expression_node_ptr result = error_node();
   38867             : 
   38868             :                const bool synthesis_result =
   38869             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38870           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   38871             : 
   38872           0 :                if (synthesis_result)
   38873           0 :                   return result;
   38874           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38875           0 :                   return error_node();
   38876             : 
   38877             :                exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
   38878             : 
   38879           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   38880             :             }
   38881             : 
   38882           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38883             :                                          const details::operator_type o0,
   38884             :                                          const details::operator_type o1,
   38885             :                                          const details::operator_type o2)
   38886             :             {
   38887           0 :                return details::build_string()
   38888           0 :                   << "t"  << expr_gen.to_str(o0)
   38889           0 :                   << "(t" << expr_gen.to_str(o1)
   38890           0 :                   << "(t" << expr_gen.to_str(o2)
   38891           0 :                   << "t))";
   38892             :             }
   38893             :          };
   38894             : 
   38895             :          struct synthesize_vococov_expression1
   38896             :          {
   38897             :             typedef typename vococov_t::type1 node_type;
   38898             :             typedef typename vococov_t::sf4_type sf4_type;
   38899             :             typedef typename node_type::T0 T0;
   38900             :             typedef typename node_type::T1 T1;
   38901             :             typedef typename node_type::T2 T2;
   38902             :             typedef typename node_type::T3 T3;
   38903             : 
   38904           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38905             :                                                       const details::operator_type& operation,
   38906             :                                                       expression_node_ptr (&branch)[2])
   38907             :             {
   38908             :                // v0 o0 (c0 o1 (c1 o2 v1))
   38909             :                typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
   38910             : 
   38911           0 :                const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
   38912           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38913           0 :                const Type  c0 = cocov->t0();
   38914           0 :                const Type  c1 = cocov->t1();
   38915           0 :                const Type& v1 = cocov->t2();
   38916           0 :                const details::operator_type o0 = operation;
   38917           0 :                const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
   38918           0 :                const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
   38919             : 
   38920           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38921           0 :                binary_functor_t f1 = cocov->f0();
   38922           0 :                binary_functor_t f2 = cocov->f1();
   38923             : 
   38924           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38925             : 
   38926           0 :                expression_node_ptr result = error_node();
   38927             : 
   38928             :                const bool synthesis_result =
   38929             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38930           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
   38931             : 
   38932           0 :                if (synthesis_result)
   38933           0 :                   return result;
   38934           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38935           0 :                   return error_node();
   38936             : 
   38937             :                exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
   38938             : 
   38939           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
   38940             :             }
   38941             : 
   38942           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38943             :                                          const details::operator_type o0,
   38944             :                                          const details::operator_type o1,
   38945             :                                          const details::operator_type o2)
   38946             :             {
   38947           0 :                return details::build_string()
   38948           0 :                   << "t"  << expr_gen.to_str(o0)
   38949           0 :                   << "(t" << expr_gen.to_str(o1)
   38950           0 :                   << "(t" << expr_gen.to_str(o2)
   38951           0 :                   << "t))";
   38952             :             }
   38953             :          };
   38954             : 
   38955             :          struct synthesize_vovovov_expression2
   38956             :          {
   38957             :             typedef typename vovovov_t::type2 node_type;
   38958             :             typedef typename vovovov_t::sf4_type sf4_type;
   38959             :             typedef typename node_type::T0 T0;
   38960             :             typedef typename node_type::T1 T1;
   38961             :             typedef typename node_type::T2 T2;
   38962             :             typedef typename node_type::T3 T3;
   38963             : 
   38964           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38965             :                                                       const details::operator_type& operation,
   38966             :                                                       expression_node_ptr (&branch)[2])
   38967             :             {
   38968             :                // v0 o0 ((v1 o1 v2) o2 v3)
   38969             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   38970             : 
   38971           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   38972           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   38973           0 :                const Type& v1 = vovov->t0();
   38974           0 :                const Type& v2 = vovov->t1();
   38975           0 :                const Type& v3 = vovov->t2();
   38976           0 :                const details::operator_type o0 = operation;
   38977           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   38978           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   38979             : 
   38980           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38981           0 :                binary_functor_t f1 = vovov->f0();
   38982           0 :                binary_functor_t f2 = vovov->f1();
   38983             : 
   38984           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38985             : 
   38986           0 :                expression_node_ptr result = error_node();
   38987             : 
   38988             :                const bool synthesis_result =
   38989             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38990           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   38991             : 
   38992           0 :                if (synthesis_result)
   38993           0 :                   return result;
   38994           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38995           0 :                   return error_node();
   38996             : 
   38997             :                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
   38998             : 
   38999           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   39000             :             }
   39001             : 
   39002           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39003             :                                          const details::operator_type o0,
   39004             :                                          const details::operator_type o1,
   39005             :                                          const details::operator_type o2)
   39006             :             {
   39007           0 :                return details::build_string()
   39008           0 :                   << "t"   << expr_gen.to_str(o0)
   39009           0 :                   << "((t" << expr_gen.to_str(o1)
   39010           0 :                   << "t)"  << expr_gen.to_str(o2)
   39011           0 :                   << "t)";
   39012             :             }
   39013             :          };
   39014             : 
   39015             :          struct synthesize_vovovoc_expression2
   39016             :          {
   39017             :             typedef typename vovovoc_t::type2 node_type;
   39018             :             typedef typename vovovoc_t::sf4_type sf4_type;
   39019             :             typedef typename node_type::T0 T0;
   39020             :             typedef typename node_type::T1 T1;
   39021             :             typedef typename node_type::T2 T2;
   39022             :             typedef typename node_type::T3 T3;
   39023             : 
   39024           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39025             :                                                       const details::operator_type& operation,
   39026             :                                                       expression_node_ptr (&branch)[2])
   39027             :             {
   39028             :                // v0 o0 ((v1 o1 v2) o2 c)
   39029             :                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
   39030             : 
   39031           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   39032           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   39033           0 :                const Type& v1 = vovoc->t0();
   39034           0 :                const Type& v2 = vovoc->t1();
   39035           0 :                const Type   c = vovoc->t2();
   39036           0 :                const details::operator_type o0 = operation;
   39037           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   39038           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   39039             : 
   39040           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39041           0 :                binary_functor_t f1 = vovoc->f0();
   39042           0 :                binary_functor_t f2 = vovoc->f1();
   39043             : 
   39044           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39045             : 
   39046           0 :                expression_node_ptr result = error_node();
   39047             : 
   39048             :                const bool synthesis_result =
   39049             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39050           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   39051             : 
   39052           0 :                if (synthesis_result)
   39053           0 :                   return result;
   39054           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39055           0 :                   return error_node();
   39056             : 
   39057             :                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
   39058             : 
   39059           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   39060             :             }
   39061             : 
   39062           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39063             :                                          const details::operator_type o0,
   39064             :                                          const details::operator_type o1,
   39065             :                                          const details::operator_type o2)
   39066             :             {
   39067           0 :                return details::build_string()
   39068           0 :                   << "t"   << expr_gen.to_str(o0)
   39069           0 :                   << "((t" << expr_gen.to_str(o1)
   39070           0 :                   << "t)"  << expr_gen.to_str(o2)
   39071           0 :                   << "t)";
   39072             :             }
   39073             :          };
   39074             : 
   39075             :          struct synthesize_vovocov_expression2
   39076             :          {
   39077             :             typedef typename vovocov_t::type2 node_type;
   39078             :             typedef typename vovocov_t::sf4_type sf4_type;
   39079             :             typedef typename node_type::T0 T0;
   39080             :             typedef typename node_type::T1 T1;
   39081             :             typedef typename node_type::T2 T2;
   39082             :             typedef typename node_type::T3 T3;
   39083             : 
   39084           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39085             :                                                       const details::operator_type& operation,
   39086             :                                                       expression_node_ptr (&branch)[2])
   39087             :             {
   39088             :                // v0 o0 ((v1 o1 c) o2 v2)
   39089             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   39090             : 
   39091           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   39092           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   39093           0 :                const Type& v1 = vocov->t0();
   39094           0 :                const Type   c = vocov->t1();
   39095           0 :                const Type& v2 = vocov->t2();
   39096           0 :                const details::operator_type o0 = operation;
   39097           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   39098           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   39099             : 
   39100           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39101           0 :                binary_functor_t f1 = vocov->f0();
   39102           0 :                binary_functor_t f2 = vocov->f1();
   39103             : 
   39104           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39105             : 
   39106           0 :                expression_node_ptr result = error_node();
   39107             : 
   39108             :                const bool synthesis_result =
   39109             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39110           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   39111             : 
   39112           0 :                if (synthesis_result)
   39113           0 :                   return result;
   39114           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39115           0 :                   return error_node();
   39116             : 
   39117             :                exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
   39118             : 
   39119           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   39120             :             }
   39121             : 
   39122           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39123             :                                          const details::operator_type o0,
   39124             :                                          const details::operator_type o1,
   39125             :                                          const details::operator_type o2)
   39126             :             {
   39127           0 :                return details::build_string()
   39128           0 :                   << "t"   << expr_gen.to_str(o0)
   39129           0 :                   << "((t" << expr_gen.to_str(o1)
   39130           0 :                   << "t)"  << expr_gen.to_str(o2)
   39131           0 :                   << "t)";
   39132             :             }
   39133             :          };
   39134             : 
   39135             :          struct synthesize_vocovov_expression2
   39136             :          {
   39137             :             typedef typename vocovov_t::type2 node_type;
   39138             :             typedef typename vocovov_t::sf4_type sf4_type;
   39139             :             typedef typename node_type::T0 T0;
   39140             :             typedef typename node_type::T1 T1;
   39141             :             typedef typename node_type::T2 T2;
   39142             :             typedef typename node_type::T3 T3;
   39143             : 
   39144           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39145             :                                                       const details::operator_type& operation,
   39146             :                                                       expression_node_ptr (&branch)[2])
   39147             :             {
   39148             :                // v0 o0 ((c o1 v1) o2 v2)
   39149             :                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
   39150             : 
   39151           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
   39152           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   39153           0 :                const Type   c = covov->t0();
   39154           0 :                const Type& v1 = covov->t1();
   39155           0 :                const Type& v2 = covov->t2();
   39156           0 :                const details::operator_type o0 = operation;
   39157           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
   39158           0 :                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
   39159             : 
   39160           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39161           0 :                binary_functor_t f1 = covov->f0();
   39162           0 :                binary_functor_t f2 = covov->f1();
   39163             : 
   39164           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39165             : 
   39166           0 :                expression_node_ptr result = error_node();
   39167             : 
   39168             :                const bool synthesis_result =
   39169             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39170           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   39171             : 
   39172           0 :                if (synthesis_result)
   39173           0 :                   return result;
   39174           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39175           0 :                   return error_node();
   39176             : 
   39177             :                exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
   39178             : 
   39179           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   39180             :             }
   39181             : 
   39182           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39183             :                                          const details::operator_type o0,
   39184             :                                          const details::operator_type o1,
   39185             :                                          const details::operator_type o2)
   39186             :             {
   39187           0 :                return details::build_string()
   39188           0 :                   << "t"   << expr_gen.to_str(o0)
   39189           0 :                   << "((t" << expr_gen.to_str(o1)
   39190           0 :                   << "t)"  << expr_gen.to_str(o2)
   39191           0 :                   << "t)";
   39192             :             }
   39193             :          };
   39194             : 
   39195             :          struct synthesize_covovov_expression2
   39196             :          {
   39197             :             typedef typename covovov_t::type2 node_type;
   39198             :             typedef typename covovov_t::sf4_type sf4_type;
   39199             :             typedef typename node_type::T0 T0;
   39200             :             typedef typename node_type::T1 T1;
   39201             :             typedef typename node_type::T2 T2;
   39202             :             typedef typename node_type::T3 T3;
   39203             : 
   39204           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39205             :                                                       const details::operator_type& operation,
   39206             :                                                       expression_node_ptr (&branch)[2])
   39207             :             {
   39208             :                // c o0 ((v1 o1 v2) o2 v3)
   39209             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   39210             : 
   39211           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   39212           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   39213           0 :                const Type& v0 = vovov->t0();
   39214           0 :                const Type& v1 = vovov->t1();
   39215           0 :                const Type& v2 = vovov->t2();
   39216           0 :                const details::operator_type o0 = operation;
   39217           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   39218           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   39219             : 
   39220           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39221           0 :                binary_functor_t f1 = vovov->f0();
   39222           0 :                binary_functor_t f2 = vovov->f1();
   39223             : 
   39224           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39225           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39226             : 
   39227           0 :                expression_node_ptr result = error_node();
   39228             : 
   39229             :                const bool synthesis_result =
   39230             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39231           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   39232             : 
   39233           0 :                if (synthesis_result)
   39234           0 :                   return result;
   39235           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39236           0 :                   return error_node();
   39237             : 
   39238             :                exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
   39239             : 
   39240           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   39241             :             }
   39242             : 
   39243           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39244             :                                          const details::operator_type o0,
   39245             :                                          const details::operator_type o1,
   39246             :                                          const details::operator_type o2)
   39247             :             {
   39248           0 :                return details::build_string()
   39249           0 :                   << "t"   << expr_gen.to_str(o0)
   39250           0 :                   << "((t" << expr_gen.to_str(o1)
   39251           0 :                   << "t)"  << expr_gen.to_str(o2)
   39252           0 :                   << "t)";
   39253             :             }
   39254             :         };
   39255             : 
   39256             :          struct synthesize_covocov_expression2
   39257             :          {
   39258             :             typedef typename covocov_t::type2 node_type;
   39259             :             typedef typename covocov_t::sf4_type sf4_type;
   39260             :             typedef typename node_type::T0 T0;
   39261             :             typedef typename node_type::T1 T1;
   39262             :             typedef typename node_type::T2 T2;
   39263             :             typedef typename node_type::T3 T3;
   39264             : 
   39265           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39266             :                                                       const details::operator_type& operation,
   39267             :                                                       expression_node_ptr (&branch)[2])
   39268             :             {
   39269             :                // c0 o0 ((v0 o1 c1) o2 v1)
   39270             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   39271             : 
   39272           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   39273           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   39274           0 :                const Type& v0 = vocov->t0();
   39275           0 :                const Type  c1 = vocov->t1();
   39276           0 :                const Type& v1 = vocov->t2();
   39277           0 :                const details::operator_type o0 = operation;
   39278           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   39279           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   39280             : 
   39281           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39282           0 :                binary_functor_t f1 = vocov->f0();
   39283           0 :                binary_functor_t f2 = vocov->f1();
   39284             : 
   39285           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39286           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39287             : 
   39288           0 :                expression_node_ptr result = error_node();
   39289             : 
   39290             :                const bool synthesis_result =
   39291             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39292           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   39293             : 
   39294           0 :                if (synthesis_result)
   39295           0 :                   return result;
   39296           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39297           0 :                   return error_node();
   39298             : 
   39299             :                exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
   39300             : 
   39301           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   39302             :             }
   39303             : 
   39304           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39305             :                                          const details::operator_type o0,
   39306             :                                          const details::operator_type o1,
   39307             :                                          const details::operator_type o2)
   39308             :             {
   39309           0 :                return details::build_string()
   39310           0 :                   << "t"   << expr_gen.to_str(o0)
   39311           0 :                   << "((t" << expr_gen.to_str(o1)
   39312           0 :                   << "t)"  << expr_gen.to_str(o2)
   39313           0 :                   << "t)";
   39314             :             }
   39315             :          };
   39316             : 
   39317             :          struct synthesize_vocovoc_expression2
   39318             :          {
   39319             :             typedef typename vocovoc_t::type2 node_type;
   39320             :             typedef typename vocovoc_t::sf4_type sf4_type;
   39321             :             typedef typename node_type::T0 T0;
   39322             :             typedef typename node_type::T1 T1;
   39323             :             typedef typename node_type::T2 T2;
   39324             :             typedef typename node_type::T3 T3;
   39325             : 
   39326           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39327             :                                                       const details::operator_type& operation,
   39328             :                                                       expression_node_ptr (&branch)[2])
   39329             :             {
   39330             :                // v0 o0 ((c0 o1 v1) o2 c1)
   39331             :                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
   39332             : 
   39333           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
   39334           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   39335           0 :                const Type  c0 = covoc->t0();
   39336           0 :                const Type& v1 = covoc->t1();
   39337           0 :                const Type  c1 = covoc->t2();
   39338           0 :                const details::operator_type o0 = operation;
   39339           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
   39340           0 :                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
   39341             : 
   39342           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39343           0 :                binary_functor_t f1 = covoc->f0();
   39344           0 :                binary_functor_t f2 = covoc->f1();
   39345             : 
   39346           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39347             : 
   39348           0 :                expression_node_ptr result = error_node();
   39349             : 
   39350             :                const bool synthesis_result =
   39351             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39352           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   39353             : 
   39354           0 :                if (synthesis_result)
   39355           0 :                   return result;
   39356           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39357           0 :                   return error_node();
   39358             : 
   39359             :                exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
   39360             : 
   39361           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   39362             :             }
   39363             : 
   39364           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39365             :                                          const details::operator_type o0,
   39366             :                                          const details::operator_type o1,
   39367             :                                          const details::operator_type o2)
   39368             :             {
   39369           0 :                return details::build_string()
   39370           0 :                   << "t"   << expr_gen.to_str(o0)
   39371           0 :                   << "((t" << expr_gen.to_str(o1)
   39372           0 :                   << "t)"  << expr_gen.to_str(o2)
   39373           0 :                   << "t)";
   39374             :             }
   39375             :          };
   39376             : 
   39377             :          struct synthesize_covovoc_expression2
   39378             :          {
   39379             :             typedef typename covovoc_t::type2 node_type;
   39380             :             typedef typename covovoc_t::sf4_type sf4_type;
   39381             :             typedef typename node_type::T0 T0;
   39382             :             typedef typename node_type::T1 T1;
   39383             :             typedef typename node_type::T2 T2;
   39384             :             typedef typename node_type::T3 T3;
   39385             : 
   39386           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39387             :                                                       const details::operator_type& operation,
   39388             :                                                       expression_node_ptr (&branch)[2])
   39389             :             {
   39390             :                // c0 o0 ((v0 o1 v1) o2 c1)
   39391             :                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
   39392             : 
   39393           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   39394           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   39395           0 :                const Type& v0 = vovoc->t0();
   39396           0 :                const Type& v1 = vovoc->t1();
   39397           0 :                const Type  c1 = vovoc->t2();
   39398           0 :                const details::operator_type o0 = operation;
   39399           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   39400           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   39401             : 
   39402           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   39403           0 :                binary_functor_t f1 = vovoc->f0();
   39404           0 :                binary_functor_t f2 = vovoc->f1();
   39405             : 
   39406           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39407           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39408             : 
   39409           0 :                expression_node_ptr result = error_node();
   39410             : 
   39411             :                const bool synthesis_result =
   39412             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39413           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   39414             : 
   39415           0 :                if (synthesis_result)
   39416           0 :                   return result;
   39417           0 :                else if (!expr_gen.valid_operator(o0,f0))
   39418           0 :                   return error_node();
   39419             : 
   39420             :                exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
   39421             : 
   39422           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   39423             :             }
   39424             : 
   39425           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39426             :                                          const details::operator_type o0,
   39427             :                                          const details::operator_type o1,
   39428             :                                          const details::operator_type o2)
   39429             :             {
   39430           0 :                return details::build_string()
   39431           0 :                   << "t"   << expr_gen.to_str(o0)
   39432           0 :                   << "((t" << expr_gen.to_str(o1)
   39433           0 :                   << "t)"  << expr_gen.to_str(o2)
   39434           0 :                   << "t)";
   39435             :             }
   39436             :          };
   39437             : 
   39438             :          struct synthesize_vococov_expression2
   39439             :          {
   39440             :             typedef typename vococov_t::type2 node_type;
   39441             :             static inline expression_node_ptr process(expression_generator<Type>&,
   39442             :                                                       const details::operator_type&,
   39443             :                                                       expression_node_ptr (&)[2])
   39444             :             {
   39445             :                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
   39446             :                exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
   39447             :                return error_node();
   39448             :             }
   39449             : 
   39450             :             static inline std::string id(expression_generator<Type>&,
   39451             :                                          const details::operator_type,
   39452             :                                          const details::operator_type,
   39453             :                                          const details::operator_type)
   39454             :             {
   39455             :                return "INVALID";
   39456             :             }
   39457             :          };
   39458             : 
   39459             :          struct synthesize_vovovov_expression3
   39460             :          {
   39461             :             typedef typename vovovov_t::type3 node_type;
   39462             :             typedef typename vovovov_t::sf4_type sf4_type;
   39463             :             typedef typename node_type::T0 T0;
   39464             :             typedef typename node_type::T1 T1;
   39465             :             typedef typename node_type::T2 T2;
   39466             :             typedef typename node_type::T3 T3;
   39467             : 
   39468           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39469             :                                                       const details::operator_type& operation,
   39470             :                                                       expression_node_ptr (&branch)[2])
   39471             :             {
   39472             :                // ((v0 o0 v1) o1 v2) o2 v3
   39473             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   39474             : 
   39475           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   39476           0 :                const Type& v0 = vovov->t0();
   39477           0 :                const Type& v1 = vovov->t1();
   39478           0 :                const Type& v2 = vovov->t2();
   39479           0 :                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   39480           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   39481           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   39482           0 :                const details::operator_type o2 = operation;
   39483             : 
   39484           0 :                binary_functor_t f0 = vovov->f0();
   39485           0 :                binary_functor_t f1 = vovov->f1();
   39486           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39487             : 
   39488           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39489             : 
   39490           0 :                expression_node_ptr result = error_node();
   39491             : 
   39492             :                const bool synthesis_result =
   39493             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39494           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   39495             : 
   39496           0 :                if (synthesis_result)
   39497           0 :                   return result;
   39498           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39499           0 :                   return error_node();
   39500             : 
   39501             :                exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
   39502             : 
   39503           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   39504             :             }
   39505             : 
   39506           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39507             :                                          const details::operator_type o0,
   39508             :                                          const details::operator_type o1,
   39509             :                                          const details::operator_type o2)
   39510             :             {
   39511           0 :                return details::build_string()
   39512           0 :                   << "((t" << expr_gen.to_str(o0)
   39513           0 :                   << "t)"  << expr_gen.to_str(o1)
   39514           0 :                   << "t)"  << expr_gen.to_str(o2)
   39515           0 :                   << "t";
   39516             :             }
   39517             :          };
   39518             : 
   39519             :          struct synthesize_vovovoc_expression3
   39520             :          {
   39521             :             typedef typename vovovoc_t::type3 node_type;
   39522             :             typedef typename vovovoc_t::sf4_type sf4_type;
   39523             :             typedef typename node_type::T0 T0;
   39524             :             typedef typename node_type::T1 T1;
   39525             :             typedef typename node_type::T2 T2;
   39526             :             typedef typename node_type::T3 T3;
   39527             : 
   39528           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39529             :                                                       const details::operator_type& operation,
   39530             :                                                       expression_node_ptr (&branch)[2])
   39531             :             {
   39532             :                // ((v0 o0 v1) o1 v2) o2 c
   39533             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   39534             : 
   39535           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   39536           0 :                const Type& v0 = vovov->t0();
   39537           0 :                const Type& v1 = vovov->t1();
   39538           0 :                const Type& v2 = vovov->t2();
   39539           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   39540           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   39541           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   39542           0 :                const details::operator_type o2 = operation;
   39543             : 
   39544           0 :                binary_functor_t f0 = vovov->f0();
   39545           0 :                binary_functor_t f1 = vovov->f1();
   39546           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39547             : 
   39548           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39549           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39550             : 
   39551           0 :                expression_node_ptr result = error_node();
   39552             : 
   39553             :                const bool synthesis_result =
   39554             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39555           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   39556             : 
   39557           0 :                if (synthesis_result)
   39558           0 :                   return result;
   39559           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39560           0 :                   return error_node();
   39561             : 
   39562             :                exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
   39563             : 
   39564           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   39565             :             }
   39566             : 
   39567           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39568             :                                          const details::operator_type o0,
   39569             :                                          const details::operator_type o1,
   39570             :                                          const details::operator_type o2)
   39571             :             {
   39572           0 :                return details::build_string()
   39573           0 :                   << "((t" << expr_gen.to_str(o0)
   39574           0 :                   << "t)"  << expr_gen.to_str(o1)
   39575           0 :                   << "t)"  << expr_gen.to_str(o2)
   39576           0 :                   << "t";
   39577             :             }
   39578             :          };
   39579             : 
   39580             :          struct synthesize_vovocov_expression3
   39581             :          {
   39582             :             typedef typename vovocov_t::type3 node_type;
   39583             :             typedef typename vovocov_t::sf4_type sf4_type;
   39584             :             typedef typename node_type::T0 T0;
   39585             :             typedef typename node_type::T1 T1;
   39586             :             typedef typename node_type::T2 T2;
   39587             :             typedef typename node_type::T3 T3;
   39588             : 
   39589           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39590             :                                                       const details::operator_type& operation,
   39591             :                                                       expression_node_ptr (&branch)[2])
   39592             :             {
   39593             :                // ((v0 o0 v1) o1 c) o2 v2
   39594             :                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
   39595             : 
   39596           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
   39597           0 :                const Type& v0 = vovoc->t0();
   39598           0 :                const Type& v1 = vovoc->t1();
   39599           0 :                const Type   c = vovoc->t2();
   39600           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   39601           0 :                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
   39602           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
   39603           0 :                const details::operator_type o2 = operation;
   39604             : 
   39605           0 :                binary_functor_t f0 = vovoc->f0();
   39606           0 :                binary_functor_t f1 = vovoc->f1();
   39607           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39608             : 
   39609           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39610             : 
   39611           0 :                expression_node_ptr result = error_node();
   39612             : 
   39613             :                const bool synthesis_result =
   39614             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39615           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   39616             : 
   39617           0 :                if (synthesis_result)
   39618           0 :                   return result;
   39619           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39620           0 :                   return error_node();
   39621             : 
   39622             :                exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
   39623             : 
   39624           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   39625             :             }
   39626             : 
   39627           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39628             :                                          const details::operator_type o0,
   39629             :                                          const details::operator_type o1,
   39630             :                                          const details::operator_type o2)
   39631             :             {
   39632           0 :                return details::build_string()
   39633           0 :                   << "((t" << expr_gen.to_str(o0)
   39634           0 :                   << "t)"  << expr_gen.to_str(o1)
   39635           0 :                   << "t)"  << expr_gen.to_str(o2)
   39636           0 :                   << "t";
   39637             :             }
   39638             :          };
   39639             : 
   39640             :          struct synthesize_vocovov_expression3
   39641             :          {
   39642             :             typedef typename vocovov_t::type3 node_type;
   39643             :             typedef typename vocovov_t::sf4_type sf4_type;
   39644             :             typedef typename node_type::T0 T0;
   39645             :             typedef typename node_type::T1 T1;
   39646             :             typedef typename node_type::T2 T2;
   39647             :             typedef typename node_type::T3 T3;
   39648             : 
   39649           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39650             :                                                       const details::operator_type& operation,
   39651             :                                                       expression_node_ptr (&branch)[2])
   39652             :             {
   39653             :                // ((v0 o0 c) o1 v1) o2 v2
   39654             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   39655             : 
   39656           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   39657           0 :                const Type& v0 = vocov->t0();
   39658           0 :                const Type   c = vocov->t1();
   39659           0 :                const Type& v1 = vocov->t2();
   39660           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   39661           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   39662           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   39663           0 :                const details::operator_type o2 = operation;
   39664             : 
   39665           0 :                binary_functor_t f0 = vocov->f0();
   39666           0 :                binary_functor_t f1 = vocov->f1();
   39667           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39668             : 
   39669           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39670             : 
   39671           0 :                expression_node_ptr result = error_node();
   39672             : 
   39673             :                const bool synthesis_result =
   39674             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39675           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   39676             : 
   39677           0 :                if (synthesis_result)
   39678           0 :                   return result;
   39679           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39680           0 :                   return error_node();
   39681             : 
   39682             :                exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
   39683             : 
   39684           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   39685             :             }
   39686             : 
   39687           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39688             :                                          const details::operator_type o0,
   39689             :                                          const details::operator_type o1,
   39690             :                                          const details::operator_type o2)
   39691             :             {
   39692           0 :                return details::build_string()
   39693           0 :                   << "((t" << expr_gen.to_str(o0)
   39694           0 :                   << "t)"  << expr_gen.to_str(o1)
   39695           0 :                   << "t)"  << expr_gen.to_str(o2)
   39696           0 :                   << "t";
   39697             :             }
   39698             :          };
   39699             : 
   39700             :          struct synthesize_covovov_expression3
   39701             :          {
   39702             :             typedef typename covovov_t::type3 node_type;
   39703             :             typedef typename covovov_t::sf4_type sf4_type;
   39704             :             typedef typename node_type::T0 T0;
   39705             :             typedef typename node_type::T1 T1;
   39706             :             typedef typename node_type::T2 T2;
   39707             :             typedef typename node_type::T3 T3;
   39708             : 
   39709           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39710             :                                                       const details::operator_type& operation,
   39711             :                                                       expression_node_ptr (&branch)[2])
   39712             :             {
   39713             :                // ((c o0 v0) o1 v1) o2 v2
   39714             :                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
   39715             : 
   39716           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   39717           0 :                const Type   c = covov->t0();
   39718           0 :                const Type& v0 = covov->t1();
   39719           0 :                const Type& v1 = covov->t2();
   39720           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   39721           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   39722           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   39723           0 :                const details::operator_type o2 = operation;
   39724             : 
   39725           0 :                binary_functor_t f0 = covov->f0();
   39726           0 :                binary_functor_t f1 = covov->f1();
   39727           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39728             : 
   39729           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39730             : 
   39731           0 :                expression_node_ptr result = error_node();
   39732             : 
   39733             :                const bool synthesis_result =
   39734             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39735           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   39736             : 
   39737           0 :                if (synthesis_result)
   39738           0 :                   return result;
   39739           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39740           0 :                   return error_node();
   39741             : 
   39742             :                exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
   39743             : 
   39744           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   39745             :             }
   39746             : 
   39747           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39748             :                                          const details::operator_type o0,
   39749             :                                          const details::operator_type o1,
   39750             :                                          const details::operator_type o2)
   39751             :             {
   39752           0 :                return details::build_string()
   39753           0 :                   << "((t" << expr_gen.to_str(o0)
   39754           0 :                   << "t)"  << expr_gen.to_str(o1)
   39755           0 :                   << "t)"  << expr_gen.to_str(o2)
   39756           0 :                   << "t";
   39757             :             }
   39758             :          };
   39759             : 
   39760             :          struct synthesize_covocov_expression3
   39761             :          {
   39762             :             typedef typename covocov_t::type3 node_type;
   39763             :             typedef typename covocov_t::sf4_type sf4_type;
   39764             :             typedef typename node_type::T0 T0;
   39765             :             typedef typename node_type::T1 T1;
   39766             :             typedef typename node_type::T2 T2;
   39767             :             typedef typename node_type::T3 T3;
   39768             : 
   39769           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39770             :                                                       const details::operator_type& operation,
   39771             :                                                       expression_node_ptr (&branch)[2])
   39772             :             {
   39773             :                // ((c0 o0 v0) o1 c1) o2 v1
   39774             :                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
   39775             : 
   39776           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
   39777           0 :                const Type  c0 = covoc->t0();
   39778           0 :                const Type& v0 = covoc->t1();
   39779           0 :                const Type  c1 = covoc->t2();
   39780           0 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   39781           0 :                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
   39782           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
   39783           0 :                const details::operator_type o2 = operation;
   39784             : 
   39785           0 :                binary_functor_t f0 = covoc->f0();
   39786           0 :                binary_functor_t f1 = covoc->f1();
   39787           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39788             : 
   39789           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39790             : 
   39791           0 :                expression_node_ptr result = error_node();
   39792             : 
   39793             :                const bool synthesis_result =
   39794             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39795           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   39796             : 
   39797           0 :                if (synthesis_result)
   39798           0 :                   return result;
   39799           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39800           0 :                   return error_node();
   39801             : 
   39802             :                exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
   39803             : 
   39804           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   39805             :             }
   39806             : 
   39807           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39808             :                                          const details::operator_type o0,
   39809             :                                          const details::operator_type o1,
   39810             :                                          const details::operator_type o2)
   39811             :             {
   39812           0 :                return details::build_string()
   39813           0 :                   << "((t" << expr_gen.to_str(o0)
   39814           0 :                   << "t)"  << expr_gen.to_str(o1)
   39815           0 :                   << "t)"  << expr_gen.to_str(o2)
   39816           0 :                   << "t";
   39817             :             }
   39818             :          };
   39819             : 
   39820             :          struct synthesize_vocovoc_expression3
   39821             :          {
   39822             :             typedef typename vocovoc_t::type3 node_type;
   39823             :             typedef typename vocovoc_t::sf4_type sf4_type;
   39824             :             typedef typename node_type::T0 T0;
   39825             :             typedef typename node_type::T1 T1;
   39826             :             typedef typename node_type::T2 T2;
   39827             :             typedef typename node_type::T3 T3;
   39828             : 
   39829           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39830             :                                                       const details::operator_type& operation,
   39831             :                                                       expression_node_ptr (&branch)[2])
   39832             :             {
   39833             :                // ((v0 o0 c0) o1 v1) o2 c1
   39834             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   39835             : 
   39836           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   39837           0 :                const Type& v0 = vocov->t0();
   39838           0 :                const Type  c0 = vocov->t1();
   39839           0 :                const Type& v1 = vocov->t2();
   39840           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   39841           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   39842           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   39843           0 :                const details::operator_type o2 = operation;
   39844             : 
   39845           0 :                binary_functor_t f0 = vocov->f0();
   39846           0 :                binary_functor_t f1 = vocov->f1();
   39847           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39848             : 
   39849           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39850           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39851             : 
   39852           0 :                expression_node_ptr result = error_node();
   39853             : 
   39854             :                const bool synthesis_result =
   39855             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39856           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   39857             : 
   39858           0 :                if (synthesis_result)
   39859           0 :                   return result;
   39860           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39861           0 :                   return error_node();
   39862             : 
   39863             :                exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
   39864             : 
   39865           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   39866             :             }
   39867             : 
   39868           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39869             :                                          const details::operator_type o0,
   39870             :                                          const details::operator_type o1,
   39871             :                                          const details::operator_type o2)
   39872             :             {
   39873           0 :                return details::build_string()
   39874           0 :                   << "((t" << expr_gen.to_str(o0)
   39875           0 :                   << "t)"  << expr_gen.to_str(o1)
   39876           0 :                   << "t)"  << expr_gen.to_str(o2)
   39877           0 :                   << "t";
   39878             :             }
   39879             :          };
   39880             : 
   39881             :          struct synthesize_covovoc_expression3
   39882             :          {
   39883             :             typedef typename covovoc_t::type3 node_type;
   39884             :             typedef typename covovoc_t::sf4_type sf4_type;
   39885             :             typedef typename node_type::T0 T0;
   39886             :             typedef typename node_type::T1 T1;
   39887             :             typedef typename node_type::T2 T2;
   39888             :             typedef typename node_type::T3 T3;
   39889             : 
   39890           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39891             :                                                       const details::operator_type& operation,
   39892             :                                                       expression_node_ptr (&branch)[2])
   39893             :             {
   39894             :                // ((c0 o0 v0) o1 v1) o2 c1
   39895             :                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
   39896             : 
   39897           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   39898           0 :                const Type  c0 = covov->t0();
   39899           0 :                const Type& v0 = covov->t1();
   39900           0 :                const Type& v1 = covov->t2();
   39901           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   39902           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   39903           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   39904           0 :                const details::operator_type o2 = operation;
   39905             : 
   39906           0 :                binary_functor_t f0 = covov->f0();
   39907           0 :                binary_functor_t f1 = covov->f1();
   39908           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39909             : 
   39910           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39911           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39912             : 
   39913           0 :                expression_node_ptr result = error_node();
   39914             : 
   39915             :                const bool synthesis_result =
   39916             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39917           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   39918             : 
   39919           0 :                if (synthesis_result)
   39920           0 :                   return result;
   39921           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39922           0 :                   return error_node();
   39923             : 
   39924             :                exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
   39925             : 
   39926           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   39927             :             }
   39928             : 
   39929           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39930             :                                          const details::operator_type o0,
   39931             :                                          const details::operator_type o1,
   39932             :                                          const details::operator_type o2)
   39933             :             {
   39934           0 :                return details::build_string()
   39935           0 :                   << "((t" << expr_gen.to_str(o0)
   39936           0 :                   << "t)"  << expr_gen.to_str(o1)
   39937           0 :                   << "t)"  << expr_gen.to_str(o2)
   39938           0 :                   << "t";
   39939             :             }
   39940             :          };
   39941             : 
   39942             :          struct synthesize_vococov_expression3
   39943             :          {
   39944             :             typedef typename vococov_t::type3 node_type;
   39945             :             typedef typename vococov_t::sf4_type sf4_type;
   39946             :             typedef typename node_type::T0 T0;
   39947             :             typedef typename node_type::T1 T1;
   39948             :             typedef typename node_type::T2 T2;
   39949             :             typedef typename node_type::T3 T3;
   39950             : 
   39951           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39952             :                                                       const details::operator_type& operation,
   39953             :                                                       expression_node_ptr (&branch)[2])
   39954             :             {
   39955             :                // ((v0 o0 c0) o1 c1) o2 v1
   39956             :                typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
   39957             : 
   39958           0 :                const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
   39959           0 :                const Type& v0 = vococ->t0();
   39960           0 :                const Type  c0 = vococ->t1();
   39961           0 :                const Type  c1 = vococ->t2();
   39962           0 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   39963           0 :                const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
   39964           0 :                const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
   39965           0 :                const details::operator_type o2 = operation;
   39966             : 
   39967           0 :                binary_functor_t f0 = vococ->f0();
   39968           0 :                binary_functor_t f1 = vococ->f1();
   39969           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39970             : 
   39971           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39972             : 
   39973           0 :                expression_node_ptr result = error_node();
   39974             : 
   39975             :                const bool synthesis_result =
   39976             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39977           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
   39978             : 
   39979           0 :                if (synthesis_result)
   39980           0 :                   return result;
   39981           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39982           0 :                   return error_node();
   39983             : 
   39984             :                exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
   39985             : 
   39986           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
   39987             :             }
   39988             : 
   39989           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39990             :                                          const details::operator_type o0,
   39991             :                                          const details::operator_type o1,
   39992             :                                          const details::operator_type o2)
   39993             :             {
   39994           0 :                return details::build_string()
   39995           0 :                   << "((t" << expr_gen.to_str(o0)
   39996           0 :                   << "t)"  << expr_gen.to_str(o1)
   39997           0 :                   << "t)"  << expr_gen.to_str(o2)
   39998           0 :                   << "t";
   39999             :             }
   40000             :          };
   40001             : 
   40002             :          struct synthesize_vovovov_expression4
   40003             :          {
   40004             :             typedef typename vovovov_t::type4 node_type;
   40005             :             typedef typename vovovov_t::sf4_type sf4_type;
   40006             :             typedef typename node_type::T0 T0;
   40007             :             typedef typename node_type::T1 T1;
   40008             :             typedef typename node_type::T2 T2;
   40009             :             typedef typename node_type::T3 T3;
   40010             : 
   40011           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40012             :                                                       const details::operator_type& operation,
   40013             :                                                       expression_node_ptr (&branch)[2])
   40014             :             {
   40015             :                // (v0 o0 (v1 o1 v2)) o2 v3
   40016             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   40017             : 
   40018           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   40019           0 :                const Type& v0 = vovov->t0();
   40020           0 :                const Type& v1 = vovov->t1();
   40021           0 :                const Type& v2 = vovov->t2();
   40022           0 :                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   40023           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   40024           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   40025           0 :                const details::operator_type o2 = operation;
   40026             : 
   40027           0 :                binary_functor_t f0 = vovov->f0();
   40028           0 :                binary_functor_t f1 = vovov->f1();
   40029           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40030             : 
   40031           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40032             : 
   40033           0 :                expression_node_ptr result = error_node();
   40034             : 
   40035             :                const bool synthesis_result =
   40036             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40037           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   40038             : 
   40039           0 :                if (synthesis_result)
   40040           0 :                   return result;
   40041           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40042           0 :                   return error_node();
   40043             : 
   40044             :                exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
   40045             : 
   40046           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   40047             :             }
   40048             : 
   40049           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40050             :                                          const details::operator_type o0,
   40051             :                                          const details::operator_type o1,
   40052             :                                          const details::operator_type o2)
   40053             :             {
   40054           0 :                return details::build_string()
   40055           0 :                   << "(t" << expr_gen.to_str(o0)
   40056           0 :                   << "(t" << expr_gen.to_str(o1)
   40057           0 :                   << "t)" << expr_gen.to_str(o2)
   40058           0 :                   << "t";
   40059             :             }
   40060             :          };
   40061             : 
   40062             :          struct synthesize_vovovoc_expression4
   40063             :          {
   40064             :             typedef typename vovovoc_t::type4 node_type;
   40065             :             typedef typename vovovoc_t::sf4_type sf4_type;
   40066             :             typedef typename node_type::T0 T0;
   40067             :             typedef typename node_type::T1 T1;
   40068             :             typedef typename node_type::T2 T2;
   40069             :             typedef typename node_type::T3 T3;
   40070             : 
   40071           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40072             :                                                       const details::operator_type& operation,
   40073             :                                                       expression_node_ptr (&branch)[2])
   40074             :             {
   40075             :                // ((v0 o0 (v1 o1 v2)) o2 c)
   40076             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   40077             : 
   40078           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   40079           0 :                const Type& v0 = vovov->t0();
   40080           0 :                const Type& v1 = vovov->t1();
   40081           0 :                const Type& v2 = vovov->t2();
   40082           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   40083           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   40084           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   40085           0 :                const details::operator_type o2 = operation;
   40086             : 
   40087           0 :                binary_functor_t f0 = vovov->f0();
   40088           0 :                binary_functor_t f1 = vovov->f1();
   40089           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40090             : 
   40091           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40092           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   40093             : 
   40094           0 :                expression_node_ptr result = error_node();
   40095             : 
   40096             :                const bool synthesis_result =
   40097             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40098           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   40099             : 
   40100           0 :                if (synthesis_result)
   40101           0 :                   return result;
   40102           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40103           0 :                   return error_node();
   40104             : 
   40105             :                exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
   40106             : 
   40107           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   40108             :             }
   40109             : 
   40110           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40111             :                                          const details::operator_type o0,
   40112             :                                          const details::operator_type o1,
   40113             :                                          const details::operator_type o2)
   40114             :             {
   40115           0 :                return details::build_string()
   40116           0 :                   << "(t" << expr_gen.to_str(o0)
   40117           0 :                   << "(t" << expr_gen.to_str(o1)
   40118           0 :                   << "t)" << expr_gen.to_str(o2)
   40119           0 :                   << "t";
   40120             :             }
   40121             :          };
   40122             : 
   40123             :          struct synthesize_vovocov_expression4
   40124             :          {
   40125             :             typedef typename vovocov_t::type4 node_type;
   40126             :             typedef typename vovocov_t::sf4_type sf4_type;
   40127             :             typedef typename node_type::T0 T0;
   40128             :             typedef typename node_type::T1 T1;
   40129             :             typedef typename node_type::T2 T2;
   40130             :             typedef typename node_type::T3 T3;
   40131             : 
   40132           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40133             :                                                       const details::operator_type& operation,
   40134             :                                                       expression_node_ptr (&branch)[2])
   40135             :             {
   40136             :                // ((v0 o0 (v1 o1 c)) o2 v1)
   40137             :                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
   40138             : 
   40139           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
   40140           0 :                const Type& v0 = vovoc->t0();
   40141           0 :                const Type& v1 = vovoc->t1();
   40142           0 :                const Type   c = vovoc->t2();
   40143           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   40144           0 :                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
   40145           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
   40146           0 :                const details::operator_type o2 = operation;
   40147             : 
   40148           0 :                binary_functor_t f0 = vovoc->f0();
   40149           0 :                binary_functor_t f1 = vovoc->f1();
   40150           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40151             : 
   40152           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40153             : 
   40154           0 :                expression_node_ptr result = error_node();
   40155             : 
   40156             :                const bool synthesis_result =
   40157             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40158           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   40159             : 
   40160           0 :                if (synthesis_result)
   40161           0 :                   return result;
   40162           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40163           0 :                   return error_node();
   40164             : 
   40165             :                exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
   40166             : 
   40167           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   40168             :             }
   40169             : 
   40170           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40171             :                                          const details::operator_type o0,
   40172             :                                          const details::operator_type o1,
   40173             :                                          const details::operator_type o2)
   40174             :             {
   40175           0 :                return details::build_string()
   40176           0 :                   << "(t" << expr_gen.to_str(o0)
   40177           0 :                   << "(t" << expr_gen.to_str(o1)
   40178           0 :                   << "t)" << expr_gen.to_str(o2)
   40179           0 :                   << "t";
   40180             :             }
   40181             :          };
   40182             : 
   40183             :          struct synthesize_vocovov_expression4
   40184             :          {
   40185             :             typedef typename vocovov_t::type4 node_type;
   40186             :             typedef typename vocovov_t::sf4_type sf4_type;
   40187             :             typedef typename node_type::T0 T0;
   40188             :             typedef typename node_type::T1 T1;
   40189             :             typedef typename node_type::T2 T2;
   40190             :             typedef typename node_type::T3 T3;
   40191             : 
   40192           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40193             :                                                       const details::operator_type& operation,
   40194             :                                                       expression_node_ptr (&branch)[2])
   40195             :             {
   40196             :                // ((v0 o0 (c o1 v1)) o2 v2)
   40197             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   40198             : 
   40199           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   40200           0 :                const Type& v0 = vocov->t0();
   40201           0 :                const Type   c = vocov->t1();
   40202           0 :                const Type& v1 = vocov->t2();
   40203           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   40204           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   40205           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   40206           0 :                const details::operator_type o2 = operation;
   40207             : 
   40208           0 :                binary_functor_t f0 = vocov->f0();
   40209           0 :                binary_functor_t f1 = vocov->f1();
   40210           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40211             : 
   40212           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40213           0 :                expression_node_ptr result = error_node();
   40214             : 
   40215             :                const bool synthesis_result =
   40216             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40217           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   40218             : 
   40219           0 :                if (synthesis_result)
   40220           0 :                   return result;
   40221           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40222           0 :                   return error_node();
   40223             : 
   40224             :                exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
   40225             : 
   40226           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   40227             :             }
   40228             : 
   40229           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40230             :                                          const details::operator_type o0,
   40231             :                                          const details::operator_type o1,
   40232             :                                          const details::operator_type o2)
   40233             :             {
   40234           0 :                return details::build_string()
   40235           0 :                   << "(t" << expr_gen.to_str(o0)
   40236           0 :                   << "(t" << expr_gen.to_str(o1)
   40237           0 :                   << "t)" << expr_gen.to_str(o2)
   40238           0 :                   << "t";
   40239             :             }
   40240             :          };
   40241             : 
   40242             :          struct synthesize_covovov_expression4
   40243             :          {
   40244             :             typedef typename covovov_t::type4 node_type;
   40245             :             typedef typename covovov_t::sf4_type sf4_type;
   40246             :             typedef typename node_type::T0 T0;
   40247             :             typedef typename node_type::T1 T1;
   40248             :             typedef typename node_type::T2 T2;
   40249             :             typedef typename node_type::T3 T3;
   40250             : 
   40251           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40252             :                                                       const details::operator_type& operation,
   40253             :                                                       expression_node_ptr (&branch)[2])
   40254             :             {
   40255             :                // ((c o0 (v0 o1 v1)) o2 v2)
   40256             :                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
   40257             : 
   40258           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   40259           0 :                const Type   c = covov->t0();
   40260           0 :                const Type& v0 = covov->t1();
   40261           0 :                const Type& v1 = covov->t2();
   40262           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   40263           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   40264           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   40265           0 :                const details::operator_type o2 = operation;
   40266             : 
   40267           0 :                binary_functor_t f0 = covov->f0();
   40268           0 :                binary_functor_t f1 = covov->f1();
   40269           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40270             : 
   40271           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40272             : 
   40273           0 :                expression_node_ptr result = error_node();
   40274             : 
   40275             :                const bool synthesis_result =
   40276             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40277           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   40278             : 
   40279           0 :                if (synthesis_result)
   40280           0 :                   return result;
   40281           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40282           0 :                   return error_node();
   40283             : 
   40284             :                exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
   40285             : 
   40286           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   40287             :             }
   40288             : 
   40289           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40290             :                                          const details::operator_type o0,
   40291             :                                          const details::operator_type o1,
   40292             :                                          const details::operator_type o2)
   40293             :             {
   40294           0 :                return details::build_string()
   40295           0 :                   << "(t" << expr_gen.to_str(o0)
   40296           0 :                   << "(t" << expr_gen.to_str(o1)
   40297           0 :                   << "t)" << expr_gen.to_str(o2)
   40298           0 :                   << "t";
   40299             :             }
   40300             :          };
   40301             : 
   40302             :          struct synthesize_covocov_expression4
   40303             :          {
   40304             :             typedef typename covocov_t::type4 node_type;
   40305             :             typedef typename covocov_t::sf4_type sf4_type;
   40306             :             typedef typename node_type::T0 T0;
   40307             :             typedef typename node_type::T1 T1;
   40308             :             typedef typename node_type::T2 T2;
   40309             :             typedef typename node_type::T3 T3;
   40310             : 
   40311           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40312             :                                                       const details::operator_type& operation,
   40313             :                                                       expression_node_ptr (&branch)[2])
   40314             :             {
   40315             :                // ((c0 o0 (v0 o1 c1)) o2 v1)
   40316             :                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
   40317             : 
   40318           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
   40319           0 :                const Type  c0 = covoc->t0();
   40320           0 :                const Type& v0 = covoc->t1();
   40321           0 :                const Type  c1 = covoc->t2();
   40322           0 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   40323           0 :                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
   40324           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
   40325           0 :                const details::operator_type o2 = operation;
   40326             : 
   40327           0 :                binary_functor_t f0 = covoc->f0();
   40328           0 :                binary_functor_t f1 = covoc->f1();
   40329           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40330             : 
   40331           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40332             : 
   40333           0 :                expression_node_ptr result = error_node();
   40334             : 
   40335             :                const bool synthesis_result =
   40336             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40337           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   40338             : 
   40339           0 :                if (synthesis_result)
   40340           0 :                   return result;
   40341           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40342           0 :                   return error_node();
   40343             : 
   40344             :                exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
   40345             : 
   40346           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   40347             :             }
   40348             : 
   40349           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40350             :                                          const details::operator_type o0,
   40351             :                                          const details::operator_type o1,
   40352             :                                          const details::operator_type o2)
   40353             :             {
   40354           0 :                return details::build_string()
   40355           0 :                   << "(t" << expr_gen.to_str(o0)
   40356           0 :                   << "(t" << expr_gen.to_str(o1)
   40357           0 :                   << "t)" << expr_gen.to_str(o2)
   40358           0 :                   << "t";
   40359             :             }
   40360             :          };
   40361             : 
   40362             :          struct synthesize_vocovoc_expression4
   40363             :          {
   40364             :             typedef typename vocovoc_t::type4 node_type;
   40365             :             typedef typename vocovoc_t::sf4_type sf4_type;
   40366             :             typedef typename node_type::T0 T0;
   40367             :             typedef typename node_type::T1 T1;
   40368             :             typedef typename node_type::T2 T2;
   40369             :             typedef typename node_type::T3 T3;
   40370             : 
   40371           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40372             :                                                       const details::operator_type& operation,
   40373             :                                                       expression_node_ptr (&branch)[2])
   40374             :             {
   40375             :                // ((v0 o0 (c0 o1 v1)) o2 c1)
   40376             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   40377             : 
   40378           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   40379           0 :                const Type& v0 = vocov->t0();
   40380           0 :                const Type  c0 = vocov->t1();
   40381           0 :                const Type& v1 = vocov->t2();
   40382           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   40383           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   40384           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   40385           0 :                const details::operator_type o2 = operation;
   40386             : 
   40387           0 :                binary_functor_t f0 = vocov->f0();
   40388           0 :                binary_functor_t f1 = vocov->f1();
   40389           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40390             : 
   40391           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40392           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   40393             : 
   40394           0 :                expression_node_ptr result = error_node();
   40395             : 
   40396             :                const bool synthesis_result =
   40397             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40398           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   40399             : 
   40400           0 :                if (synthesis_result)
   40401           0 :                   return result;
   40402           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40403           0 :                   return error_node();
   40404             : 
   40405             :                exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
   40406             : 
   40407           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   40408             :             }
   40409             : 
   40410           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40411             :                                          const details::operator_type o0,
   40412             :                                          const details::operator_type o1,
   40413             :                                          const details::operator_type o2)
   40414             :             {
   40415           0 :                return details::build_string()
   40416           0 :                   << "(t" << expr_gen.to_str(o0)
   40417           0 :                   << "(t" << expr_gen.to_str(o1)
   40418           0 :                   << "t)" << expr_gen.to_str(o2)
   40419           0 :                   << "t";
   40420             :             }
   40421             :          };
   40422             : 
   40423             :          struct synthesize_covovoc_expression4
   40424             :          {
   40425             :             typedef typename covovoc_t::type4 node_type;
   40426             :             typedef typename covovoc_t::sf4_type sf4_type;
   40427             :             typedef typename node_type::T0 T0;
   40428             :             typedef typename node_type::T1 T1;
   40429             :             typedef typename node_type::T2 T2;
   40430             :             typedef typename node_type::T3 T3;
   40431             : 
   40432           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   40433             :                                                       const details::operator_type& operation,
   40434             :                                                       expression_node_ptr (&branch)[2])
   40435             :             {
   40436             :                // ((c0 o0 (v0 o1 v1)) o2 c1)
   40437             :                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
   40438             : 
   40439           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   40440           0 :                const Type  c0 = covov->t0();
   40441           0 :                const Type& v0 = covov->t1();
   40442           0 :                const Type& v1 = covov->t2();
   40443           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   40444           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   40445           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   40446           0 :                const details::operator_type o2 = operation;
   40447             : 
   40448           0 :                binary_functor_t f0 = covov->f0();
   40449           0 :                binary_functor_t f1 = covov->f1();
   40450           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   40451             : 
   40452           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   40453           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   40454             : 
   40455           0 :                expression_node_ptr result = error_node();
   40456             : 
   40457             :                const bool synthesis_result =
   40458             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   40459           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   40460             : 
   40461           0 :                if (synthesis_result)
   40462           0 :                   return result;
   40463           0 :                else if (!expr_gen.valid_operator(o2,f2))
   40464           0 :                   return error_node();
   40465             : 
   40466             :                exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
   40467             : 
   40468           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   40469             :             }
   40470             : 
   40471           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   40472             :                                          const details::operator_type o0,
   40473             :                                          const details::operator_type o1,
   40474             :                                          const details::operator_type o2)
   40475             :             {
   40476           0 :                return details::build_string()
   40477           0 :                   << "(t" << expr_gen.to_str(o0)
   40478           0 :                   << "(t" << expr_gen.to_str(o1)
   40479           0 :                   << "t)" << expr_gen.to_str(o2)
   40480           0 :                   << "t";
   40481             :             }
   40482             :          };
   40483             : 
   40484             :          struct synthesize_vococov_expression4
   40485             :          {
   40486             :             typedef typename vococov_t::type4 node_type;
   40487             :             static inline expression_node_ptr process(expression_generator<Type>&,
   40488             :                                                       const details::operator_type&,
   40489             :                                                       expression_node_ptr (&)[2])
   40490             :             {
   40491             :                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
   40492             :                exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
   40493             :                return error_node();
   40494             :             }
   40495             : 
   40496             :             static inline std::string id(expression_generator<Type>&,
   40497             :                                          const details::operator_type,
   40498             :                                          const details::operator_type,
   40499             :                                          const details::operator_type)
   40500             :             {
   40501             :                return "INVALID";
   40502             :             }
   40503             :          };
   40504             :          #endif
   40505             : 
   40506         900 :          inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   40507             :          {
   40508             :             // Definition: uv o uv
   40509         900 :             details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
   40510         900 :             details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
   40511         900 :             const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
   40512         900 :             const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
   40513         900 :             unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
   40514         900 :             unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
   40515         900 :             binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
   40516             : 
   40517         900 :             if (!valid_operator(o0,u0))
   40518           0 :                return error_node();
   40519         900 :             else if (!valid_operator(o1,u1))
   40520           0 :                return error_node();
   40521         900 :             else if (!valid_operator(operation,f))
   40522           0 :                return error_node();
   40523             : 
   40524         900 :             expression_node_ptr result = error_node();
   40525             : 
   40526         900 :             if (
   40527         900 :                  (details::e_neg == o0) &&
   40528         280 :                  (details::e_neg == o1)
   40529             :                )
   40530             :             {
   40531         280 :                switch (operation)
   40532             :                {
   40533             :                   // (-v0 + -v1) --> -(v0 + v1)
   40534           0 :                   case details::e_add : result = (*this)(details::e_neg,
   40535           0 :                                                     node_allocator_->
   40536             :                                                        allocate_rr<typename details::
   40537             :                                                           vov_node<Type,details::add_op<Type> > >(v0, v1));
   40538             :                                         exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
   40539           0 :                                         break;
   40540             : 
   40541             :                   // (-v0 - -v1) --> (v1 - v0)
   40542           0 :                   case details::e_sub : result = node_allocator_->
   40543             :                                                     allocate_rr<typename details::
   40544           0 :                                                        vov_node<Type,details::sub_op<Type> > >(v1, v0);
   40545             :                                         exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
   40546           0 :                                         break;
   40547             : 
   40548             :                   // (-v0 * -v1) --> (v0 * v1)
   40549         160 :                   case details::e_mul : result = node_allocator_->
   40550             :                                                     allocate_rr<typename details::
   40551         160 :                                                        vov_node<Type,details::mul_op<Type> > >(v0, v1);
   40552             :                                         exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
   40553         160 :                                         break;
   40554             : 
   40555             :                   // (-v0 / -v1) --> (v0 / v1)
   40556         120 :                   case details::e_div : result = node_allocator_->
   40557             :                                                     allocate_rr<typename details::
   40558         120 :                                                        vov_node<Type,details::div_op<Type> > >(v0, v1);
   40559             :                                         exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
   40560         120 :                                         break;
   40561             : 
   40562           0 :                   default             : break;
   40563             :                }
   40564             :             }
   40565             : 
   40566         900 :             if (0 == result)
   40567             :             {
   40568         620 :                result = node_allocator_->
   40569         620 :                             allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
   40570             :             }
   40571             : 
   40572         900 :             details::free_all_nodes(*node_allocator_,branch);
   40573         900 :             return result;
   40574             :          }
   40575             : 
   40576             :          #undef basic_opr_switch_statements
   40577             :          #undef extended_opr_switch_statements
   40578             :          #undef unary_opr_switch_statements
   40579             : 
   40580             :          #ifndef exprtk_disable_string_capabilities
   40581             : 
   40582             :          #define string_opr_switch_statements            \
   40583             :          case_stmt(details::e_lt    , details::lt_op   ) \
   40584             :          case_stmt(details::e_lte   , details::lte_op  ) \
   40585             :          case_stmt(details::e_gt    , details::gt_op   ) \
   40586             :          case_stmt(details::e_gte   , details::gte_op  ) \
   40587             :          case_stmt(details::e_eq    , details::eq_op   ) \
   40588             :          case_stmt(details::e_ne    , details::ne_op   ) \
   40589             :          case_stmt(details::e_in    , details::in_op   ) \
   40590             :          case_stmt(details::e_like  , details::like_op ) \
   40591             :          case_stmt(details::e_ilike , details::ilike_op) \
   40592             : 
   40593             :          template <typename T0, typename T1>
   40594        3690 :          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
   40595             :                                                                         T0 s0, T1 s1,
   40596             :                                                                         range_t rp0)
   40597             :          {
   40598        3690 :             switch (opr)
   40599             :             {
   40600             :                #define case_stmt(op0, op1)                                                                      \
   40601             :                case op0 : return node_allocator_->                                                              \
   40602             :                              allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
   40603             :                                 (s0, s1, rp0);                                                                  \
   40604             : 
   40605        3690 :                string_opr_switch_statements
   40606             :                #undef case_stmt
   40607           0 :                default : return error_node();
   40608             :             }
   40609             :          }
   40610             : 
   40611             :          template <typename T0, typename T1>
   40612        3560 :          inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
   40613             :                                                                         T0 s0, T1 s1,
   40614             :                                                                         range_t rp1)
   40615             :          {
   40616        3560 :             switch (opr)
   40617             :             {
   40618             :                #define case_stmt(op0, op1)                                                                      \
   40619             :                case op0 : return node_allocator_->                                                              \
   40620             :                              allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
   40621             :                                 (s0, s1, rp1);                                                                  \
   40622             : 
   40623        3560 :                string_opr_switch_statements
   40624             :                #undef case_stmt
   40625           0 :                default : return error_node();
   40626             :             }
   40627             :          }
   40628             : 
   40629             :          template <typename T0, typename T1>
   40630        3355 :          inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
   40631             :                                                                          T0 s0, T1 s1,
   40632             :                                                                          range_t rp0, range_t rp1)
   40633             :          {
   40634        3355 :             switch (opr)
   40635             :             {
   40636             :                #define case_stmt(op0, op1)                                                                        \
   40637             :                case op0 : return node_allocator_->                                                                \
   40638             :                              allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
   40639             :                                 (s0, s1, rp0, rp1);                                                               \
   40640             : 
   40641        3355 :                string_opr_switch_statements
   40642             :                #undef case_stmt
   40643           0 :                default : return error_node();
   40644             :             }
   40645             :          }
   40646             : 
   40647             :          template <typename T0, typename T1>
   40648       20042 :          inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
   40649             :          {
   40650       20042 :             switch (opr)
   40651             :             {
   40652             :                #define case_stmt(op0, op1)                                                                 \
   40653             :                case op0 : return node_allocator_->                                                         \
   40654             :                              allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
   40655             : 
   40656       20042 :                string_opr_switch_statements
   40657             :                #undef case_stmt
   40658           0 :                default : return error_node();
   40659             :             }
   40660             :          }
   40661             : 
   40662        6111 :          inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40663             :          {
   40664        6111 :             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
   40665        6111 :             std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
   40666             : 
   40667        6111 :             return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
   40668             :          }
   40669             : 
   40670        1100 :          inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40671             :          {
   40672        1100 :             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
   40673        1100 :             std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
   40674        1100 :             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
   40675             : 
   40676        1100 :             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
   40677             : 
   40678        1100 :             details::free_node(*node_allocator_,branch[0]);
   40679             : 
   40680        2200 :             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
   40681             :          }
   40682             : 
   40683        1100 :          inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40684             :          {
   40685        1100 :             std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
   40686        1100 :             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
   40687        1100 :             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
   40688             : 
   40689        1100 :             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
   40690             : 
   40691        1100 :             details::free_node(*node_allocator_,branch[1]);
   40692             : 
   40693        2200 :             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
   40694             :          }
   40695             : 
   40696         150 :          inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40697             :          {
   40698         150 :             std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
   40699         150 :             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   40700         150 :             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   40701             : 
   40702         150 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   40703             : 
   40704         150 :             details::free_node(*node_allocator_,branch[1]);
   40705             : 
   40706         300 :             return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
   40707         150 :          }
   40708             : 
   40709        1255 :          inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40710             :          {
   40711        1255 :             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
   40712        1255 :             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
   40713        1255 :             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
   40714        1255 :             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
   40715             : 
   40716        1255 :             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
   40717        1255 :             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
   40718             : 
   40719        1255 :             details::free_node(*node_allocator_,branch[0]);
   40720        1255 :             details::free_node(*node_allocator_,branch[1]);
   40721             : 
   40722        2510 :             return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
   40723             :          }
   40724             : 
   40725       10196 :          inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40726             :          {
   40727       10196 :             std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
   40728       10196 :             std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   40729             : 
   40730       10196 :             details::free_node(*node_allocator_,branch[1]);
   40731             : 
   40732       20392 :             return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
   40733       10196 :          }
   40734             : 
   40735        1930 :          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40736             :          {
   40737        1930 :             std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   40738        1930 :             std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   40739             : 
   40740        1930 :             details::free_node(*node_allocator_,branch[0]);
   40741             : 
   40742        3860 :             return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
   40743        1930 :          }
   40744             : 
   40745        1610 :          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40746             :          {
   40747        1610 :             std::string  s0  = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
   40748        1610 :             std::string& s1  = static_cast<details::string_range_node<Type>*  >(branch[1])->ref  ();
   40749        1610 :             range_t      rp1 = static_cast<details::string_range_node<Type>*  >(branch[1])->range();
   40750             : 
   40751        1610 :             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
   40752             : 
   40753        1610 :             details::free_node(*node_allocator_,branch[0]);
   40754        1610 :             details::free_node(*node_allocator_,branch[1]);
   40755             : 
   40756        3220 :             return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
   40757        1610 :          }
   40758             : 
   40759        1640 :          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40760             :          {
   40761        1640 :             std::string&  s0 = static_cast<details::string_range_node<Type>*  >(branch[0])->ref  ();
   40762        1640 :             std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
   40763        1640 :             range_t      rp0 = static_cast<details::string_range_node<Type>*  >(branch[0])->range();
   40764             : 
   40765        1640 :             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
   40766             : 
   40767        1640 :             details::free_node(*node_allocator_,branch[0]);
   40768        1640 :             details::free_node(*node_allocator_,branch[1]);
   40769             : 
   40770        3280 :             return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
   40771        1640 :          }
   40772             : 
   40773         500 :          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40774             :          {
   40775         500 :             std::string&  s0 = static_cast<details::string_range_node<Type>*      >(branch[0])->ref  ();
   40776         500 :             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   40777         500 :             range_t      rp0 = static_cast<details::string_range_node<Type>*      >(branch[0])->range();
   40778         500 :             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   40779             : 
   40780         500 :             static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
   40781         500 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   40782             : 
   40783         500 :             details::free_node(*node_allocator_,branch[0]);
   40784         500 :             details::free_node(*node_allocator_,branch[1]);
   40785             : 
   40786        1000 :             return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
   40787         500 :          }
   40788             : 
   40789        6462 :          inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40790             :          {
   40791        6462 :             const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   40792        6462 :             const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   40793             : 
   40794        6462 :             expression_node_ptr result = error_node();
   40795             : 
   40796        6462 :             if (details::e_add == opr)
   40797        3082 :                result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
   40798        3380 :             else if (details::e_in == opr)
   40799         160 :                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op   <Type>::process(s0,s1));
   40800        3220 :             else if (details::e_like == opr)
   40801         620 :                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
   40802        2600 :             else if (details::e_ilike == opr)
   40803         795 :                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
   40804             :             else
   40805             :             {
   40806        1805 :                expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
   40807             : 
   40808        1805 :                const Type v = temp->value();
   40809             : 
   40810        1805 :                details::free_node(*node_allocator_,temp);
   40811             : 
   40812        1805 :                result = node_allocator_->allocate<literal_node_t>(v);
   40813             :             }
   40814             : 
   40815        6462 :             details::free_all_nodes(*node_allocator_,branch);
   40816             : 
   40817        6462 :             return result;
   40818        6462 :          }
   40819             : 
   40820         700 :          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40821             :          {
   40822         700 :             const std::string s0 = static_cast<details::string_literal_node<Type>*    >(branch[0])->str  ();
   40823         700 :                   std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   40824         700 :             range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   40825             : 
   40826         700 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   40827             : 
   40828         700 :             details::free_node(*node_allocator_,branch[0]);
   40829         700 :             details::free_node(*node_allocator_,branch[1]);
   40830             : 
   40831        1400 :             return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
   40832         700 :          }
   40833             : 
   40834         250 :          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40835             :          {
   40836         250 :             std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   40837         250 :             std::string&  s1 = static_cast<details::stringvar_node<Type>*         >(branch[1])->ref  ();
   40838         250 :             range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   40839             : 
   40840         250 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   40841             : 
   40842         250 :             details::free_node(*node_allocator_,branch[0]);
   40843             : 
   40844         500 :             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
   40845         250 :          }
   40846             : 
   40847         500 :          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40848             :          {
   40849         500 :             const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   40850         500 :                   std::string& s1 = static_cast<details::string_range_node<Type>*      >(branch[1])->ref  ();
   40851         500 :             const range_t     rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   40852         500 :             const range_t     rp1 = static_cast<details::string_range_node<Type>*      >(branch[1])->range();
   40853             : 
   40854         500 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   40855         500 :             static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
   40856             : 
   40857         500 :             details::free_node(*node_allocator_,branch[0]);
   40858         500 :             details::free_node(*node_allocator_,branch[1]);
   40859             : 
   40860        1000 :             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
   40861         500 :          }
   40862             : 
   40863         700 :          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40864             :          {
   40865         700 :             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   40866         700 :             const std::string s1 = static_cast<details::string_literal_node<Type>*    >(branch[1])->str  ();
   40867         700 :             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   40868             : 
   40869         700 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   40870             : 
   40871         700 :             details::free_all_nodes(*node_allocator_,branch);
   40872             : 
   40873        1400 :             return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
   40874         700 :          }
   40875             : 
   40876        1100 :          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40877             :          {
   40878        1100 :             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   40879        1100 :             const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   40880        1100 :             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   40881        1100 :             const range_t    rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   40882             : 
   40883        1100 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   40884        1100 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   40885             : 
   40886        1100 :             details::free_all_nodes(*node_allocator_,branch);
   40887             : 
   40888        2200 :             return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
   40889        1100 :          }
   40890             : 
   40891        4846 :          inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40892             :          {
   40893        4846 :             switch (opr)
   40894             :             {
   40895             :                #define case_stmt(op0, op1)                                                      \
   40896             :                case op0 : return node_allocator_->                                              \
   40897             :                              allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
   40898             :                                 (opr, branch[0], branch[1]);                                    \
   40899             : 
   40900        4846 :                string_opr_switch_statements
   40901             :                #undef case_stmt
   40902           0 :                default : return error_node();
   40903             :             }
   40904             :          }
   40905             : 
   40906             :          #undef string_opr_switch_statements
   40907             :          #endif
   40908             : 
   40909             :          #ifndef exprtk_disable_string_capabilities
   40910       45322 :          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   40911             :          {
   40912       45322 :             if ((0 == branch[0]) || (0 == branch[1]))
   40913             :             {
   40914           0 :                details::free_all_nodes(*node_allocator_,branch);
   40915             : 
   40916           0 :                return error_node();
   40917             :             }
   40918             : 
   40919       45322 :             const bool b0_is_s   = details::is_string_node            (branch[0]);
   40920       45322 :             const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
   40921       45322 :             const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
   40922       45322 :             const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
   40923             : 
   40924       45322 :             const bool b1_is_s   = details::is_string_node            (branch[1]);
   40925       45322 :             const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
   40926       45322 :             const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
   40927       45322 :             const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
   40928             : 
   40929       45322 :             const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
   40930       45022 :                                    details::is_genricstring_range_node(branch[0]) ||
   40931       43722 :                                    details::is_string_concat_node     (branch[0]) ||
   40932       41922 :                                    details::is_string_function_node   (branch[0]) ||
   40933       41904 :                                    details::is_string_condition_node  (branch[0]) ||
   40934      131548 :                                    details::is_string_ccondition_node (branch[0]) ||
   40935       41204 :                                    details::is_string_vararg_node     (branch[0]) ;
   40936             : 
   40937       45322 :             const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
   40938       45322 :                                    details::is_genricstring_range_node(branch[1]) ||
   40939       45322 :                                    details::is_string_concat_node     (branch[1]) ||
   40940       44466 :                                    details::is_string_function_node   (branch[1]) ||
   40941       44454 :                                    details::is_string_condition_node  (branch[1]) ||
   40942      134692 :                                    details::is_string_ccondition_node (branch[1]) ||
   40943       44048 :                                    details::is_string_vararg_node     (branch[1]) ;
   40944             : 
   40945       45322 :             if (details::e_add == opr)
   40946             :             {
   40947        8254 :                if (!b0_is_cs || !b1_is_cs)
   40948             :                {
   40949        5172 :                   return synthesize_expression<string_concat_node_t,2>(opr,branch);
   40950             :                }
   40951             :             }
   40952             : 
   40953       40150 :             if (b0_is_gen || b1_is_gen)
   40954             :             {
   40955        4846 :                return synthesize_strogen_expression(opr,branch);
   40956             :             }
   40957       35304 :             else if (b0_is_s)
   40958             :             {
   40959       17557 :                if      (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
   40960       11446 :                else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
   40961        1250 :                else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
   40962         150 :                else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
   40963             :             }
   40964       17747 :             else if (b0_is_cs)
   40965             :             {
   40966       10702 :                if      (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
   40967        8772 :                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
   40968        2310 :                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
   40969         700 :                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
   40970             :             }
   40971        7045 :             else if (b0_is_sr)
   40972             :             {
   40973        4495 :                if      (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
   40974        3395 :                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
   40975        2140 :                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
   40976         500 :                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
   40977             :             }
   40978        2550 :             else if (b0_is_csr)
   40979             :             {
   40980        2550 :                if      (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
   40981        2300 :                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
   40982        1800 :                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
   40983        1100 :                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
   40984             :             }
   40985             : 
   40986           0 :             return error_node();
   40987             :          }
   40988             :          #else
   40989             :          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
   40990             :          {
   40991             :             details::free_all_nodes(*node_allocator_,branch);
   40992             :             return error_node();
   40993             :          }
   40994             :          #endif
   40995             : 
   40996             :          #ifndef exprtk_disable_string_capabilities
   40997         355 :          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
   40998             :          {
   40999         355 :             if (details::e_inrange != opr)
   41000           0 :                return error_node();
   41001         355 :             else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
   41002             :             {
   41003           0 :                details::free_all_nodes(*node_allocator_,branch);
   41004             : 
   41005           0 :                return error_node();
   41006             :             }
   41007         355 :             else if (
   41008         355 :                       details::is_const_string_node(branch[0]) &&
   41009         410 :                       details::is_const_string_node(branch[1]) &&
   41010          55 :                       details::is_const_string_node(branch[2])
   41011             :                     )
   41012             :             {
   41013          55 :                const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   41014          55 :                const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   41015          55 :                const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
   41016             : 
   41017          55 :                const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
   41018             : 
   41019          55 :                details::free_all_nodes(*node_allocator_,branch);
   41020             : 
   41021          55 :                return node_allocator_->allocate_c<details::literal_node<Type> >(v);
   41022          55 :             }
   41023         300 :             else if (
   41024         300 :                       details::is_string_node(branch[0]) &&
   41025         400 :                       details::is_string_node(branch[1]) &&
   41026         100 :                       details::is_string_node(branch[2])
   41027             :                     )
   41028             :             {
   41029          50 :                std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
   41030          50 :                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
   41031          50 :                std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
   41032             : 
   41033             :                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
   41034             : 
   41035          50 :                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
   41036             :             }
   41037         250 :             else if (
   41038         250 :                       details::is_const_string_node(branch[0]) &&
   41039         400 :                             details::is_string_node(branch[1]) &&
   41040         150 :                       details::is_const_string_node(branch[2])
   41041             :                     )
   41042             :             {
   41043          50 :                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   41044          50 :                std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   41045          50 :                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
   41046             : 
   41047             :                typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
   41048             : 
   41049          50 :                details::free_node(*node_allocator_,branch[0]);
   41050          50 :                details::free_node(*node_allocator_,branch[2]);
   41051             : 
   41052          50 :                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
   41053          50 :             }
   41054         200 :             else if (
   41055         200 :                             details::is_string_node(branch[0]) &&
   41056         250 :                       details::is_const_string_node(branch[1]) &&
   41057          50 :                             details::is_string_node(branch[2])
   41058             :                     )
   41059             :             {
   41060          50 :                std::string&  s0 = static_cast<details::stringvar_node<Type>*     >(branch[0])->ref();
   41061          50 :                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   41062          50 :                std::string&  s2 = static_cast<details::stringvar_node<Type>*     >(branch[2])->ref();
   41063             : 
   41064             :                typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
   41065             : 
   41066          50 :                details::free_node(*node_allocator_,branch[1]);
   41067             : 
   41068          50 :                return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
   41069          50 :             }
   41070         150 :             else if (
   41071         150 :                       details::is_string_node(branch[0]) &&
   41072         200 :                       details::is_string_node(branch[1]) &&
   41073          50 :                       details::is_const_string_node(branch[2])
   41074             :                     )
   41075             :             {
   41076          50 :                std::string& s0 = static_cast<details::stringvar_node<Type>*     >(branch[0])->ref();
   41077          50 :                std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   41078          50 :                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
   41079             : 
   41080             :                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
   41081             : 
   41082          50 :                details::free_node(*node_allocator_,branch[2]);
   41083             : 
   41084          50 :                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
   41085          50 :             }
   41086         100 :             else if (
   41087         100 :                       details::is_const_string_node(branch[0]) &&
   41088         200 :                       details::      is_string_node(branch[1]) &&
   41089         100 :                       details::      is_string_node(branch[2])
   41090             :                     )
   41091             :             {
   41092         100 :                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   41093         100 :                std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   41094         100 :                std::string& s2 = static_cast<details::stringvar_node<Type>*     >(branch[2])->ref();
   41095             : 
   41096             :                typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
   41097             : 
   41098         100 :                details::free_node(*node_allocator_,branch[0]);
   41099             : 
   41100         100 :                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
   41101         100 :             }
   41102             :             else
   41103           0 :                return error_node();
   41104             :          }
   41105             :          #else
   41106             :          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
   41107             :          {
   41108             :             details::free_all_nodes(*node_allocator_,branch);
   41109             :             return error_node();
   41110             :          }
   41111             :          #endif
   41112             : 
   41113         255 :          inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   41114             :          {
   41115             :             /*
   41116             :              Note: The following are the type promotion rules
   41117             :              that relate to operations that include 'null':
   41118             :              0. null ==/!=     null --> true false
   41119             :              1. null operation null --> null
   41120             :              2. x    ==/!=     null --> true/false
   41121             :              3. null ==/!=     x    --> true/false
   41122             :              4. x   operation  null --> x
   41123             :              5. null operation x    --> x
   41124             :             */
   41125             : 
   41126             :             typedef typename details::null_eq_node<T> nulleq_node_t;
   41127             : 
   41128         255 :             const bool b0_null = details::is_null_node(branch[0]);
   41129         255 :             const bool b1_null = details::is_null_node(branch[1]);
   41130             : 
   41131         255 :             if (b0_null && b1_null)
   41132             :             {
   41133          60 :                expression_node_ptr result = error_node();
   41134             : 
   41135          60 :                if (details::e_eq == operation)
   41136          60 :                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
   41137           0 :                else if (details::e_ne == operation)
   41138           0 :                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
   41139             : 
   41140          60 :                if (result)
   41141             :                {
   41142          60 :                   details::free_node(*node_allocator_,branch[0]);
   41143          60 :                   details::free_node(*node_allocator_,branch[1]);
   41144             : 
   41145          60 :                   return result;
   41146             :                }
   41147             : 
   41148           0 :                details::free_node(*node_allocator_,branch[1]);
   41149             : 
   41150           0 :                return branch[0];
   41151             :             }
   41152         195 :             else if (details::e_eq == operation)
   41153             :             {
   41154         195 :                expression_node_ptr result = node_allocator_->
   41155         195 :                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
   41156             : 
   41157         195 :                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
   41158             : 
   41159         195 :                return result;
   41160             :             }
   41161           0 :             else if (details::e_ne == operation)
   41162             :             {
   41163           0 :                expression_node_ptr result = node_allocator_->
   41164           0 :                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
   41165             : 
   41166           0 :                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
   41167             : 
   41168           0 :                return result;
   41169             :             }
   41170           0 :             else if (b0_null)
   41171             :             {
   41172           0 :                details::free_node(*node_allocator_,branch[0]);
   41173           0 :                branch[0] = branch[1];
   41174           0 :                branch[1] = error_node();
   41175             :             }
   41176           0 :             else if (b1_null)
   41177             :             {
   41178           0 :                details::free_node(*node_allocator_,branch[1]);
   41179           0 :                branch[1] = error_node();
   41180             :             }
   41181             : 
   41182           0 :             if (
   41183           0 :                  (details::e_add == operation) || (details::e_sub == operation) ||
   41184           0 :                  (details::e_mul == operation) || (details::e_div == operation) ||
   41185           0 :                  (details::e_mod == operation) || (details::e_pow == operation)
   41186             :                )
   41187             :             {
   41188           0 :                return branch[0];
   41189             :             }
   41190             : 
   41191           0 :             details::free_node(*node_allocator_, branch[0]);
   41192             : 
   41193           0 :             if (
   41194           0 :                  (details::e_lt    == operation) || (details::e_lte  == operation) ||
   41195           0 :                  (details::e_gt    == operation) || (details::e_gte  == operation) ||
   41196           0 :                  (details::e_and   == operation) || (details::e_nand == operation) ||
   41197           0 :                  (details::e_or    == operation) || (details::e_nor  == operation) ||
   41198           0 :                  (details::e_xor   == operation) || (details::e_xnor == operation) ||
   41199           0 :                  (details::e_in    == operation) || (details::e_like == operation) ||
   41200           0 :                  (details::e_ilike == operation)
   41201             :                )
   41202             :             {
   41203           0 :                return node_allocator_->allocate_c<literal_node_t>(T(0));
   41204             :             }
   41205             : 
   41206           0 :             return node_allocator_->allocate<details::null_node<Type> >();
   41207             :          }
   41208             : 
   41209             :          template <typename NodeType, std::size_t N>
   41210      622242 :          inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
   41211             :          {
   41212      622242 :             if (
   41213      622242 :                  (details::e_in    == operation) ||
   41214      622230 :                  (details::e_like  == operation) ||
   41215      622230 :                  (details::e_ilike == operation)
   41216             :                )
   41217             :             {
   41218          12 :                free_all_nodes(*node_allocator_,branch);
   41219             : 
   41220          12 :                return error_node();
   41221             :             }
   41222      622230 :             else if (!details::all_nodes_valid<N>(branch))
   41223             :             {
   41224           0 :                free_all_nodes(*node_allocator_,branch);
   41225             : 
   41226           0 :                return error_node();
   41227             :             }
   41228      622230 :             else if ((details::e_default != operation))
   41229             :             {
   41230             :                // Attempt simple constant folding optimisation.
   41231      622230 :                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
   41232             : 
   41233      622230 :                if (is_constant_foldable<N>(branch))
   41234             :                {
   41235      299252 :                   const Type v = expression_point->value();
   41236      299252 :                   details::free_node(*node_allocator_,expression_point);
   41237             : 
   41238      299252 :                   return node_allocator_->allocate<literal_node_t>(v);
   41239             :                }
   41240             : 
   41241      322978 :                if (expression_point && expression_point->valid())
   41242             :                {
   41243      322978 :                   return expression_point;
   41244             :                }
   41245             : 
   41246           0 :                parser_->set_error(parser_error::make_error(
   41247             :                   parser_error::e_parser,
   41248           0 :                   token_t(),
   41249             :                   "ERR273 - Failed to synthesize node: NodeType",
   41250             :                   exprtk_error_location));
   41251             : 
   41252           0 :                details::free_node(*node_allocator_, expression_point);
   41253             :             }
   41254             : 
   41255           0 :             return error_node();
   41256             :          }
   41257             : 
   41258             :          template <typename NodeType, std::size_t N>
   41259       60380 :          inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
   41260             :          {
   41261       60380 :             if (!details::all_nodes_valid<N>(branch))
   41262             :             {
   41263           0 :                free_all_nodes(*node_allocator_,branch);
   41264             : 
   41265           0 :                return error_node();
   41266             :             }
   41267             : 
   41268             :             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
   41269             : 
   41270             :             // Attempt simple constant folding optimisation.
   41271             : 
   41272       60380 :             expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
   41273       60380 :             function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
   41274             : 
   41275       60380 :             if (0 == func_node_ptr)
   41276             :             {
   41277           0 :                free_all_nodes(*node_allocator_,branch);
   41278             : 
   41279           0 :                return error_node();
   41280             :             }
   41281             :             else
   41282       60380 :                func_node_ptr->init_branches(branch);
   41283             : 
   41284       60380 :             if (is_constant_foldable<N>(branch) && !f->has_side_effects())
   41285             :             {
   41286         120 :                Type v = expression_point->value();
   41287         120 :                details::free_node(*node_allocator_,expression_point);
   41288             : 
   41289         120 :                return node_allocator_->allocate<literal_node_t>(v);
   41290             :             }
   41291             : 
   41292      120520 :             parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
   41293             : 
   41294       60260 :             return expression_point;
   41295             :          }
   41296             : 
   41297             :          bool                     strength_reduction_enabled_;
   41298             :          details::node_allocator* node_allocator_;
   41299             :          synthesize_map_t         synthesize_map_;
   41300             :          unary_op_map_t*          unary_op_map_;
   41301             :          binary_op_map_t*         binary_op_map_;
   41302             :          inv_binary_op_map_t*     inv_binary_op_map_;
   41303             :          sf3_map_t*               sf3_map_;
   41304             :          sf4_map_t*               sf4_map_;
   41305             :          parser_t*                parser_;
   41306             :       }; // class expression_generator
   41307             : 
   41308       43680 :       inline void set_error(const parser_error::type& error_type)
   41309             :       {
   41310       43680 :          error_list_.push_back(error_type);
   41311       43680 :       }
   41312             : 
   41313             :       inline void remove_last_error()
   41314             :       {
   41315             :          if (!error_list_.empty())
   41316             :          {
   41317             :             error_list_.pop_back();
   41318             :          }
   41319             :       }
   41320             : 
   41321           0 :       inline void set_synthesis_error(const std::string& synthesis_error_message)
   41322             :       {
   41323           0 :          if (synthesis_error_.empty())
   41324             :          {
   41325           0 :             synthesis_error_ = synthesis_error_message;
   41326             :          }
   41327           0 :       }
   41328             : 
   41329      359159 :       inline void register_local_vars(expression<T>& e)
   41330             :       {
   41331      450721 :          for (std::size_t i = 0; i < sem_.size(); ++i)
   41332             :          {
   41333       91562 :             scope_element& se = sem_.get_element(i);
   41334             : 
   41335       91562 :             if (
   41336       91562 :                  (scope_element::e_variable == se.type) ||
   41337       46690 :                  (scope_element::e_literal  == se.type) ||
   41338       44055 :                  (scope_element::e_vecelem  == se.type)
   41339             :                )
   41340             :             {
   41341       58561 :                if (se.var_node)
   41342             :                {
   41343       58561 :                   e.register_local_var(se.var_node);
   41344             :                }
   41345             : 
   41346       58561 :                if (se.data)
   41347             :                {
   41348       44872 :                   e.register_local_data(se.data, 1, 0);
   41349             :                }
   41350             :             }
   41351       33001 :             else if (scope_element::e_vector == se.type)
   41352             :             {
   41353       23261 :                if (se.vec_node)
   41354             :                {
   41355       23261 :                   e.register_local_var(se.vec_node);
   41356             :                }
   41357             : 
   41358       23261 :                if (se.data)
   41359             :                {
   41360       23261 :                   e.register_local_data(se.data, se.size, 1);
   41361             :                }
   41362             :             }
   41363             :             #ifndef exprtk_disable_string_capabilities
   41364        9740 :             else if (scope_element::e_string == se.type)
   41365             :             {
   41366        9740 :                if (se.str_node)
   41367             :                {
   41368        9740 :                   e.register_local_var(se.str_node);
   41369             :                }
   41370             : 
   41371        9740 :                if (se.data)
   41372             :                {
   41373        9740 :                   e.register_local_data(se.data, se.size, 2);
   41374             :                }
   41375             :             }
   41376             :             #endif
   41377             : 
   41378       91562 :             se.var_node  = 0;
   41379       91562 :             se.vec_node  = 0;
   41380             :             #ifndef exprtk_disable_string_capabilities
   41381       91562 :             se.str_node  = 0;
   41382             :             #endif
   41383       91562 :             se.data      = 0;
   41384       91562 :             se.ref_count = 0;
   41385       91562 :             se.active    = false;
   41386             :          }
   41387      359159 :       }
   41388             : 
   41389      359159 :       inline void register_return_results(expression<T>& e)
   41390             :       {
   41391      359159 :          e.register_return_results(results_context_);
   41392      359159 :          results_context_ = 0;
   41393      359159 :       }
   41394             : 
   41395      108660 :       inline void load_unary_operations_map(unary_op_map_t& m)
   41396             :       {
   41397             :          #define register_unary_op(Op, UnaryFunctor)            \
   41398             :          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
   41399             : 
   41400      108660 :          register_unary_op(details::e_abs   , details::abs_op  )
   41401      108660 :          register_unary_op(details::e_acos  , details::acos_op )
   41402      108660 :          register_unary_op(details::e_acosh , details::acosh_op)
   41403      108660 :          register_unary_op(details::e_asin  , details::asin_op )
   41404      108660 :          register_unary_op(details::e_asinh , details::asinh_op)
   41405      108660 :          register_unary_op(details::e_atanh , details::atanh_op)
   41406      108660 :          register_unary_op(details::e_ceil  , details::ceil_op )
   41407      108660 :          register_unary_op(details::e_cos   , details::cos_op  )
   41408      108660 :          register_unary_op(details::e_cosh  , details::cosh_op )
   41409      108660 :          register_unary_op(details::e_exp   , details::exp_op  )
   41410      108660 :          register_unary_op(details::e_expm1 , details::expm1_op)
   41411      108660 :          register_unary_op(details::e_floor , details::floor_op)
   41412      108660 :          register_unary_op(details::e_log   , details::log_op  )
   41413      108660 :          register_unary_op(details::e_log10 , details::log10_op)
   41414      108660 :          register_unary_op(details::e_log2  , details::log2_op )
   41415      108660 :          register_unary_op(details::e_log1p , details::log1p_op)
   41416      108660 :          register_unary_op(details::e_neg   , details::neg_op  )
   41417      108660 :          register_unary_op(details::e_pos   , details::pos_op  )
   41418      108660 :          register_unary_op(details::e_round , details::round_op)
   41419      108660 :          register_unary_op(details::e_sin   , details::sin_op  )
   41420      108660 :          register_unary_op(details::e_sinc  , details::sinc_op )
   41421      108660 :          register_unary_op(details::e_sinh  , details::sinh_op )
   41422      108660 :          register_unary_op(details::e_sqrt  , details::sqrt_op )
   41423      108660 :          register_unary_op(details::e_tan   , details::tan_op  )
   41424      108660 :          register_unary_op(details::e_tanh  , details::tanh_op )
   41425      108660 :          register_unary_op(details::e_cot   , details::cot_op  )
   41426      108660 :          register_unary_op(details::e_sec   , details::sec_op  )
   41427      108660 :          register_unary_op(details::e_csc   , details::csc_op  )
   41428      108660 :          register_unary_op(details::e_r2d   , details::r2d_op  )
   41429      108660 :          register_unary_op(details::e_d2r   , details::d2r_op  )
   41430      108660 :          register_unary_op(details::e_d2g   , details::d2g_op  )
   41431      108660 :          register_unary_op(details::e_g2d   , details::g2d_op  )
   41432      108660 :          register_unary_op(details::e_notl  , details::notl_op )
   41433      108660 :          register_unary_op(details::e_sgn   , details::sgn_op  )
   41434      108660 :          register_unary_op(details::e_erf   , details::erf_op  )
   41435      108660 :          register_unary_op(details::e_erfc  , details::erfc_op )
   41436      108660 :          register_unary_op(details::e_ncdf  , details::ncdf_op )
   41437      108660 :          register_unary_op(details::e_frac  , details::frac_op )
   41438      108660 :          register_unary_op(details::e_trunc , details::trunc_op)
   41439             :          #undef register_unary_op
   41440      108660 :       }
   41441             : 
   41442      108660 :       inline void load_binary_operations_map(binary_op_map_t& m)
   41443             :       {
   41444             :          typedef typename binary_op_map_t::value_type value_type;
   41445             : 
   41446             :          #define register_binary_op(Op, BinaryFunctor)       \
   41447             :          m.insert(value_type(Op,BinaryFunctor<T>::process)); \
   41448             : 
   41449      108660 :          register_binary_op(details::e_add  , details::add_op )
   41450      108660 :          register_binary_op(details::e_sub  , details::sub_op )
   41451      108660 :          register_binary_op(details::e_mul  , details::mul_op )
   41452      108660 :          register_binary_op(details::e_div  , details::div_op )
   41453      108660 :          register_binary_op(details::e_mod  , details::mod_op )
   41454      108660 :          register_binary_op(details::e_pow  , details::pow_op )
   41455      108660 :          register_binary_op(details::e_lt   , details::lt_op  )
   41456      108660 :          register_binary_op(details::e_lte  , details::lte_op )
   41457      108660 :          register_binary_op(details::e_gt   , details::gt_op  )
   41458      108660 :          register_binary_op(details::e_gte  , details::gte_op )
   41459      108660 :          register_binary_op(details::e_eq   , details::eq_op  )
   41460      108660 :          register_binary_op(details::e_ne   , details::ne_op  )
   41461      108660 :          register_binary_op(details::e_and  , details::and_op )
   41462      108660 :          register_binary_op(details::e_nand , details::nand_op)
   41463      108660 :          register_binary_op(details::e_or   , details::or_op  )
   41464      108660 :          register_binary_op(details::e_nor  , details::nor_op )
   41465      108660 :          register_binary_op(details::e_xor  , details::xor_op )
   41466      108660 :          register_binary_op(details::e_xnor , details::xnor_op)
   41467             :          #undef register_binary_op
   41468      108660 :       }
   41469             : 
   41470      108660 :       inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
   41471             :       {
   41472             :          typedef typename inv_binary_op_map_t::value_type value_type;
   41473             : 
   41474             :          #define register_binary_op(Op, BinaryFunctor)       \
   41475             :          m.insert(value_type(BinaryFunctor<T>::process,Op)); \
   41476             : 
   41477      108660 :          register_binary_op(details::e_add  , details::add_op )
   41478      108660 :          register_binary_op(details::e_sub  , details::sub_op )
   41479      108660 :          register_binary_op(details::e_mul  , details::mul_op )
   41480      108660 :          register_binary_op(details::e_div  , details::div_op )
   41481      108660 :          register_binary_op(details::e_mod  , details::mod_op )
   41482      108660 :          register_binary_op(details::e_pow  , details::pow_op )
   41483      108660 :          register_binary_op(details::e_lt   , details::lt_op  )
   41484      108660 :          register_binary_op(details::e_lte  , details::lte_op )
   41485      108660 :          register_binary_op(details::e_gt   , details::gt_op  )
   41486      108660 :          register_binary_op(details::e_gte  , details::gte_op )
   41487      108660 :          register_binary_op(details::e_eq   , details::eq_op  )
   41488      108660 :          register_binary_op(details::e_ne   , details::ne_op  )
   41489      108660 :          register_binary_op(details::e_and  , details::and_op )
   41490      108660 :          register_binary_op(details::e_nand , details::nand_op)
   41491      108660 :          register_binary_op(details::e_or   , details::or_op  )
   41492      108660 :          register_binary_op(details::e_nor  , details::nor_op )
   41493      108660 :          register_binary_op(details::e_xor  , details::xor_op )
   41494      108660 :          register_binary_op(details::e_xnor , details::xnor_op)
   41495             :          #undef register_binary_op
   41496      108660 :       }
   41497             : 
   41498      108660 :       inline void load_sf3_map(sf3_map_t& sf3_map)
   41499             :       {
   41500             :          typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
   41501             : 
   41502             :          #define register_sf3(Op)                                                                             \
   41503             :          sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
   41504             : 
   41505      108660 :          register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
   41506      108660 :          register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
   41507      108660 :          register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
   41508      108660 :          register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
   41509      108660 :          register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
   41510      108660 :          register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
   41511      108660 :          register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
   41512      108660 :          register_sf3(28) register_sf3(29) register_sf3(30)
   41513             :          #undef register_sf3
   41514             : 
   41515             :          #define register_sf3_extid(Id, Op)                                        \
   41516             :          sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
   41517             : 
   41518      217320 :          register_sf3_extid("(t-t)-t",23)  // (t-t)-t --> t-(t+t)
   41519             :          #undef register_sf3_extid
   41520      108660 :       }
   41521             : 
   41522      108660 :       inline void load_sf4_map(sf4_map_t& sf4_map)
   41523             :       {
   41524             :          typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
   41525             : 
   41526             :          #define register_sf4(Op)                                                                             \
   41527             :          sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
   41528             : 
   41529      108660 :          register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
   41530      108660 :          register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
   41531      108660 :          register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
   41532      108660 :          register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
   41533      108660 :          register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
   41534      108660 :          register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
   41535      108660 :          register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
   41536      108660 :          register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
   41537      108660 :          register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
   41538             :          #undef register_sf4
   41539             : 
   41540             :          #define register_sf4ext(Op)                                                                                    \
   41541             :          sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
   41542             : 
   41543      108660 :          register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
   41544      108660 :          register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
   41545      108660 :          register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
   41546      108660 :          register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
   41547      108660 :          register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
   41548      108660 :          register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
   41549      108660 :          register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
   41550      108660 :          register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
   41551      108660 :          register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
   41552      108660 :          register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
   41553      108660 :          register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
   41554      108660 :          register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
   41555      108660 :          register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
   41556      108660 :          register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
   41557      108660 :          register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
   41558      108660 :          register_sf4ext(60) register_sf4ext(61)
   41559             :          #undef register_sf4ext
   41560      108660 :       }
   41561             : 
   41562         116 :       inline results_context_t& results_ctx()
   41563             :       {
   41564         116 :          if (0 == results_context_)
   41565             :          {
   41566         111 :             results_context_ = new results_context_t();
   41567             :          }
   41568             : 
   41569         116 :          return (*results_context_);
   41570             :       }
   41571             : 
   41572      391685 :       inline void return_cleanup()
   41573             :       {
   41574             :          #ifndef exprtk_disable_return_statement
   41575      391685 :          if (results_context_)
   41576             :          {
   41577           0 :             delete results_context_;
   41578           0 :             results_context_ = 0;
   41579             :          }
   41580             : 
   41581      391685 :          state_.return_stmt_present = false;
   41582             :          #endif
   41583      391685 :       }
   41584             : 
   41585             :    private:
   41586             : 
   41587             :       parser(const parser<T>&) exprtk_delete;
   41588             :       parser<T>& operator=(const parser<T>&) exprtk_delete;
   41589             : 
   41590             :       settings_store settings_;
   41591             :       expression_generator<T> expression_generator_;
   41592             :       details::node_allocator node_allocator_;
   41593             :       symtab_store symtab_store_;
   41594             :       dependent_entity_collector dec_;
   41595             :       std::deque<parser_error::type> error_list_;
   41596             :       std::deque<bool> brkcnt_list_;
   41597             :       parser_state state_;
   41598             :       bool resolve_unknown_symbol_;
   41599             :       results_context_t* results_context_;
   41600             :       unknown_symbol_resolver* unknown_symbol_resolver_;
   41601             :       unknown_symbol_resolver default_usr_;
   41602             :       base_ops_map_t base_ops_map_;
   41603             :       unary_op_map_t unary_op_map_;
   41604             :       binary_op_map_t binary_op_map_;
   41605             :       inv_binary_op_map_t inv_binary_op_map_;
   41606             :       sf3_map_t sf3_map_;
   41607             :       sf4_map_t sf4_map_;
   41608             :       std::string synthesis_error_;
   41609             :       scope_element_manager sem_;
   41610             :       std::vector<state_t> current_state_stack_;
   41611             : 
   41612             :       immutable_memory_map_t immutable_memory_map_;
   41613             :       immutable_symtok_map_t immutable_symtok_map_;
   41614             : 
   41615             :       lexer::helper::helper_assembly helper_assembly_;
   41616             : 
   41617             :       lexer::helper::commutative_inserter       commutative_inserter_;
   41618             :       lexer::helper::operator_joiner            operator_joiner_2_;
   41619             :       lexer::helper::operator_joiner            operator_joiner_3_;
   41620             :       lexer::helper::symbol_replacer            symbol_replacer_;
   41621             :       lexer::helper::bracket_checker            bracket_checker_;
   41622             :       lexer::helper::numeric_checker<T>         numeric_checker_;
   41623             :       lexer::helper::sequence_validator         sequence_validator_;
   41624             :       lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
   41625             : 
   41626             :       loop_runtime_check_ptr          loop_runtime_check_;
   41627             :       vector_access_runtime_check_ptr vector_access_runtime_check_;
   41628             :       compilation_check_ptr           compilation_check_ptr_;
   41629             :       assert_check_ptr                assert_check_;
   41630             :       std::set<std::string>           assert_ids_;
   41631             : 
   41632             :       template <typename ParserType>
   41633             :       friend void details::disable_type_checking(ParserType& p);
   41634             :    }; // class parser
   41635             : 
   41636             :    namespace details
   41637             :    {
   41638             :       template <typename T>
   41639             :       struct collector_helper
   41640             :       {
   41641             :          typedef exprtk::symbol_table<T> symbol_table_t;
   41642             :          typedef exprtk::expression<T>   expression_t;
   41643             :          typedef exprtk::parser<T>       parser_t;
   41644             :          typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
   41645             :          typedef typename parser_t::unknown_symbol_resolver usr_t;
   41646             : 
   41647             :          struct resolve_as_vector : public usr_t
   41648             :          {
   41649             :             typedef exprtk::parser<T> parser_t;
   41650             : 
   41651             :             using usr_t::process;
   41652             : 
   41653           4 :             resolve_as_vector()
   41654           4 :             : usr_t(usr_t::e_usrmode_extended)
   41655           4 :             {}
   41656             : 
   41657           6 :             virtual bool process(const std::string& unknown_symbol,
   41658             :                                  symbol_table_t& symbol_table,
   41659             :                                  std::string&) exprtk_override
   41660             :             {
   41661             :                static T v[1];
   41662           6 :                symbol_table.add_vector(unknown_symbol,v);
   41663           6 :                return true;
   41664             :             }
   41665             :          };
   41666             : 
   41667           4 :          static inline bool collection_pass(const std::string& expression_string,
   41668             :                                             std::set<std::string>& symbol_set,
   41669             :                                             const bool collect_variables,
   41670             :                                             const bool collect_functions,
   41671             :                                             const bool vector_pass,
   41672             :                                             symbol_table_t& ext_symbol_table)
   41673             :          {
   41674           4 :             symbol_table_t symbol_table;
   41675           4 :             expression_t   expression;
   41676           4 :             parser_t       parser;
   41677             : 
   41678           4 :             resolve_as_vector vect_resolver;
   41679             : 
   41680           4 :             expression.register_symbol_table(symbol_table    );
   41681           4 :             expression.register_symbol_table(ext_symbol_table);
   41682             : 
   41683           4 :             if (vector_pass)
   41684           2 :                parser.enable_unknown_symbol_resolver(&vect_resolver);
   41685             :             else
   41686           2 :                parser.enable_unknown_symbol_resolver();
   41687             : 
   41688           4 :             if (collect_variables)
   41689           2 :                parser.dec().collect_variables() = true;
   41690             : 
   41691           4 :             if (collect_functions)
   41692           2 :                parser.dec().collect_functions() = true;
   41693             : 
   41694           4 :             bool pass_result = false;
   41695             : 
   41696           4 :             details::disable_type_checking(parser);
   41697             : 
   41698           4 :             if (parser.compile(expression_string, expression))
   41699             :             {
   41700           2 :                pass_result = true;
   41701             : 
   41702           2 :                std::deque<symbol_t> symb_list;
   41703           2 :                parser.dec().symbols(symb_list);
   41704             : 
   41705           9 :                for (std::size_t i = 0; i < symb_list.size(); ++i)
   41706             :                {
   41707           7 :                   symbol_set.insert(symb_list[i].first);
   41708             :                }
   41709           2 :             }
   41710             : 
   41711           4 :             return pass_result;
   41712           4 :          }
   41713             :       };
   41714             :    }
   41715             : 
   41716             :    template <typename Allocator,
   41717             :              template <typename, typename> class Sequence>
   41718           1 :    inline bool collect_variables(const std::string& expression,
   41719             :                                  Sequence<std::string, Allocator>& symbol_list)
   41720             :    {
   41721             :       typedef double T;
   41722             :       typedef details::collector_helper<T> collect_t;
   41723             : 
   41724           1 :       collect_t::symbol_table_t null_symbol_table;
   41725             : 
   41726           1 :       std::set<std::string> symbol_set;
   41727             : 
   41728             :       const bool variable_pass = collect_t::collection_pass
   41729           1 :                                     (expression, symbol_set, true, false, false, null_symbol_table);
   41730             :       const bool vector_pass   = collect_t::collection_pass
   41731           1 :                                     (expression, symbol_set, true, false,  true, null_symbol_table);
   41732             : 
   41733           1 :       if (!variable_pass && !vector_pass)
   41734           0 :          return false;
   41735             : 
   41736           1 :       std::set<std::string>::iterator itr = symbol_set.begin();
   41737             : 
   41738           5 :       while (symbol_set.end() != itr)
   41739             :       {
   41740           4 :          symbol_list.push_back(*itr);
   41741           4 :          ++itr;
   41742             :       }
   41743             : 
   41744           1 :       return true;
   41745           1 :    }
   41746             : 
   41747             :    template <typename T,
   41748             :              typename Allocator,
   41749             :              template <typename, typename> class Sequence>
   41750             :    inline bool collect_variables(const std::string& expression,
   41751             :                                  exprtk::symbol_table<T>& extrnl_symbol_table,
   41752             :                                  Sequence<std::string, Allocator>& symbol_list)
   41753             :    {
   41754             :       typedef details::collector_helper<T> collect_t;
   41755             : 
   41756             :       std::set<std::string> symbol_set;
   41757             : 
   41758             :       const bool variable_pass = collect_t::collection_pass
   41759             :                                     (expression, symbol_set, true, false, false, extrnl_symbol_table);
   41760             :       const bool vector_pass   = collect_t::collection_pass
   41761             :                                     (expression, symbol_set, true, false,  true, extrnl_symbol_table);
   41762             : 
   41763             :       if (!variable_pass && !vector_pass)
   41764             :          return false;
   41765             : 
   41766             :       std::set<std::string>::iterator itr = symbol_set.begin();
   41767             : 
   41768             :       while (symbol_set.end() != itr)
   41769             :       {
   41770             :          symbol_list.push_back(*itr);
   41771             :          ++itr;
   41772             :       }
   41773             : 
   41774             :       return true;
   41775             :    }
   41776             : 
   41777             :    template <typename Allocator,
   41778             :              template <typename, typename> class Sequence>
   41779           1 :    inline bool collect_functions(const std::string& expression,
   41780             :                                  Sequence<std::string, Allocator>& symbol_list)
   41781             :    {
   41782             :       typedef double T;
   41783             :       typedef details::collector_helper<T> collect_t;
   41784             : 
   41785           1 :       collect_t::symbol_table_t null_symbol_table;
   41786             : 
   41787           1 :       std::set<std::string> symbol_set;
   41788             : 
   41789             :       const bool variable_pass = collect_t::collection_pass
   41790           1 :                                     (expression, symbol_set, false, true, false, null_symbol_table);
   41791             :       const bool vector_pass   = collect_t::collection_pass
   41792           1 :                                     (expression, symbol_set, false, true,  true, null_symbol_table);
   41793             : 
   41794           1 :       if (!variable_pass && !vector_pass)
   41795           0 :          return false;
   41796             : 
   41797           1 :       std::set<std::string>::iterator itr = symbol_set.begin();
   41798             : 
   41799           4 :       while (symbol_set.end() != itr)
   41800             :       {
   41801           3 :          symbol_list.push_back(*itr);
   41802           3 :          ++itr;
   41803             :       }
   41804             : 
   41805           1 :       return true;
   41806           1 :    }
   41807             : 
   41808             :    template <typename T,
   41809             :              typename Allocator,
   41810             :              template <typename, typename> class Sequence>
   41811             :    inline bool collect_functions(const std::string& expression,
   41812             :                                  exprtk::symbol_table<T>& extrnl_symbol_table,
   41813             :                                  Sequence<std::string, Allocator>& symbol_list)
   41814             :    {
   41815             :       typedef details::collector_helper<T> collect_t;
   41816             : 
   41817             :       std::set<std::string> symbol_set;
   41818             : 
   41819             :       const bool variable_pass = collect_t::collection_pass
   41820             :                                     (expression, symbol_set, false, true, false, extrnl_symbol_table);
   41821             :       const bool vector_pass   = collect_t::collection_pass
   41822             :                                     (expression, symbol_set, false, true,  true, extrnl_symbol_table);
   41823             : 
   41824             :       if (!variable_pass && !vector_pass)
   41825             :          return false;
   41826             : 
   41827             :       std::set<std::string>::iterator itr = symbol_set.begin();
   41828             : 
   41829             :       while (symbol_set.end() != itr)
   41830             :       {
   41831             :          symbol_list.push_back(*itr);
   41832             :          ++itr;
   41833             :       }
   41834             : 
   41835             :       return true;
   41836             :    }
   41837             : 
   41838             :    template <typename T>
   41839           2 :    inline T integrate(const expression<T>& e,
   41840             :                       T& x,
   41841             :                       const T& r0, const T& r1,
   41842             :                       const std::size_t number_of_intervals = 1000000)
   41843             :    {
   41844           2 :       if (r0 > r1)
   41845           0 :          return T(0);
   41846             : 
   41847           2 :       const T h = (r1 - r0) / (T(2) * number_of_intervals);
   41848           2 :       T total_area = T(0);
   41849             : 
   41850     2000002 :       for (std::size_t i = 0; i < number_of_intervals; ++i)
   41851             :       {
   41852     2000000 :          x = r0 + T(2) * i * h;
   41853     2000000 :          const T y0 = e.value(); x += h;
   41854     2000000 :          const T y1 = e.value(); x += h;
   41855     2000000 :          const T y2 = e.value(); x += h;
   41856     2000000 :          total_area += h * (y0 + T(4) * y1 + y2) / T(3);
   41857             :       }
   41858             : 
   41859           2 :       return total_area;
   41860             :    }
   41861             : 
   41862             :    template <typename T>
   41863           1 :    inline T integrate(const expression<T>& e,
   41864             :                       const std::string& variable_name,
   41865             :                       const T& r0, const T& r1,
   41866             :                       const std::size_t number_of_intervals = 1000000)
   41867             :    {
   41868           1 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   41869             : 
   41870           1 :       if (!sym_table.valid())
   41871             :       {
   41872           0 :          return std::numeric_limits<T>::quiet_NaN();
   41873             :       }
   41874             : 
   41875           1 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   41876             : 
   41877           1 :       if (var)
   41878             :       {
   41879           1 :          T& x = var->ref();
   41880           1 :          const T x_original = x;
   41881           1 :          const T result = integrate(e, x, r0, r1, number_of_intervals);
   41882           1 :          x = x_original;
   41883             : 
   41884           1 :          return result;
   41885             :       }
   41886             : 
   41887           0 :       return std::numeric_limits<T>::quiet_NaN();
   41888             :    }
   41889             : 
   41890             :    template <typename T>
   41891     8000000 :    inline T derivative(const expression<T>& e,
   41892             :                        T& x,
   41893     4000000 :                        const T& h = T(0.00000001))
   41894             :    {
   41895     8000000 :       const T x_init = x;
   41896     8000000 :       const T _2h    = T(2) * h;
   41897             : 
   41898     8000000 :       x = x_init + _2h;
   41899     8000000 :       const T y0 = e.value();
   41900     8000000 :       x = x_init + h;
   41901     8000000 :       const T y1 = e.value();
   41902     8000000 :       x = x_init - h;
   41903     8000000 :       const T y2 = e.value();
   41904     8000000 :       x = x_init - _2h;
   41905     8000000 :       const T y3 = e.value();
   41906     8000000 :       x = x_init;
   41907             : 
   41908     8000000 :       return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
   41909             :    }
   41910             : 
   41911             :    template <typename T>
   41912     8000000 :    inline T second_derivative(const expression<T>& e,
   41913             :                               T& x,
   41914     4000000 :                               const T& h = T(0.00001))
   41915             :    {
   41916     8000000 :       const T x_init = x;
   41917     8000000 :       const T _2h    = T(2) * h;
   41918             : 
   41919     8000000 :       const T y = e.value();
   41920     8000000 :       x = x_init + _2h;
   41921     8000000 :       const T y0 = e.value();
   41922     8000000 :       x = x_init + h;
   41923     8000000 :       const T y1 = e.value();
   41924     8000000 :       x = x_init - h;
   41925     8000000 :       const T y2 = e.value();
   41926     8000000 :       x = x_init - _2h;
   41927     8000000 :       const T y3 = e.value();
   41928     8000000 :       x = x_init;
   41929             : 
   41930     8000000 :       return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
   41931             :    }
   41932             : 
   41933             :    template <typename T>
   41934     8000000 :    inline T third_derivative(const expression<T>& e,
   41935             :                              T& x,
   41936     4000000 :                              const T& h = T(0.0001))
   41937             :    {
   41938     8000000 :       const T x_init = x;
   41939     8000000 :       const T _2h    = T(2) * h;
   41940             : 
   41941     8000000 :       x = x_init + _2h;
   41942     8000000 :       const T y0 = e.value();
   41943     8000000 :       x = x_init + h;
   41944     8000000 :       const T y1 = e.value();
   41945     8000000 :       x = x_init - h;
   41946     8000000 :       const T y2 = e.value();
   41947     8000000 :       x = x_init - _2h;
   41948     8000000 :       const T y3 = e.value();
   41949     8000000 :       x = x_init;
   41950             : 
   41951     8000000 :       return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
   41952             :    }
   41953             : 
   41954             :    template <typename T>
   41955     4000000 :    inline T derivative(const expression<T>& e,
   41956             :                        const std::string& variable_name,
   41957     8000000 :                        const T& h = T(0.00000001))
   41958             :    {
   41959     4000000 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   41960             : 
   41961     4000000 :       if (!sym_table.valid())
   41962             :       {
   41963           0 :          return std::numeric_limits<T>::quiet_NaN();
   41964             :       }
   41965             : 
   41966     4000000 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   41967             : 
   41968     4000000 :       if (var)
   41969             :       {
   41970     4000000 :          T& x = var->ref();
   41971     4000000 :          const T x_original = x;
   41972     4000000 :          const T result = derivative(e, x, h);
   41973     4000000 :          x = x_original;
   41974             : 
   41975     4000000 :          return result;
   41976             :       }
   41977             : 
   41978           0 :       return std::numeric_limits<T>::quiet_NaN();
   41979             :    }
   41980             : 
   41981             :    template <typename T>
   41982     4000000 :    inline T second_derivative(const expression<T>& e,
   41983             :                               const std::string& variable_name,
   41984     8000000 :                               const T& h = T(0.00001))
   41985             :    {
   41986     4000000 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   41987             : 
   41988     4000000 :       if (!sym_table.valid())
   41989             :       {
   41990           0 :          return std::numeric_limits<T>::quiet_NaN();
   41991             :       }
   41992             : 
   41993     4000000 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   41994             : 
   41995     4000000 :       if (var)
   41996             :       {
   41997     4000000 :          T& x = var->ref();
   41998     4000000 :          const T x_original = x;
   41999     4000000 :          const T result = second_derivative(e, x, h);
   42000     4000000 :          x = x_original;
   42001             : 
   42002     4000000 :          return result;
   42003             :       }
   42004             : 
   42005           0 :       return std::numeric_limits<T>::quiet_NaN();
   42006             :    }
   42007             : 
   42008             :    template <typename T>
   42009     4000000 :    inline T third_derivative(const expression<T>& e,
   42010             :                              const std::string& variable_name,
   42011     8000000 :                              const T& h = T(0.0001))
   42012             :    {
   42013     4000000 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   42014             : 
   42015     4000000 :       if (!sym_table.valid())
   42016             :       {
   42017           0 :          return std::numeric_limits<T>::quiet_NaN();
   42018             :       }
   42019             : 
   42020     4000000 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   42021             : 
   42022     4000000 :       if (var)
   42023             :       {
   42024     4000000 :          T& x = var->ref();
   42025     4000000 :          const T x_original = x;
   42026     4000000 :          const T result = third_derivative(e, x, h);
   42027     4000000 :          x = x_original;
   42028             : 
   42029     4000000 :          return result;
   42030             :       }
   42031             : 
   42032           0 :       return std::numeric_limits<T>::quiet_NaN();
   42033             :    }
   42034             : 
   42035             :    /*
   42036             :       Note: The following 'compute' routines are simple helpers,
   42037             :       for quickly setting up the required pieces of code in order
   42038             :       to evaluate an expression. By virtue of how they operate
   42039             :       there will be an overhead with regards to their setup and
   42040             :       teardown and hence should not be used in time critical
   42041             :       sections of code.
   42042             :       Furthermore they only assume a small sub set of variables,
   42043             :       no string variables or user defined functions.
   42044             :    */
   42045             :    template <typename T>
   42046             :    inline bool compute(const std::string& expression_string, T& result)
   42047             :    {
   42048             :       // No variables
   42049             :       symbol_table<T> symbol_table;
   42050             :       symbol_table.add_constants();
   42051             : 
   42052             :       expression<T> expression;
   42053             :       expression.register_symbol_table(symbol_table);
   42054             : 
   42055             :       parser<T> parser;
   42056             : 
   42057             :       if (parser.compile(expression_string,expression))
   42058             :       {
   42059             :          result = expression.value();
   42060             : 
   42061             :          return true;
   42062             :       }
   42063             :       else
   42064             :          return false;
   42065             :    }
   42066             : 
   42067             :    template <typename T>
   42068             :    inline bool compute(const std::string& expression_string,
   42069             :                        const T& x,
   42070             :                        T& result)
   42071             :    {
   42072             :       // Only 'x'
   42073             :       static const std::string x_var("x");
   42074             : 
   42075             :       symbol_table<T> symbol_table;
   42076             :       symbol_table.add_constants();
   42077             :       symbol_table.add_constant(x_var,x);
   42078             : 
   42079             :       expression<T> expression;
   42080             :       expression.register_symbol_table(symbol_table);
   42081             : 
   42082             :       parser<T> parser;
   42083             : 
   42084             :       if (parser.compile(expression_string,expression))
   42085             :       {
   42086             :          result = expression.value();
   42087             : 
   42088             :          return true;
   42089             :       }
   42090             :       else
   42091             :          return false;
   42092             :    }
   42093             : 
   42094             :    template <typename T>
   42095             :    inline bool compute(const std::string& expression_string,
   42096             :                        const T&x, const T& y,
   42097             :                        T& result)
   42098             :    {
   42099             :       // Only 'x' and 'y'
   42100             :       static const std::string x_var("x");
   42101             :       static const std::string y_var("y");
   42102             : 
   42103             :       symbol_table<T> symbol_table;
   42104             :       symbol_table.add_constants();
   42105             :       symbol_table.add_constant(x_var,x);
   42106             :       symbol_table.add_constant(y_var,y);
   42107             : 
   42108             :       expression<T> expression;
   42109             :       expression.register_symbol_table(symbol_table);
   42110             : 
   42111             :       parser<T> parser;
   42112             : 
   42113             :       if (parser.compile(expression_string,expression))
   42114             :       {
   42115             :          result = expression.value();
   42116             : 
   42117             :          return true;
   42118             :       }
   42119             :       else
   42120             :          return false;
   42121             :    }
   42122             : 
   42123             :    template <typename T>
   42124             :    inline bool compute(const std::string& expression_string,
   42125             :                        const T& x, const T& y, const T& z,
   42126             :                        T& result)
   42127             :    {
   42128             :       // Only 'x', 'y' or 'z'
   42129             :       static const std::string x_var("x");
   42130             :       static const std::string y_var("y");
   42131             :       static const std::string z_var("z");
   42132             : 
   42133             :       symbol_table<T> symbol_table;
   42134             :       symbol_table.add_constants();
   42135             :       symbol_table.add_constant(x_var,x);
   42136             :       symbol_table.add_constant(y_var,y);
   42137             :       symbol_table.add_constant(z_var,z);
   42138             : 
   42139             :       expression<T> expression;
   42140             :       expression.register_symbol_table(symbol_table);
   42141             : 
   42142             :       parser<T> parser;
   42143             : 
   42144             :       if (parser.compile(expression_string,expression))
   42145             :       {
   42146             :          result = expression.value();
   42147             : 
   42148             :          return true;
   42149             :       }
   42150             :       else
   42151             :          return false;
   42152             :    }
   42153             : 
   42154             :    template <typename T, std::size_t N>
   42155             :    class polynomial : public ifunction<T>
   42156             :    {
   42157             :    private:
   42158             : 
   42159             :       template <typename Type, std::size_t NumberOfCoefficients>
   42160             :       struct poly_impl { };
   42161             : 
   42162             :       template <typename Type>
   42163             :       struct poly_impl <Type,12>
   42164             :       {
   42165        1015 :          static inline T evaluate(const Type x,
   42166             :                                   const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
   42167             :                                   const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
   42168             :                                   const Type  c2, const Type  c1, const Type  c0)
   42169             :          {
   42170             :             // 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
   42171        1015 :             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);
   42172             :          }
   42173             :       };
   42174             : 
   42175             :       template <typename Type>
   42176             :       struct poly_impl <Type,11>
   42177             :       {
   42178        1015 :          static inline T evaluate(const Type x,
   42179             :                                   const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
   42180             :                                   const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
   42181             :                                   const Type c1,  const Type  c0)
   42182             :          {
   42183             :             // 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
   42184        1015 :             return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42185             :          }
   42186             :       };
   42187             : 
   42188             :       template <typename Type>
   42189             :       struct poly_impl <Type,10>
   42190             :       {
   42191        1015 :          static inline T evaluate(const Type x,
   42192             :                                   const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
   42193             :                                   const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
   42194             :                                   const Type c0)
   42195             :          {
   42196             :             // 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
   42197        1015 :             return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42198             :          }
   42199             :       };
   42200             : 
   42201             :       template <typename Type>
   42202             :       struct poly_impl <Type,9>
   42203             :       {
   42204        1015 :          static inline T evaluate(const Type x,
   42205             :                                   const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
   42206             :                                   const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
   42207             :          {
   42208             :             // 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
   42209        1015 :             return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42210             :          }
   42211             :       };
   42212             : 
   42213             :       template <typename Type>
   42214             :       struct poly_impl <Type,8>
   42215             :       {
   42216        1015 :          static inline T evaluate(const Type x,
   42217             :                                   const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
   42218             :                                   const Type c3, const Type c2, const Type c1, const Type c0)
   42219             :          {
   42220             :             // 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
   42221        1015 :             return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42222             :          }
   42223             :       };
   42224             : 
   42225             :       template <typename Type>
   42226             :       struct poly_impl <Type,7>
   42227             :       {
   42228        1015 :          static inline T evaluate(const Type x,
   42229             :                                   const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
   42230             :                                   const Type c2, const Type c1, const Type c0)
   42231             :          {
   42232             :             // 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
   42233        1015 :             return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42234             :          }
   42235             :       };
   42236             : 
   42237             :       template <typename Type>
   42238             :       struct poly_impl <Type,6>
   42239             :       {
   42240        1015 :          static inline T evaluate(const Type x,
   42241             :                                   const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
   42242             :                                   const Type c1, const Type c0)
   42243             :          {
   42244             :             // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   42245        1015 :             return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42246             :          }
   42247             :       };
   42248             : 
   42249             :       template <typename Type>
   42250             :       struct poly_impl <Type,5>
   42251             :       {
   42252        1015 :          static inline T evaluate(const Type x,
   42253             :                                   const Type c5, const Type c4, const Type c3, const Type c2,
   42254             :                                   const Type c1, const Type c0)
   42255             :          {
   42256             :             // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   42257        1015 :             return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   42258             :          }
   42259             :       };
   42260             : 
   42261             :       template <typename Type>
   42262             :       struct poly_impl <Type,4>
   42263             :       {
   42264        1015 :          static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
   42265             :          {
   42266             :             // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   42267        1015 :             return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
   42268             :          }
   42269             :       };
   42270             : 
   42271             :       template <typename Type>
   42272             :       struct poly_impl <Type,3>
   42273             :       {
   42274        1015 :          static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
   42275             :          {
   42276             :             // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   42277        1015 :             return (((c3 * x + c2) * x + c1) * x + c0);
   42278             :          }
   42279             :       };
   42280             : 
   42281             :       template <typename Type>
   42282             :       struct poly_impl <Type,2>
   42283             :       {
   42284        1015 :          static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
   42285             :          {
   42286             :             // p(x) = c_2x^2 + c_1x^1 + c_0x^0
   42287        1015 :             return ((c2 * x + c1) * x + c0);
   42288             :          }
   42289             :       };
   42290             : 
   42291             :       template <typename Type>
   42292             :       struct poly_impl <Type,1>
   42293             :       {
   42294        1015 :          static inline T evaluate(const Type x, const Type c1, const Type c0)
   42295             :          {
   42296             :             // p(x) = c_1x^1 + c_0x^0
   42297        1015 :             return (c1 * x + c0);
   42298             :          }
   42299             :       };
   42300             : 
   42301             :    public:
   42302             : 
   42303             :       using ifunction<T>::operator();
   42304             : 
   42305      128736 :       polynomial()
   42306      128736 :       : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
   42307             :       {
   42308      128736 :          disable_has_side_effects(*this);
   42309      128736 :       }
   42310             : 
   42311      128736 :       virtual ~polynomial()
   42312      128736 :       {}
   42313             : 
   42314             :       #define poly_rtrn(NN) \
   42315             :       return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
   42316             : 
   42317        1015 :       inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override
   42318             :       {
   42319        1015 :          poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
   42320             :       }
   42321             : 
   42322        1015 :       inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override
   42323             :       {
   42324        1015 :          poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
   42325             :       }
   42326             : 
   42327        1015 :       inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   42328             :       {
   42329        1015 :          poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
   42330             :       }
   42331             : 
   42332        1015 :       inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1,
   42333             :                                    const T& c0) exprtk_override
   42334             :       {
   42335        1015 :          poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
   42336             :       }
   42337             : 
   42338        1015 :       inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2,
   42339             :                                    const T& c1, const T& c0) exprtk_override
   42340             :       {
   42341        1015 :          poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
   42342             :       }
   42343             : 
   42344        1015 :       inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3,
   42345             :                                    const T& c2, const T& c1, const T& c0) exprtk_override
   42346             :       {
   42347        1015 :          poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
   42348             :       }
   42349             : 
   42350        1015 :       inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4,
   42351             :                                    const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   42352             :       {
   42353        1015 :          poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
   42354             :       }
   42355             : 
   42356        1015 :       inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5,
   42357             :                                    const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   42358             :       {
   42359        1015 :          poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   42360             :       }
   42361             : 
   42362        1015 :       inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6,
   42363             :                                    const T& c5, const T& c4, const T& c3, const T& c2, const T& c1,
   42364             :                                    const T& c0) exprtk_override
   42365             :       {
   42366        1015 :          poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   42367             :       }
   42368             : 
   42369        1015 :       inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7,
   42370             :                                    const T& c6, const T& c5, const T& c4, const T& c3, const T& c2,
   42371             :                                    const T& c1, const T& c0) exprtk_override
   42372             :       {
   42373        1015 :          poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   42374             :       }
   42375             : 
   42376        1015 :       inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8,
   42377             :                                    const T& c7, const T& c6, const T& c5, const T& c4, const T& c3,
   42378             :                                    const T& c2, const T& c1, const T& c0) exprtk_override
   42379             :       {
   42380        1015 :          poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   42381             :       }
   42382             : 
   42383        1015 :       inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9,
   42384             :                                    const T& c8, const T& c7, const T& c6, const T& c5, const T& c4,
   42385             :                                    const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   42386             :       {
   42387        1015 :          poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   42388             :       }
   42389             : 
   42390             :       #undef poly_rtrn
   42391             : 
   42392           0 :       inline virtual T operator() () exprtk_override
   42393             :       {
   42394           0 :          return std::numeric_limits<T>::quiet_NaN();
   42395             :       }
   42396             : 
   42397           0 :       inline virtual T operator() (const T&) exprtk_override
   42398             :       {
   42399           0 :          return std::numeric_limits<T>::quiet_NaN();
   42400             :       }
   42401             : 
   42402           0 :       inline virtual T operator() (const T&, const T&) exprtk_override
   42403             :       {
   42404           0 :          return std::numeric_limits<T>::quiet_NaN();
   42405             :       }
   42406             :    };
   42407             : 
   42408             :    template <typename T>
   42409             :    class function_compositor
   42410             :    {
   42411             :    public:
   42412             : 
   42413             :       typedef exprtk::expression<T>             expression_t;
   42414             :       typedef exprtk::symbol_table<T>           symbol_table_t;
   42415             :       typedef exprtk::parser<T>                 parser_t;
   42416             :       typedef typename parser_t::settings_store settings_t;
   42417             : 
   42418             :       struct function
   42419             :       {
   42420             :          function()
   42421             :          {}
   42422             : 
   42423         700 :          function(const std::string& n)
   42424         700 :          : name_(n)
   42425         700 :          {}
   42426             : 
   42427           1 :          function(const std::string& name,
   42428             :                   const std::string& expression)
   42429           1 :          : name_(name)
   42430           1 :          , expression_(expression)
   42431           1 :          {}
   42432             : 
   42433          19 :          function(const std::string& name,
   42434             :                   const std::string& expression,
   42435             :                   const std::string& v0)
   42436          19 :          : name_(name)
   42437          19 :          , expression_(expression)
   42438             :          {
   42439          19 :             v_.push_back(v0);
   42440          19 :          }
   42441             : 
   42442           4 :          function(const std::string& name,
   42443             :                   const std::string& expression,
   42444             :                   const std::string& v0, const std::string& v1)
   42445           4 :          : name_(name)
   42446           4 :          , expression_(expression)
   42447             :          {
   42448           4 :             v_.push_back(v0); v_.push_back(v1);
   42449           4 :          }
   42450             : 
   42451           1 :          function(const std::string& name,
   42452             :                   const std::string& expression,
   42453             :                   const std::string& v0, const std::string& v1,
   42454             :                   const std::string& v2)
   42455           1 :          : name_(name)
   42456           1 :          , expression_(expression)
   42457             :          {
   42458           1 :             v_.push_back(v0); v_.push_back(v1);
   42459           1 :             v_.push_back(v2);
   42460           1 :          }
   42461             : 
   42462           2 :          function(const std::string& name,
   42463             :                   const std::string& expression,
   42464             :                   const std::string& v0, const std::string& v1,
   42465             :                   const std::string& v2, const std::string& v3)
   42466           2 :          : name_(name)
   42467           2 :          , expression_(expression)
   42468             :          {
   42469           2 :             v_.push_back(v0); v_.push_back(v1);
   42470           2 :             v_.push_back(v2); v_.push_back(v3);
   42471           2 :          }
   42472             : 
   42473             :          function(const std::string& name,
   42474             :                   const std::string& expression,
   42475             :                   const std::string& v0, const std::string& v1,
   42476             :                   const std::string& v2, const std::string& v3,
   42477             :                   const std::string& v4)
   42478             :          : name_(name)
   42479             :          , expression_(expression)
   42480             :          {
   42481             :             v_.push_back(v0); v_.push_back(v1);
   42482             :             v_.push_back(v2); v_.push_back(v3);
   42483             :             v_.push_back(v4);
   42484             :          }
   42485             : 
   42486             :          inline function& name(const std::string& n)
   42487             :          {
   42488             :             name_ = n;
   42489             :             return (*this);
   42490             :          }
   42491             : 
   42492         700 :          inline function& expression(const std::string& e)
   42493             :          {
   42494         700 :             expression_ = e;
   42495         700 :             return (*this);
   42496             :          }
   42497             : 
   42498        2100 :          inline function& var(const std::string& v)
   42499             :          {
   42500        2100 :             v_.push_back(v);
   42501        2100 :             return (*this);
   42502             :          }
   42503             : 
   42504             :          inline function& vars(const std::string& v0,
   42505             :                                const std::string& v1)
   42506             :          {
   42507             :             v_.push_back(v0);
   42508             :             v_.push_back(v1);
   42509             :             return (*this);
   42510             :          }
   42511             : 
   42512             :          inline function& vars(const std::string& v0,
   42513             :                                const std::string& v1,
   42514             :                                const std::string& v2)
   42515             :          {
   42516             :             v_.push_back(v0);
   42517             :             v_.push_back(v1);
   42518             :             v_.push_back(v2);
   42519             :             return (*this);
   42520             :          }
   42521             : 
   42522             :          inline function& vars(const std::string& v0,
   42523             :                                const std::string& v1,
   42524             :                                const std::string& v2,
   42525             :                                const std::string& v3)
   42526             :          {
   42527             :             v_.push_back(v0);
   42528             :             v_.push_back(v1);
   42529             :             v_.push_back(v2);
   42530             :             v_.push_back(v3);
   42531             :             return (*this);
   42532             :          }
   42533             : 
   42534             :          inline function& vars(const std::string& v0,
   42535             :                                const std::string& v1,
   42536             :                                const std::string& v2,
   42537             :                                const std::string& v3,
   42538             :                                const std::string& v4)
   42539             :          {
   42540             :             v_.push_back(v0);
   42541             :             v_.push_back(v1);
   42542             :             v_.push_back(v2);
   42543             :             v_.push_back(v3);
   42544             :             v_.push_back(v4);
   42545             :             return (*this);
   42546             :          }
   42547             : 
   42548             :          std::string name_;
   42549             :          std::string expression_;
   42550             :          std::deque<std::string> v_;
   42551             :       };
   42552             : 
   42553             :    private:
   42554             : 
   42555             :       struct base_func : public exprtk::ifunction<T>
   42556             :       {
   42557             :          typedef const T&                       type;
   42558             :          typedef exprtk::ifunction<T>     function_t;
   42559             :          typedef std::vector<T*>            varref_t;
   42560             :          typedef std::vector<T>                var_t;
   42561             :          typedef std::pair<T*,std::size_t> lvarref_t;
   42562             :          typedef std::vector<lvarref_t>    lvr_vec_t;
   42563             : 
   42564             :          using exprtk::ifunction<T>::operator();
   42565             : 
   42566         727 :          base_func(const std::size_t& pc = 0)
   42567             :          : exprtk::ifunction<T>(pc)
   42568         727 :          , local_var_stack_size(0)
   42569         727 :          , stack_depth(0)
   42570             :          {
   42571         727 :             v.resize(pc);
   42572         727 :          }
   42573             : 
   42574         727 :          virtual ~base_func()
   42575         727 :          {}
   42576             : 
   42577             :          #define exprtk_assign(Index) \
   42578             :          (*v[Index]) = v##Index;      \
   42579             : 
   42580    45706176 :          inline void update(const T& v0)
   42581             :          {
   42582    45706176 :             exprtk_assign(0)
   42583    45706176 :          }
   42584             : 
   42585      116833 :          inline void update(const T& v0, const T& v1)
   42586             :          {
   42587      116833 :             exprtk_assign(0) exprtk_assign(1)
   42588      116833 :          }
   42589             : 
   42590       12900 :          inline void update(const T& v0, const T& v1, const T& v2)
   42591             :          {
   42592       12900 :             exprtk_assign(0) exprtk_assign(1)
   42593       12900 :             exprtk_assign(2)
   42594       12900 :          }
   42595             : 
   42596        4264 :          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
   42597             :          {
   42598        4264 :             exprtk_assign(0) exprtk_assign(1)
   42599        4264 :             exprtk_assign(2) exprtk_assign(3)
   42600        4264 :          }
   42601             : 
   42602        1000 :          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
   42603             :          {
   42604        1000 :             exprtk_assign(0) exprtk_assign(1)
   42605        1000 :             exprtk_assign(2) exprtk_assign(3)
   42606        1000 :             exprtk_assign(4)
   42607        1000 :          }
   42608             : 
   42609         200 :          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
   42610             :          {
   42611         200 :             exprtk_assign(0) exprtk_assign(1)
   42612         200 :             exprtk_assign(2) exprtk_assign(3)
   42613         200 :             exprtk_assign(4) exprtk_assign(5)
   42614         200 :          }
   42615             : 
   42616             :          #ifdef exprtk_assign
   42617             :          #undef exprtk_assign
   42618             :          #endif
   42619             : 
   42620         727 :          inline function_t& setup(expression_t& expr)
   42621             :          {
   42622         727 :             expression = expr;
   42623             : 
   42624             :             typedef typename expression_t::control_block::local_data_list_t ldl_t;
   42625             : 
   42626         727 :             const ldl_t ldl = expr.local_data_list();
   42627             : 
   42628         727 :             std::vector<std::size_t> index_list;
   42629             : 
   42630        5043 :             for (std::size_t i = 0; i < ldl.size(); ++i)
   42631             :             {
   42632        4316 :                if (ldl[i].size)
   42633             :                {
   42634        2158 :                   index_list.push_back(i);
   42635             :                }
   42636             :             }
   42637             : 
   42638         727 :             std::size_t input_param_count = 0;
   42639             : 
   42640        2885 :             for (std::size_t i = 0; i < index_list.size(); ++i)
   42641             :             {
   42642        2158 :                const std::size_t index = index_list[i];
   42643             : 
   42644        2158 :                if (i < (index_list.size() - v.size()))
   42645             :                {
   42646          20 :                   lv.push_back(
   42647           0 :                         std::make_pair(
   42648          20 :                            reinterpret_cast<T*>(ldl[index].pointer),
   42649          20 :                            ldl[index].size));
   42650             : 
   42651          20 :                   local_var_stack_size += ldl[index].size;
   42652             :                }
   42653             :                else
   42654        2138 :                   v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
   42655             :             }
   42656             : 
   42657         727 :             clear_stack();
   42658             : 
   42659         727 :             return (*this);
   42660         727 :          }
   42661             : 
   42662    45841373 :          inline void pre()
   42663             :          {
   42664    45841373 :             if (stack_depth++)
   42665             :             {
   42666    45705335 :                if (!v.empty())
   42667             :                {
   42668    45705335 :                   var_t var_stack(v.size(),T(0));
   42669    45705335 :                   copy(v,var_stack);
   42670    45705335 :                   param_stack.push_back(var_stack);
   42671    45705335 :                }
   42672             : 
   42673    45705335 :                if (!lv.empty())
   42674             :                {
   42675        4950 :                   var_t local_var_stack(local_var_stack_size,T(0));
   42676        4950 :                   copy(lv,local_var_stack);
   42677        4950 :                   local_stack.push_back(local_var_stack);
   42678        4950 :                }
   42679             :             }
   42680    45841373 :          }
   42681             : 
   42682    45841373 :          inline void post()
   42683             :          {
   42684    45841373 :             if (--stack_depth)
   42685             :             {
   42686    45705335 :                if (!v.empty())
   42687             :                {
   42688    45705335 :                   copy(param_stack.back(),v);
   42689    45705335 :                   param_stack.pop_back();
   42690             :                }
   42691             : 
   42692    45705335 :                if (!lv.empty())
   42693             :                {
   42694        4950 :                   copy(local_stack.back(),lv);
   42695        4950 :                   local_stack.pop_back();
   42696             :                }
   42697             :             }
   42698    45841373 :          }
   42699             : 
   42700    45705335 :          void copy(const varref_t& src_v, var_t& dest_v)
   42701             :          {
   42702    91488223 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   42703             :             {
   42704    45782888 :                dest_v[i] = (*src_v[i]);
   42705             :             }
   42706    45705335 :          }
   42707             : 
   42708    45705335 :          void copy(const var_t& src_v, varref_t& dest_v)
   42709             :          {
   42710    91488223 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   42711             :             {
   42712    45782888 :                (*dest_v[i]) = src_v[i];
   42713             :             }
   42714    45705335 :          }
   42715             : 
   42716        4950 :          void copy(const lvr_vec_t& src_v, var_t& dest_v)
   42717             :          {
   42718        4950 :             typename var_t::iterator itr = dest_v.begin();
   42719             :             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
   42720             : 
   42721        9900 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   42722             :             {
   42723        4950 :                lvarref_t vr = src_v[i];
   42724             : 
   42725        4950 :                if (1 == vr.second)
   42726        4950 :                   *itr++ = (*vr.first);
   42727             :                else
   42728             :                {
   42729           0 :                   std::copy(vr.first, vr.first + vr.second, itr);
   42730           0 :                   itr += static_cast<diff_t>(vr.second);
   42731             :                }
   42732             :             }
   42733        4950 :          }
   42734             : 
   42735        4950 :          void copy(const var_t& src_v, lvr_vec_t& dest_v)
   42736             :          {
   42737        4950 :             typename var_t::const_iterator itr = src_v.begin();
   42738             :             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
   42739             : 
   42740        9900 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   42741             :             {
   42742        4950 :                lvarref_t vr = dest_v[i];
   42743             : 
   42744        4950 :                if (1 == vr.second)
   42745        4950 :                   (*vr.first) = *itr++;
   42746             :                else
   42747             :                {
   42748           0 :                   std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
   42749           0 :                   itr += static_cast<diff_t>(vr.second);
   42750             :                }
   42751             :             }
   42752        4950 :          }
   42753             : 
   42754         727 :          inline void clear_stack()
   42755             :          {
   42756        2865 :             for (std::size_t i = 0; i < v.size(); ++i)
   42757             :             {
   42758        2138 :                (*v[i]) = 0;
   42759             :             }
   42760         727 :          }
   42761             : 
   42762    45918873 :          inline virtual T value(expression_t& e)
   42763             :          {
   42764    45918873 :             return e.value();
   42765             :          }
   42766             : 
   42767             :          expression_t expression;
   42768             :          varref_t v;
   42769             :          lvr_vec_t lv;
   42770             :          std::size_t local_var_stack_size;
   42771             :          std::size_t stack_depth;
   42772             :          std::deque<var_t> param_stack;
   42773             :          std::deque<var_t> local_stack;
   42774             :       };
   42775             : 
   42776             :       typedef std::map<std::string,base_func*> funcparam_t;
   42777             : 
   42778             :       struct func_0param : public base_func
   42779             :       {
   42780             :          using exprtk::ifunction<T>::operator();
   42781             : 
   42782         101 :          func_0param() : base_func(0) {}
   42783             : 
   42784       77500 :          inline T operator() () exprtk_override
   42785             :          {
   42786       77500 :             return this->value(base_func::expression);
   42787             :          }
   42788             :       };
   42789             : 
   42790             :       typedef const T& type;
   42791             : 
   42792             :       template <typename BaseFuncType>
   42793             :       struct scoped_bft
   42794             :       {
   42795    45841373 :          explicit scoped_bft(BaseFuncType& bft)
   42796    45841373 :          : bft_(bft)
   42797             :          {
   42798    45841373 :             bft_.pre ();
   42799    45841373 :          }
   42800             : 
   42801    45841373 :         ~scoped_bft()
   42802             :          {
   42803    45841373 :             bft_.post();
   42804    45841373 :          }
   42805             : 
   42806             :          BaseFuncType& bft_;
   42807             : 
   42808             :       private:
   42809             : 
   42810             :          scoped_bft(const scoped_bft&) exprtk_delete;
   42811             :          scoped_bft& operator=(const scoped_bft&) exprtk_delete;
   42812             :       };
   42813             : 
   42814             :       struct func_1param : public base_func
   42815             :       {
   42816             :          using exprtk::ifunction<T>::operator();
   42817             : 
   42818         119 :          func_1param() : base_func(1) {}
   42819             : 
   42820    45706176 :          inline T operator() (type v0) exprtk_override
   42821             :          {
   42822    45706176 :             scoped_bft<func_1param> sb(*this);
   42823    45706176 :             base_func::update(v0);
   42824    91412352 :             return this->value(base_func::expression);
   42825    45706176 :          }
   42826             :       };
   42827             : 
   42828             :       struct func_2param : public base_func
   42829             :       {
   42830             :          using exprtk::ifunction<T>::operator();
   42831             : 
   42832         104 :          func_2param() : base_func(2) {}
   42833             : 
   42834      116833 :          inline T operator() (type v0, type v1) exprtk_override
   42835             :          {
   42836      116833 :             scoped_bft<func_2param> sb(*this);
   42837      116833 :             base_func::update(v0, v1);
   42838      233666 :             return this->value(base_func::expression);
   42839      116833 :          }
   42840             :       };
   42841             : 
   42842             :       struct func_3param : public base_func
   42843             :       {
   42844             :          using exprtk::ifunction<T>::operator();
   42845             : 
   42846         101 :          func_3param() : base_func(3) {}
   42847             : 
   42848       12900 :          inline T operator() (type v0, type v1, type v2) exprtk_override
   42849             :          {
   42850       12900 :             scoped_bft<func_3param> sb(*this);
   42851       12900 :             base_func::update(v0, v1, v2);
   42852       25800 :             return this->value(base_func::expression);
   42853       12900 :          }
   42854             :       };
   42855             : 
   42856             :       struct func_4param : public base_func
   42857             :       {
   42858             :          using exprtk::ifunction<T>::operator();
   42859             : 
   42860         102 :          func_4param() : base_func(4) {}
   42861             : 
   42862        4264 :          inline T operator() (type v0, type v1, type v2, type v3) exprtk_override
   42863             :          {
   42864        4264 :             scoped_bft<func_4param> sb(*this);
   42865        4264 :             base_func::update(v0, v1, v2, v3);
   42866        8528 :             return this->value(base_func::expression);
   42867        4264 :          }
   42868             :       };
   42869             : 
   42870             :       struct func_5param : public base_func
   42871             :       {
   42872             :          using exprtk::ifunction<T>::operator();
   42873             : 
   42874         100 :          func_5param() : base_func(5) {}
   42875             : 
   42876        1000 :          inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override
   42877             :          {
   42878        1000 :             scoped_bft<func_5param> sb(*this);
   42879        1000 :             base_func::update(v0, v1, v2, v3, v4);
   42880        2000 :             return this->value(base_func::expression);
   42881        1000 :          }
   42882             :       };
   42883             : 
   42884             :       struct func_6param : public base_func
   42885             :       {
   42886             :          using exprtk::ifunction<T>::operator();
   42887             : 
   42888         100 :          func_6param() : base_func(6) {}
   42889             : 
   42890         200 :          inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override
   42891             :          {
   42892         200 :             scoped_bft<func_6param> sb(*this);
   42893         200 :             base_func::update(v0, v1, v2, v3, v4, v5);
   42894         400 :             return this->value(base_func::expression);
   42895         200 :          }
   42896             :       };
   42897             : 
   42898           0 :       static T return_value(expression_t& e)
   42899             :       {
   42900             :          typedef exprtk::results_context<T> results_context_t;
   42901             :          typedef typename results_context_t::type_store_t type_t;
   42902             :          typedef typename type_t::scalar_view scalar_t;
   42903             : 
   42904           0 :          const T result = e.value();
   42905             : 
   42906           0 :          if (e.return_invoked())
   42907             :          {
   42908             :             // Due to the post compilation checks, it can be safely
   42909             :             // assumed that there will be at least one parameter
   42910             :             // and that the first parameter will always be scalar.
   42911           0 :             return scalar_t(e.results()[0])();
   42912             :          }
   42913             : 
   42914           0 :          return result;
   42915             :       }
   42916             : 
   42917             :       #define def_fp_retval(N)                                            \
   42918             :       struct func_##N##param_retval exprtk_final : public func_##N##param \
   42919             :       {                                                                   \
   42920             :          inline T value(expression_t& e) exprtk_override                  \
   42921             :          {                                                                \
   42922             :             return return_value(e);                                       \
   42923             :          }                                                                \
   42924             :       };                                                                  \
   42925             : 
   42926           0 :       def_fp_retval(0)
   42927           0 :       def_fp_retval(1)
   42928           0 :       def_fp_retval(2)
   42929           0 :       def_fp_retval(3)
   42930           0 :       def_fp_retval(4)
   42931           0 :       def_fp_retval(5)
   42932           0 :       def_fp_retval(6)
   42933             : 
   42934             :       #undef def_fp_retval
   42935             : 
   42936             :       template <typename Allocator,
   42937             :                 template <typename, typename> class Sequence>
   42938         727 :       inline bool add(const std::string& name,
   42939             :                       const std::string& expression,
   42940             :                       const Sequence<std::string,Allocator>& var_list,
   42941             :                       const bool override = false)
   42942             :       {
   42943         727 :          const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
   42944             : 
   42945         727 :          if (expr_map_.end() != itr)
   42946             :          {
   42947           0 :             if (!override)
   42948             :             {
   42949             :                exprtk_debug(("Compositor error(add): function '%s' already defined\n",
   42950             :                              name.c_str()));
   42951             : 
   42952           0 :                return false;
   42953             :             }
   42954             : 
   42955           0 :             remove(name, var_list.size());
   42956             :          }
   42957             : 
   42958         727 :          if (compile_expression(name, expression, var_list))
   42959             :          {
   42960         727 :             const std::size_t n = var_list.size();
   42961             : 
   42962         727 :             fp_map_[n][name]->setup(expr_map_[name]);
   42963             : 
   42964         727 :             return true;
   42965             :          }
   42966             :          else
   42967             :          {
   42968             :             exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
   42969             :                           name.c_str()));
   42970             : 
   42971           0 :             return false;
   42972             :          }
   42973             :       }
   42974             : 
   42975             :    public:
   42976             : 
   42977         103 :       function_compositor()
   42978         103 :       : parser_(settings_t::default_compile_all_opts +
   42979             :                 settings_t::e_disable_zero_return)
   42980         206 :       , fp_map_(7)
   42981         103 :       , load_variables_(false)
   42982         309 :       , load_vectors_(false)
   42983         103 :       {}
   42984             : 
   42985           3 :       explicit function_compositor(const symbol_table_t& st)
   42986           3 :       : symbol_table_(st)
   42987           3 :       , parser_(settings_t::default_compile_all_opts +
   42988             :                 settings_t::e_disable_zero_return)
   42989           6 :       , fp_map_(7)
   42990           3 :       , load_variables_(false)
   42991           6 :       , load_vectors_(false)
   42992           3 :       {}
   42993             : 
   42994         106 :      ~function_compositor()
   42995             :       {
   42996         106 :          clear();
   42997         106 :       }
   42998             : 
   42999         103 :       inline symbol_table_t& symbol_table()
   43000             :       {
   43001         103 :          return symbol_table_;
   43002             :       }
   43003             : 
   43004             :       inline const symbol_table_t& symbol_table() const
   43005             :       {
   43006             :          return symbol_table_;
   43007             :       }
   43008             : 
   43009             :       inline void add_auxiliary_symtab(symbol_table_t& symtab)
   43010             :       {
   43011             :          auxiliary_symtab_list_.push_back(&symtab);
   43012             :       }
   43013             : 
   43014             :       void load_variables(const bool load = true)
   43015             :       {
   43016             :          load_variables_ = load;
   43017             :       }
   43018             : 
   43019             :       void load_vectors(const bool load = true)
   43020             :       {
   43021             :          load_vectors_ = load;
   43022             :       }
   43023             : 
   43024         106 :       void clear()
   43025             :       {
   43026         106 :          symbol_table_.clear();
   43027         106 :          expr_map_    .clear();
   43028             : 
   43029         848 :          for (std::size_t i = 0; i < fp_map_.size(); ++i)
   43030             :          {
   43031         742 :             typename funcparam_t::iterator itr = fp_map_[i].begin();
   43032         742 :             typename funcparam_t::iterator end = fp_map_[i].end  ();
   43033             : 
   43034        1469 :             while (itr != end)
   43035             :             {
   43036         727 :                delete itr->second;
   43037         727 :                ++itr;
   43038             :             }
   43039             : 
   43040         742 :             fp_map_[i].clear();
   43041             :          }
   43042         106 :       }
   43043             : 
   43044         727 :       inline bool add(const function& f, const bool override = false)
   43045             :       {
   43046         727 :          return add(f.name_, f.expression_, f.v_,override);
   43047             :       }
   43048             : 
   43049             :       inline std::string error() const
   43050             :       {
   43051             :          if (!error_list_.empty())
   43052             :          {
   43053             :             return error_list_[0].diagnostic;
   43054             :          }
   43055             :          else
   43056             :             return std::string("No Error");
   43057             :       }
   43058             : 
   43059             :       inline std::size_t error_count() const
   43060             :       {
   43061             :          return error_list_.size();
   43062             :       }
   43063             : 
   43064             :       inline parser_error::type get_error(const std::size_t& index) const
   43065             :       {
   43066             :          if (index < error_list_.size())
   43067             :          {
   43068             :             return error_list_[index];
   43069             :          }
   43070             : 
   43071             :          throw std::invalid_argument("compositor::get_error() - Invalid error index specified");
   43072             :       }
   43073             : 
   43074             :    private:
   43075             : 
   43076             :       template <typename Allocator,
   43077             :                 template <typename, typename> class Sequence>
   43078         727 :       bool compile_expression(const std::string& name,
   43079             :                               const std::string& expression,
   43080             :                               const Sequence<std::string,Allocator>& input_var_list,
   43081             :                               bool  return_present = false)
   43082             :       {
   43083         727 :          expression_t compiled_expression;
   43084         727 :          symbol_table_t local_symbol_table;
   43085             : 
   43086         727 :          local_symbol_table.load_from(symbol_table_);
   43087         727 :          local_symbol_table.add_constants();
   43088             : 
   43089         727 :          if (load_variables_)
   43090             :          {
   43091           0 :             local_symbol_table.load_variables_from(symbol_table_);
   43092             :          }
   43093             : 
   43094         727 :          if (load_vectors_)
   43095             :          {
   43096           0 :             local_symbol_table.load_vectors_from(symbol_table_);
   43097             :          }
   43098             : 
   43099         727 :          error_list_.clear();
   43100             : 
   43101         727 :          if (!valid(name,input_var_list.size()))
   43102             :          {
   43103           0 :             parser_error::type error =
   43104             :                parser_error::make_error(
   43105             :                   parser_error::e_parser,
   43106           0 :                   lexer::token(),
   43107             :                   "ERR274 - Function '" + name + "' is an invalid overload",
   43108             :                   exprtk_error_location);
   43109             : 
   43110           0 :             error_list_.push_back(error);
   43111           0 :             return false;
   43112           0 :          }
   43113             : 
   43114        2181 :          if (!forward(name,
   43115         727 :                       input_var_list.size(),
   43116             :                       local_symbol_table,
   43117             :                       return_present))
   43118           0 :             return false;
   43119             : 
   43120         727 :          compiled_expression.register_symbol_table(local_symbol_table);
   43121             : 
   43122         727 :          for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
   43123             :          {
   43124           0 :             compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
   43125             :          }
   43126             : 
   43127         727 :          std::string mod_expression;
   43128             : 
   43129        2865 :          for (std::size_t i = 0; i < input_var_list.size(); ++i)
   43130             :          {
   43131        2138 :             mod_expression += " var " + input_var_list[i] + "{};\n";
   43132             :          }
   43133             : 
   43134         727 :          if (
   43135         727 :               ('{' == details::front(expression)) &&
   43136           0 :               ('}' == details::back (expression))
   43137             :             )
   43138           0 :             mod_expression += "~" + expression + ";";
   43139             :          else
   43140         727 :             mod_expression += "~{" + expression + "};";
   43141             : 
   43142         727 :          if (!parser_.compile(mod_expression,compiled_expression))
   43143             :          {
   43144             :             exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str()));
   43145             :             exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str()));
   43146             : 
   43147           0 :             remove(name,input_var_list.size());
   43148             : 
   43149           0 :             for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index)
   43150             :             {
   43151           0 :                error_list_.push_back(parser_.get_error(err_index));
   43152             :             }
   43153             : 
   43154           0 :             return false;
   43155             :          }
   43156             : 
   43157         727 :          if (!return_present && parser_.dec().return_present())
   43158             :          {
   43159           0 :             remove(name,input_var_list.size());
   43160           0 :             return compile_expression(name, expression, input_var_list, true);
   43161             :          }
   43162             : 
   43163             :          // Make sure every return point has a scalar as its first parameter
   43164         727 :          if (parser_.dec().return_present())
   43165             :          {
   43166             :             typedef std::vector<std::string> str_list_t;
   43167             : 
   43168           0 :             str_list_t ret_param_list = parser_.dec().return_param_type_list();
   43169             : 
   43170           0 :             for (std::size_t i = 0; i < ret_param_list.size(); ++i)
   43171             :             {
   43172           0 :                const std::string& params = ret_param_list[i];
   43173             : 
   43174           0 :                if (params.empty() || ('T' != params[0]))
   43175             :                {
   43176             :                   exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
   43177             :                                 name.c_str()));
   43178             : 
   43179           0 :                   remove(name,input_var_list.size());
   43180             : 
   43181           0 :                   return false;
   43182             :                }
   43183             :             }
   43184           0 :          }
   43185             : 
   43186         727 :          expr_map_[name] = compiled_expression;
   43187             : 
   43188         727 :          exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
   43189             : 
   43190         727 :          if (symbol_table_.add_function(name,ifunc))
   43191         727 :             return true;
   43192             :          else
   43193             :          {
   43194             :             exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
   43195             :                           name.c_str()));
   43196           0 :             return false;
   43197             :          }
   43198         727 :       }
   43199             : 
   43200         727 :       inline bool symbol_used(const std::string& symbol) const
   43201             :       {
   43202             :          return (
   43203         727 :                   symbol_table_.is_variable       (symbol) ||
   43204         727 :                   symbol_table_.is_stringvar      (symbol) ||
   43205         727 :                   symbol_table_.is_function       (symbol) ||
   43206        2181 :                   symbol_table_.is_vector         (symbol) ||
   43207         727 :                   symbol_table_.is_vararg_function(symbol)
   43208         727 :                 );
   43209             :       }
   43210             : 
   43211         727 :       inline bool valid(const std::string& name,
   43212             :                         const std::size_t& arg_count) const
   43213             :       {
   43214         727 :          if (arg_count > 6)
   43215           0 :             return false;
   43216         727 :          else if (symbol_used(name))
   43217           0 :             return false;
   43218         727 :          else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
   43219           0 :             return false;
   43220             :          else
   43221         727 :             return true;
   43222             :       }
   43223             : 
   43224         727 :       inline bool forward(const std::string& name,
   43225             :                           const std::size_t& arg_count,
   43226             :                           symbol_table_t& sym_table,
   43227             :                           const bool ret_present = false)
   43228             :       {
   43229         727 :          switch (arg_count)
   43230             :          {
   43231             :             #define case_stmt(N)                                     \
   43232             :             case N : (fp_map_[arg_count])[name] =                    \
   43233             :                      (!ret_present) ? static_cast<base_func*>        \
   43234             :                                       (new func_##N##param) :        \
   43235             :                                       static_cast<base_func*>        \
   43236             :                                       (new func_##N##param_retval) ; \
   43237             :                      break;                                          \
   43238             : 
   43239         324 :             case_stmt(0) case_stmt(1) case_stmt(2)
   43240         303 :             case_stmt(3) case_stmt(4) case_stmt(5)
   43241         100 :             case_stmt(6)
   43242             :             #undef case_stmt
   43243             :          }
   43244             : 
   43245         727 :          exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
   43246             : 
   43247         727 :          return sym_table.add_function(name,ifunc);
   43248             :       }
   43249             : 
   43250           0 :       inline void remove(const std::string& name, const std::size_t& arg_count)
   43251             :       {
   43252           0 :          if (arg_count > 6)
   43253           0 :             return;
   43254             : 
   43255           0 :          const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
   43256             : 
   43257           0 :          if (expr_map_.end() != em_itr)
   43258             :          {
   43259           0 :             expr_map_.erase(em_itr);
   43260             :          }
   43261             : 
   43262           0 :          const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
   43263             : 
   43264           0 :          if (fp_map_[arg_count].end() != fp_itr)
   43265             :          {
   43266           0 :             delete fp_itr->second;
   43267           0 :             fp_map_[arg_count].erase(fp_itr);
   43268             :          }
   43269             : 
   43270           0 :          symbol_table_.remove_function(name);
   43271             :       }
   43272             : 
   43273             :    private:
   43274             : 
   43275             :       symbol_table_t symbol_table_;
   43276             :       parser_t parser_;
   43277             :       std::map<std::string,expression_t> expr_map_;
   43278             :       std::vector<funcparam_t> fp_map_;
   43279             :       std::vector<symbol_table_t*> auxiliary_symtab_list_;
   43280             :       std::deque<parser_error::type> error_list_;
   43281             :       bool load_variables_;
   43282             :       bool load_vectors_;
   43283             :    }; // class function_compositor
   43284             : 
   43285             : } // namespace exprtk
   43286             : 
   43287             : #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
   43288             : #   ifndef NOMINMAX
   43289             : #      define NOMINMAX
   43290             : #   endif
   43291             : #   ifndef WIN32_LEAN_AND_MEAN
   43292             : #      define WIN32_LEAN_AND_MEAN
   43293             : #   endif
   43294             : #   include <windows.h>
   43295             : #   include <ctime>
   43296             : #else
   43297             : #   include <ctime>
   43298             : #   include <sys/time.h>
   43299             : #   include <sys/types.h>
   43300             : #endif
   43301             : 
   43302             : namespace exprtk
   43303             : {
   43304             :    class timer
   43305             :    {
   43306             :    public:
   43307             : 
   43308             :       #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
   43309             :       timer()
   43310             :       : in_use_(false)
   43311             :       , start_time_{ 0 }
   43312             :       , stop_time_ { 0 }
   43313             :       {
   43314             :          QueryPerformanceFrequency(&clock_frequency_);
   43315             :       }
   43316             : 
   43317             :       inline void start()
   43318             :       {
   43319             :          in_use_ = true;
   43320             :          QueryPerformanceCounter(&start_time_);
   43321             :       }
   43322             : 
   43323             :       inline void stop()
   43324             :       {
   43325             :          QueryPerformanceCounter(&stop_time_);
   43326             :          in_use_ = false;
   43327             :       }
   43328             : 
   43329             :       inline double time() const
   43330             :       {
   43331             :          return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
   43332             :       }
   43333             : 
   43334             :       #else
   43335             : 
   43336          23 :       timer()
   43337          23 :       : in_use_(false)
   43338             :       {
   43339          23 :          start_time_.tv_sec  = 0;
   43340          23 :          start_time_.tv_usec = 0;
   43341             : 
   43342          23 :          stop_time_.tv_sec   = 0;
   43343          23 :          stop_time_.tv_usec  = 0;
   43344          23 :       }
   43345             : 
   43346          23 :       inline void start()
   43347             :       {
   43348          23 :          in_use_ = true;
   43349          23 :          gettimeofday(&start_time_,0);
   43350          23 :       }
   43351             : 
   43352          23 :       inline void stop()
   43353             :       {
   43354          23 :          gettimeofday(&stop_time_, 0);
   43355          23 :          in_use_ = false;
   43356          23 :       }
   43357             : 
   43358          23 :       inline unsigned long long int usec_time() const
   43359             :       {
   43360          23 :          if (!in_use_)
   43361             :          {
   43362          23 :             if (stop_time_.tv_sec >= start_time_.tv_sec)
   43363             :             {
   43364          23 :                return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec  - start_time_.tv_sec ) +
   43365          23 :                                    static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
   43366             :             }
   43367             :             else
   43368           0 :                return std::numeric_limits<details::_uint64_t>::max();
   43369             :          }
   43370             :          else
   43371           0 :             return std::numeric_limits<details::_uint64_t>::max();
   43372             :       }
   43373             : 
   43374          23 :       inline double time() const
   43375             :       {
   43376          23 :          return usec_time() * 0.000001;
   43377             :       }
   43378             : 
   43379             :       #endif
   43380             : 
   43381             :       inline bool in_use() const
   43382             :       {
   43383             :          return in_use_;
   43384             :       }
   43385             : 
   43386             :    private:
   43387             : 
   43388             :       bool in_use_;
   43389             : 
   43390             :       #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
   43391             :          LARGE_INTEGER start_time_;
   43392             :          LARGE_INTEGER stop_time_;
   43393             :          LARGE_INTEGER clock_frequency_;
   43394             :       #else
   43395             :          struct timeval start_time_;
   43396             :          struct timeval stop_time_;
   43397             :       #endif
   43398             :    };
   43399             : 
   43400             :    template <typename T>
   43401             :    struct type_defs
   43402             :    {
   43403             :       typedef symbol_table<T>         symbol_table_t;
   43404             :       typedef expression<T>           expression_t;
   43405             :       typedef parser<T>               parser_t;
   43406             :       typedef parser_error::type      error_t;
   43407             :       typedef function_compositor<T>  compositor_t;
   43408             :       typedef typename compositor_t::function function_t;
   43409             :    };
   43410             : 
   43411             : } // namespace exprtk
   43412             : 
   43413             : #ifndef exprtk_disable_rtl_io
   43414             : namespace exprtk
   43415             : {
   43416             :    namespace rtl { namespace io { namespace details
   43417             :    {
   43418             :       template <typename T>
   43419           0 :       inline void print_type(const std::string& fmt,
   43420             :                              const T v,
   43421             :                              exprtk::details::numeric::details::real_type_tag)
   43422             :       {
   43423             :          #if defined(__clang__)
   43424             :             #pragma clang diagnostic push
   43425             :             #pragma clang diagnostic ignored "-Wformat-nonliteral"
   43426             :          #elif defined(__GNUC__) || defined(__GNUG__)
   43427             :             #pragma GCC diagnostic push
   43428             :             #pragma GCC diagnostic ignored "-Wformat-nonliteral"
   43429             :          #elif defined(_MSC_VER)
   43430             :          #endif
   43431             : 
   43432           0 :          printf(fmt.c_str(), v);
   43433             : 
   43434             :          #if defined(__clang__)
   43435             :             #pragma clang diagnostic pop
   43436             :          #elif defined(__GNUC__) || defined(__GNUG__)
   43437             :             #pragma GCC diagnostic pop
   43438             :          #elif defined(_MSC_VER)
   43439             :          #endif
   43440           0 :       }
   43441             : 
   43442             :       template <typename T>
   43443             :       struct print_impl
   43444             :       {
   43445             :          typedef typename igeneric_function<T>::generic_type generic_type;
   43446             :          typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
   43447             :          typedef typename generic_type::scalar_view scalar_t;
   43448             :          typedef typename generic_type::vector_view vector_t;
   43449             :          typedef typename generic_type::string_view string_t;
   43450             :          typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
   43451             : 
   43452           0 :          static void process(const std::string& scalar_format, parameter_list_t parameters)
   43453             :          {
   43454           0 :             for (std::size_t i = 0; i < parameters.size(); ++i)
   43455             :             {
   43456           0 :                generic_type& gt = parameters[i];
   43457             : 
   43458           0 :                switch (gt.type)
   43459             :                {
   43460           0 :                   case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
   43461           0 :                                                 break;
   43462             : 
   43463           0 :                   case generic_type::e_vector : print(scalar_format,vector_t(gt));
   43464           0 :                                                 break;
   43465             : 
   43466           0 :                   case generic_type::e_string : print(string_t(gt));
   43467           0 :                                                 break;
   43468             : 
   43469           0 :                   default                     : continue;
   43470             :                }
   43471             :             }
   43472           0 :          }
   43473             : 
   43474           0 :          static inline void print(const std::string& scalar_format, const scalar_t& s)
   43475             :          {
   43476           0 :             print_type(scalar_format,s(),num_type());
   43477           0 :          }
   43478             : 
   43479           0 :          static inline void print(const std::string& scalar_format, const vector_t& v)
   43480             :          {
   43481           0 :             for (std::size_t i = 0; i < v.size(); ++i)
   43482             :             {
   43483           0 :                print_type(scalar_format,v[i],num_type());
   43484             : 
   43485           0 :                if ((i + 1) < v.size())
   43486           0 :                   printf(" ");
   43487             :             }
   43488           0 :          }
   43489             : 
   43490           0 :          static inline void print(const string_t& s)
   43491             :          {
   43492           0 :             printf("%s",to_str(s).c_str());
   43493           0 :          }
   43494             :       };
   43495             : 
   43496             :    } // namespace exprtk::rtl::io::details
   43497             : 
   43498             :    template <typename T>
   43499             :    struct print exprtk_final : public exprtk::igeneric_function<T>
   43500             :    {
   43501             :       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
   43502             : 
   43503             :       using exprtk::igeneric_function<T>::operator();
   43504             : 
   43505          30 :       explicit print(const std::string& scalar_format = "%10.5f")
   43506          90 :       : scalar_format_(scalar_format)
   43507             :       {
   43508          30 :          exprtk::enable_zero_parameters(*this);
   43509          30 :       }
   43510             : 
   43511           0 :       inline T operator() (parameter_list_t parameters) exprtk_override
   43512             :       {
   43513           0 :          details::print_impl<T>::process(scalar_format_,parameters);
   43514           0 :          return T(0);
   43515             :       }
   43516             : 
   43517             :       std::string scalar_format_;
   43518             :    };
   43519             : 
   43520             :    template <typename T>
   43521             :    struct println exprtk_final : public exprtk::igeneric_function<T>
   43522             :    {
   43523             :       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
   43524             : 
   43525             :       using exprtk::igeneric_function<T>::operator();
   43526             : 
   43527          30 :       explicit println(const std::string& scalar_format = "%10.5f")
   43528          90 :       : scalar_format_(scalar_format)
   43529             :       {
   43530          30 :          exprtk::enable_zero_parameters(*this);
   43531          30 :       }
   43532             : 
   43533           0 :       inline T operator() (parameter_list_t parameters) exprtk_override
   43534             :       {
   43535           0 :          details::print_impl<T>::process(scalar_format_,parameters);
   43536           0 :          printf("\n");
   43537           0 :          return T(0);
   43538             :       }
   43539             : 
   43540             :       std::string scalar_format_;
   43541             :    };
   43542             : 
   43543             :    template <typename T>
   43544             :    struct package
   43545             :    {
   43546             :       print  <T> p;
   43547             :       println<T> pl;
   43548             : 
   43549          30 :       bool register_package(exprtk::symbol_table<T>& symtab)
   43550             :       {
   43551             :          #define exprtk_register_function(FunctionName, FunctionType)             \
   43552             :          if (!symtab.add_function(FunctionName,FunctionType))                     \
   43553             :          {                                                                        \
   43554             :             exprtk_debug((                                                        \
   43555             :               "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
   43556             :               FunctionName));                                                     \
   43557             :             return false;                                                         \
   43558             :          }                                                                        \
   43559             : 
   43560          90 :          exprtk_register_function("print"  , p )
   43561          90 :          exprtk_register_function("println", pl)
   43562             :          #undef exprtk_register_function
   43563             : 
   43564          30 :          return true;
   43565             :       }
   43566             :    };
   43567             : 
   43568             :    } // namespace exprtk::rtl::io
   43569             :    } // namespace exprtk::rtl
   43570             : }    // namespace exprtk
   43571             : #endif
   43572             : 
   43573             : #ifndef exprtk_disable_rtl_io_file
   43574             : #include <fstream>
   43575             : namespace exprtk
   43576             : {
   43577             :    namespace rtl { namespace io { namespace file { namespace details
   43578             :    {
   43579             :       using ::exprtk::details::char_ptr;
   43580             :       using ::exprtk::details::char_cptr;
   43581             : 
   43582             :       enum file_mode
   43583             :       {
   43584             :          e_error = 0,
   43585             :          e_read  = 1,
   43586             :          e_write = 2,
   43587             :          e_rdwrt = 4
   43588             :       };
   43589             : 
   43590             :       struct file_descriptor
   43591             :       {
   43592             :          file_descriptor(const std::string& fname, const std::string& access)
   43593             :          : stream_ptr(0)
   43594             :          , mode(get_file_mode(access))
   43595             :          , file_name(fname)
   43596             :          {}
   43597             : 
   43598             :          void*       stream_ptr;
   43599             :          file_mode   mode;
   43600             :          std::string file_name;
   43601             : 
   43602             :          bool open()
   43603             :          {
   43604             :             if (e_read == mode)
   43605             :             {
   43606             :                std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
   43607             : 
   43608             :                if (!(*stream))
   43609             :                {
   43610             :                   file_name.clear();
   43611             :                   delete stream;
   43612             : 
   43613             :                   return false;
   43614             :                }
   43615             : 
   43616             :                stream_ptr = stream;
   43617             : 
   43618             :                return true;
   43619             :             }
   43620             :             else if (e_write == mode)
   43621             :             {
   43622             :                std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
   43623             : 
   43624             :                if (!(*stream))
   43625             :                {
   43626             :                   file_name.clear();
   43627             :                   delete stream;
   43628             : 
   43629             :                   return false;
   43630             :                }
   43631             : 
   43632             :                stream_ptr = stream;
   43633             : 
   43634             :                return true;
   43635             :             }
   43636             :             else if (e_rdwrt == mode)
   43637             :             {
   43638             :                std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
   43639             : 
   43640             :                if (!(*stream))
   43641             :                {
   43642             :                   file_name.clear();
   43643             :                   delete stream;
   43644             : 
   43645             :                   return false;
   43646             :                }
   43647             : 
   43648             :                stream_ptr = stream;
   43649             : 
   43650             :                return true;
   43651             :             }
   43652             : 
   43653             :             return false;
   43654             :          }
   43655             : 
   43656             :          template <typename Stream, typename Ptr>
   43657             :          void close(Ptr& p)
   43658             :          {
   43659             :             Stream* stream = reinterpret_cast<Stream*>(p);
   43660             :             stream->close();
   43661             :             delete stream;
   43662             :             p = reinterpret_cast<Ptr>(0);
   43663             :          }
   43664             : 
   43665             :          bool close()
   43666             :          {
   43667             :             switch (mode)
   43668             :             {
   43669             :                case e_read  : close<std::ifstream>(stream_ptr);
   43670             :                               break;
   43671             : 
   43672             :                case e_write : close<std::ofstream>(stream_ptr);
   43673             :                               break;
   43674             : 
   43675             :                case e_rdwrt : close<std::fstream> (stream_ptr);
   43676             :                               break;
   43677             : 
   43678             :                default      : return false;
   43679             :             }
   43680             : 
   43681             :             return true;
   43682             :          }
   43683             : 
   43684             :          template <typename View>
   43685             :          bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
   43686             :          {
   43687             :             switch (mode)
   43688             :             {
   43689             :                case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
   43690             :                                  write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
   43691             :                               break;
   43692             : 
   43693             :                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
   43694             :                                  write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
   43695             :                               break;
   43696             : 
   43697             :                default      : return false;
   43698             :             }
   43699             : 
   43700             :             return true;
   43701             :          }
   43702             : 
   43703             :          template <typename View>
   43704             :          bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
   43705             :          {
   43706             :             switch (mode)
   43707             :             {
   43708             :                case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
   43709             :                                  read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
   43710             :                               break;
   43711             : 
   43712             :                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
   43713             :                                  read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
   43714             :                               break;
   43715             : 
   43716             :                default      : return false;
   43717             :             }
   43718             : 
   43719             :             return true;
   43720             :          }
   43721             : 
   43722             :          bool getline(std::string& s)
   43723             :          {
   43724             :             switch (mode)
   43725             :             {
   43726             :                case e_read  : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
   43727             :                case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
   43728             :                default      : return false;
   43729             :             }
   43730             :          }
   43731             : 
   43732             :          bool eof() const
   43733             :          {
   43734             :             switch (mode)
   43735             :             {
   43736             :                case e_read  : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
   43737             :                case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
   43738             :                case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
   43739             :                default      : return true;
   43740             :             }
   43741             :          }
   43742             : 
   43743             :          file_mode get_file_mode(const std::string& access) const
   43744             :          {
   43745             :             if (access.empty() || access.size() > 2)
   43746             :                return e_error;
   43747             : 
   43748             :             std::size_t w_cnt = 0;
   43749             :             std::size_t r_cnt = 0;
   43750             : 
   43751             :             for (std::size_t i = 0; i < access.size(); ++i)
   43752             :             {
   43753             :                switch (std::tolower(access[i]))
   43754             :                {
   43755             :                   case 'r' : r_cnt++; break;
   43756             :                   case 'w' : w_cnt++; break;
   43757             :                   default  : return e_error;
   43758             :                }
   43759             :             }
   43760             : 
   43761             :             if ((0 == r_cnt) && (0 == w_cnt))
   43762             :                return e_error;
   43763             :             else if ((r_cnt > 1) || (w_cnt > 1))
   43764             :                return e_error;
   43765             :             else if ((1 == r_cnt) && (1 == w_cnt))
   43766             :                return e_rdwrt;
   43767             :             else if (1 == r_cnt)
   43768             :                return e_read;
   43769             :             else
   43770             :                return e_write;
   43771             :          }
   43772             :       };
   43773             : 
   43774             :       template <typename T>
   43775             :       file_descriptor* make_handle(T v)
   43776             :       {
   43777             :          const std::size_t fd_size    = sizeof(details::file_descriptor*);
   43778             :          details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
   43779             : 
   43780             :          std::memcpy(reinterpret_cast<char_ptr >(&fd),
   43781             :                      reinterpret_cast<char_cptr>(&v ),
   43782             :                      fd_size);
   43783             :          return fd;
   43784             :       }
   43785             : 
   43786             :       template <typename T>
   43787             :       void perform_check()
   43788             :       {
   43789             :          #ifdef _MSC_VER
   43790             :          #pragma warning(push)
   43791             :          #pragma warning(disable: 4127)
   43792             :          #endif
   43793             :          if (sizeof(T) < sizeof(void*))
   43794             :          {
   43795             :             throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
   43796             :          }
   43797             :          #ifdef _MSC_VER
   43798             :          #pragma warning(pop)
   43799             :          #endif
   43800             :          assert(sizeof(T) <= sizeof(void*));
   43801             :       }
   43802             : 
   43803             :    } // namespace exprtk::rtl::io::file::details
   43804             : 
   43805             :    template <typename T>
   43806             :    class open exprtk_final : public exprtk::igeneric_function<T>
   43807             :    {
   43808             :    public:
   43809             : 
   43810             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43811             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43812             :       typedef typename igfun_t::generic_type        generic_type;
   43813             :       typedef typename generic_type::string_view    string_t;
   43814             : 
   43815             :       using igfun_t::operator();
   43816             : 
   43817             :       open()
   43818             :       : exprtk::igeneric_function<T>("S|SS")
   43819             :       { details::perform_check<T>(); }
   43820             : 
   43821             :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43822             :       {
   43823             :          const std::string file_name = to_str(string_t(parameters[0]));
   43824             : 
   43825             :          if (file_name.empty())
   43826             :          {
   43827             :             return T(0);
   43828             :          }
   43829             : 
   43830             :          if ((1 == ps_index) && (0 == string_t(parameters[1]).size()))
   43831             :          {
   43832             :             return T(0);
   43833             :          }
   43834             : 
   43835             :          const std::string access =
   43836             :             (0 == ps_index) ? "r" : to_str(string_t(parameters[1]));
   43837             : 
   43838             :          details::file_descriptor* fd = new details::file_descriptor(file_name,access);
   43839             : 
   43840             :          if (fd->open())
   43841             :          {
   43842             :             T t = T(0);
   43843             : 
   43844             :             const std::size_t fd_size = sizeof(details::file_descriptor*);
   43845             : 
   43846             :             std::memcpy(reinterpret_cast<char*>(&t ),
   43847             :                         reinterpret_cast<char*>(&fd),
   43848             :                         fd_size);
   43849             :             return t;
   43850             :          }
   43851             :          else
   43852             :          {
   43853             :             delete fd;
   43854             :             return T(0);
   43855             :          }
   43856             :       }
   43857             :    };
   43858             : 
   43859             :    template <typename T>
   43860             :    struct close exprtk_final : public exprtk::ifunction<T>
   43861             :    {
   43862             :       using exprtk::ifunction<T>::operator();
   43863             : 
   43864             :       close()
   43865             :       : exprtk::ifunction<T>(1)
   43866             :       { details::perform_check<T>(); }
   43867             : 
   43868             :       inline T operator() (const T& v) exprtk_override
   43869             :       {
   43870             :          details::file_descriptor* fd = details::make_handle(v);
   43871             : 
   43872             :          if (!fd->close())
   43873             :             return T(0);
   43874             : 
   43875             :          delete fd;
   43876             : 
   43877             :          return T(1);
   43878             :       }
   43879             :    };
   43880             : 
   43881             :    template <typename T>
   43882             :    class write exprtk_final : public exprtk::igeneric_function<T>
   43883             :    {
   43884             :    public:
   43885             : 
   43886             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43887             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43888             :       typedef typename igfun_t::generic_type        generic_type;
   43889             :       typedef typename generic_type::string_view    string_t;
   43890             :       typedef typename generic_type::scalar_view    scalar_t;
   43891             :       typedef typename generic_type::vector_view    vector_t;
   43892             : 
   43893             :       using igfun_t::operator();
   43894             : 
   43895             :       write()
   43896             :       : igfun_t("TS|TST|TV|TVT")
   43897             :       { details::perform_check<T>(); }
   43898             : 
   43899             :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43900             :       {
   43901             :          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
   43902             : 
   43903             :          switch (ps_index)
   43904             :          {
   43905             :             case 0  : {
   43906             :                          const string_t buffer(parameters[1]);
   43907             :                          const std::size_t amount = buffer.size();
   43908             :                          return T(fd->write(buffer, amount) ? 1 : 0);
   43909             :                       }
   43910             : 
   43911             :             case 1  : {
   43912             :                          const string_t buffer(parameters[1]);
   43913             :                          const std::size_t amount =
   43914             :                                   std::min(buffer.size(),
   43915             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   43916             :                          return T(fd->write(buffer, amount) ? 1 : 0);
   43917             :                       }
   43918             : 
   43919             :             case 2  : {
   43920             :                          const vector_t vec(parameters[1]);
   43921             :                          const std::size_t amount = vec.size();
   43922             :                          return T(fd->write(vec, amount) ? 1 : 0);
   43923             :                       }
   43924             : 
   43925             :             case 3  : {
   43926             :                          const vector_t vec(parameters[1]);
   43927             :                          const std::size_t amount =
   43928             :                                   std::min(vec.size(),
   43929             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   43930             :                          return T(fd->write(vec, amount) ? 1 : 0);
   43931             :                       }
   43932             :          }
   43933             : 
   43934             :          return T(0);
   43935             :       }
   43936             :    };
   43937             : 
   43938             :    template <typename T>
   43939             :    class read exprtk_final : public exprtk::igeneric_function<T>
   43940             :    {
   43941             :    public:
   43942             : 
   43943             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43944             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43945             :       typedef typename igfun_t::generic_type        generic_type;
   43946             :       typedef typename generic_type::string_view    string_t;
   43947             :       typedef typename generic_type::scalar_view    scalar_t;
   43948             :       typedef typename generic_type::vector_view    vector_t;
   43949             : 
   43950             :       using igfun_t::operator();
   43951             : 
   43952             :       read()
   43953             :       : igfun_t("TS|TST|TV|TVT")
   43954             :       { details::perform_check<T>(); }
   43955             : 
   43956             :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43957             :       {
   43958             :          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
   43959             : 
   43960             :          switch (ps_index)
   43961             :          {
   43962             :             case 0  : {
   43963             :                          string_t buffer(parameters[1]);
   43964             :                          const std::size_t amount = buffer.size();
   43965             :                          return T(fd->read(buffer,amount) ? 1 : 0);
   43966             :                       }
   43967             : 
   43968             :             case 1  : {
   43969             :                          string_t buffer(parameters[1]);
   43970             :                          const std::size_t amount =
   43971             :                                   std::min(buffer.size(),
   43972             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   43973             :                          return T(fd->read(buffer,amount) ? 1 : 0);
   43974             :                       }
   43975             : 
   43976             :             case 2  : {
   43977             :                          vector_t vec(parameters[1]);
   43978             :                          const std::size_t amount = vec.size();
   43979             :                          return T(fd->read(vec,amount) ? 1 : 0);
   43980             :                       }
   43981             : 
   43982             :             case 3  : {
   43983             :                          vector_t vec(parameters[1]);
   43984             :                          const std::size_t amount =
   43985             :                                   std::min(vec.size(),
   43986             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   43987             :                          return T(fd->read(vec,amount) ? 1 : 0);
   43988             :                       }
   43989             :          }
   43990             : 
   43991             :          return T(0);
   43992             :       }
   43993             :    };
   43994             : 
   43995             :    template <typename T>
   43996             :    class getline exprtk_final : public exprtk::igeneric_function<T>
   43997             :    {
   43998             :    public:
   43999             : 
   44000             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44001             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44002             :       typedef typename igfun_t::generic_type        generic_type;
   44003             :       typedef typename generic_type::string_view    string_t;
   44004             :       typedef typename generic_type::scalar_view    scalar_t;
   44005             : 
   44006             :       using igfun_t::operator();
   44007             : 
   44008             :       getline()
   44009             :       : igfun_t("T",igfun_t::e_rtrn_string)
   44010             :       { details::perform_check<T>(); }
   44011             : 
   44012             :       inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override
   44013             :       {
   44014             :          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
   44015             :          return T(fd->getline(result) ? 1 : 0);
   44016             :       }
   44017             :    };
   44018             : 
   44019             :    template <typename T>
   44020             :    struct eof exprtk_final : public exprtk::ifunction<T>
   44021             :    {
   44022             :       using exprtk::ifunction<T>::operator();
   44023             : 
   44024             :       eof()
   44025             :       : exprtk::ifunction<T>(1)
   44026             :       { details::perform_check<T>(); }
   44027             : 
   44028             :       inline T operator() (const T& v) exprtk_override
   44029             :       {
   44030             :          details::file_descriptor* fd = details::make_handle(v);
   44031             :          return (fd->eof() ? T(1) : T(0));
   44032             :       }
   44033             :    };
   44034             : 
   44035             :    template <typename T>
   44036             :    struct package
   44037             :    {
   44038             :       open   <T> o;
   44039             :       close  <T> c;
   44040             :       write  <T> w;
   44041             :       read   <T> r;
   44042             :       getline<T> g;
   44043             :       eof    <T> e;
   44044             : 
   44045             :       bool register_package(exprtk::symbol_table<T>& symtab)
   44046             :       {
   44047             :          #define exprtk_register_function(FunctionName, FunctionType)                   \
   44048             :          if (!symtab.add_function(FunctionName,FunctionType))                           \
   44049             :          {                                                                              \
   44050             :             exprtk_debug((                                                              \
   44051             :               "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
   44052             :               FunctionName));                                                           \
   44053             :             return false;                                                               \
   44054             :          }                                                                              \
   44055             : 
   44056             :          exprtk_register_function("open"    , o)
   44057             :          exprtk_register_function("close"   , c)
   44058             :          exprtk_register_function("write"   , w)
   44059             :          exprtk_register_function("read"    , r)
   44060             :          exprtk_register_function("getline" , g)
   44061             :          exprtk_register_function("eof"     , e)
   44062             :          #undef exprtk_register_function
   44063             : 
   44064             :          return true;
   44065             :       }
   44066             :    };
   44067             : 
   44068             :    } // namespace exprtk::rtl::io::file
   44069             :    } // namespace exprtk::rtl::io
   44070             :    } // namespace exprtk::rtl
   44071             : }    // namespace exprtk
   44072             : #endif
   44073             : 
   44074             : #ifndef exprtk_disable_rtl_vecops
   44075             : namespace exprtk
   44076             : {
   44077             :    namespace rtl { namespace vecops {
   44078             : 
   44079             :    namespace helper
   44080             :    {
   44081             :       template <typename Vector>
   44082        2953 :       inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
   44083             :       {
   44084        2953 :          if (r0 > (v.size() - 1))
   44085           0 :             return true;
   44086        2953 :          else if (r1 > (v.size() - 1))
   44087           0 :             return true;
   44088        2953 :          else if (r1 < r0)
   44089           0 :             return true;
   44090             :          else
   44091        2953 :             return false;
   44092             :       }
   44093             : 
   44094             :       template <typename T>
   44095             :       struct load_vector_range
   44096             :       {
   44097             :          typedef typename exprtk::igeneric_function<T> igfun_t;
   44098             :          typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44099             :          typedef typename igfun_t::generic_type        generic_type;
   44100             :          typedef typename generic_type::scalar_view    scalar_t;
   44101             :          typedef typename generic_type::vector_view    vector_t;
   44102             : 
   44103         806 :          static inline bool process(parameter_list_t& parameters,
   44104             :                                     std::size_t& r0, std::size_t& r1,
   44105             :                                     const std::size_t& r0_prmidx,
   44106             :                                     const std::size_t& r1_prmidx,
   44107             :                                     const std::size_t vec_idx = 0)
   44108             :          {
   44109         806 :             if (r0_prmidx >= parameters.size())
   44110           0 :                return false;
   44111             : 
   44112         806 :             if (r1_prmidx >= parameters.size())
   44113           0 :                return false;
   44114             : 
   44115         806 :             if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
   44116           0 :                return false;
   44117             : 
   44118         806 :             if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
   44119           0 :                return false;
   44120             : 
   44121         806 :             return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
   44122             :          }
   44123             :       };
   44124             :    }
   44125             : 
   44126             :    namespace details
   44127             :    {
   44128             :       template <typename T>
   44129         560 :       inline void kahan_sum(T& sum, T& error, const T v)
   44130             :       {
   44131         560 :          const T x = v - error;
   44132         560 :          const T y = sum + x;
   44133         560 :          error = (y - sum) - x;
   44134         560 :          sum = y;
   44135         560 :       }
   44136             : 
   44137             :    } // namespace exprtk::rtl::details
   44138             : 
   44139             :    template <typename T>
   44140             :    class all_true exprtk_final : public exprtk::igeneric_function<T>
   44141             :    {
   44142             :    public:
   44143             : 
   44144             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44145             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44146             :       typedef typename igfun_t::generic_type        generic_type;
   44147             :       typedef typename generic_type::vector_view    vector_t;
   44148             : 
   44149             :       using igfun_t::operator();
   44150             : 
   44151          32 :       all_true()
   44152          64 :       : exprtk::igeneric_function<T>("V|VTT")
   44153             :         /*
   44154             :            Overloads:
   44155             :            0. V   - vector
   44156             :            1. VTT - vector, r0, r1
   44157             :         */
   44158          32 :       {}
   44159             : 
   44160        1505 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44161             :       {
   44162        1505 :          const vector_t vec(parameters[0]);
   44163             : 
   44164        1505 :          std::size_t r0 = 0;
   44165        1505 :          std::size_t r1 = vec.size() - 1;
   44166             : 
   44167        1505 :          if (
   44168        1505 :               (1 == ps_index) &&
   44169        1505 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44170             :             )
   44171             :          {
   44172           0 :             return std::numeric_limits<T>::quiet_NaN();
   44173             :          }
   44174             : 
   44175       10955 :          for (std::size_t i = r0; i <= r1; ++i)
   44176             :          {
   44177        9452 :             if (vec[i] == T(0))
   44178             :             {
   44179           2 :                return T(0);
   44180             :             }
   44181             :          }
   44182             : 
   44183        1503 :          return T(1);
   44184             :       }
   44185             :    };
   44186             : 
   44187             :    template <typename T>
   44188             :    class all_false exprtk_final : public exprtk::igeneric_function<T>
   44189             :    {
   44190             :    public:
   44191             : 
   44192             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44193             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44194             :       typedef typename igfun_t::generic_type        generic_type;
   44195             :       typedef typename generic_type::vector_view    vector_t;
   44196             : 
   44197             :       using igfun_t::operator();
   44198             : 
   44199          32 :       all_false()
   44200          64 :       : exprtk::igeneric_function<T>("V|VTT")
   44201             :         /*
   44202             :            Overloads:
   44203             :            0. V   - vector
   44204             :            1. VTT - vector, r0, r1
   44205             :         */
   44206          32 :       {}
   44207             : 
   44208         263 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44209             :       {
   44210         263 :          const vector_t vec(parameters[0]);
   44211             : 
   44212         263 :          std::size_t r0 = 0;
   44213         263 :          std::size_t r1 = vec.size() - 1;
   44214             : 
   44215         263 :          if (
   44216         263 :               (1 == ps_index) &&
   44217         263 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44218             :             )
   44219             :          {
   44220           0 :             return std::numeric_limits<T>::quiet_NaN();
   44221             :          }
   44222             : 
   44223        1552 :          for (std::size_t i = r0; i <= r1; ++i)
   44224             :          {
   44225        1291 :             if (vec[i] != T(0))
   44226             :             {
   44227           2 :                return T(0);
   44228             :             }
   44229             :          }
   44230             : 
   44231         261 :          return T(1);
   44232             :       }
   44233             :    };
   44234             : 
   44235             :    template <typename T>
   44236             :    class any_true exprtk_final : public exprtk::igeneric_function<T>
   44237             :    {
   44238             :    public:
   44239             : 
   44240             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44241             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44242             :       typedef typename igfun_t::generic_type        generic_type;
   44243             :       typedef typename generic_type::vector_view    vector_t;
   44244             : 
   44245             :       using igfun_t::operator();
   44246             : 
   44247          32 :       any_true()
   44248          64 :       : exprtk::igeneric_function<T>("V|VTT")
   44249             :         /*
   44250             :            Overloads:
   44251             :            0. V   - vector
   44252             :            1. VTT - vector, r0, r1
   44253             :         */
   44254          32 :       {}
   44255             : 
   44256           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44257             :       {
   44258           4 :          const vector_t vec(parameters[0]);
   44259             : 
   44260           4 :          std::size_t r0 = 0;
   44261           4 :          std::size_t r1 = vec.size() - 1;
   44262             : 
   44263           4 :          if (
   44264           4 :               (1 == ps_index) &&
   44265           4 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44266             :             )
   44267             :          {
   44268           0 :             return std::numeric_limits<T>::quiet_NaN();
   44269             :          }
   44270             : 
   44271          25 :          for (std::size_t i = r0; i <= r1; ++i)
   44272             :          {
   44273          24 :             if (vec[i] != T(0))
   44274             :             {
   44275           3 :                return T(1);
   44276             :             }
   44277             :          }
   44278             : 
   44279           1 :          return T(0);
   44280             :       }
   44281             :    };
   44282             : 
   44283             :    template <typename T>
   44284             :    class any_false exprtk_final : public exprtk::igeneric_function<T>
   44285             :    {
   44286             :    public:
   44287             : 
   44288             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44289             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44290             :       typedef typename igfun_t::generic_type        generic_type;
   44291             :       typedef typename generic_type::vector_view    vector_t;
   44292             : 
   44293             :       using igfun_t::operator();
   44294             : 
   44295          32 :       any_false()
   44296          64 :       : exprtk::igeneric_function<T>("V|VTT")
   44297             :         /*
   44298             :            Overloads:
   44299             :            0. V   - vector
   44300             :            1. VTT - vector, r0, r1
   44301             :         */
   44302          32 :       {}
   44303             : 
   44304           5 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44305             :       {
   44306           5 :          const vector_t vec(parameters[0]);
   44307             : 
   44308           5 :          std::size_t r0 = 0;
   44309           5 :          std::size_t r1 = vec.size() - 1;
   44310             : 
   44311           5 :          if (
   44312           5 :               (1 == ps_index) &&
   44313           5 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44314             :             )
   44315             :          {
   44316           0 :             return std::numeric_limits<T>::quiet_NaN();
   44317             :          }
   44318             : 
   44319          26 :          for (std::size_t i = r0; i <= r1; ++i)
   44320             :          {
   44321          25 :             if (vec[i] == T(0))
   44322             :             {
   44323           4 :                return T(1);
   44324             :             }
   44325             :          }
   44326             : 
   44327           1 :          return T(0);
   44328             :       }
   44329             :    };
   44330             : 
   44331             :    template <typename T>
   44332             :    class count exprtk_final : public exprtk::igeneric_function<T>
   44333             :    {
   44334             :    public:
   44335             : 
   44336             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44337             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44338             :       typedef typename igfun_t::generic_type        generic_type;
   44339             :       typedef typename generic_type::vector_view    vector_t;
   44340             : 
   44341             :       using igfun_t::operator();
   44342             : 
   44343          32 :       count()
   44344          64 :       : exprtk::igeneric_function<T>("V|VTT")
   44345             :         /*
   44346             :            Overloads:
   44347             :            0. V   - vector
   44348             :            1. VTT - vector, r0, r1
   44349             :         */
   44350          32 :       {}
   44351             : 
   44352           6 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44353             :       {
   44354           6 :          const vector_t vec(parameters[0]);
   44355             : 
   44356           6 :          std::size_t r0 = 0;
   44357           6 :          std::size_t r1 = vec.size() - 1;
   44358             : 
   44359           6 :          if (
   44360           6 :               (1 == ps_index) &&
   44361           6 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44362             :             )
   44363             :          {
   44364           0 :             return std::numeric_limits<T>::quiet_NaN();
   44365             :          }
   44366             : 
   44367           6 :          std::size_t cnt = 0;
   44368             : 
   44369          60 :          for (std::size_t i = r0; i <= r1; ++i)
   44370             :          {
   44371          54 :             if (vec[i] != T(0)) ++cnt;
   44372             :          }
   44373             : 
   44374           6 :          return T(cnt);
   44375             :       }
   44376             :    };
   44377             : 
   44378             :    template <typename T>
   44379             :    class copy exprtk_final : public exprtk::igeneric_function<T>
   44380             :    {
   44381             :    public:
   44382             : 
   44383             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44384             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44385             :       typedef typename igfun_t::generic_type        generic_type;
   44386             :       typedef typename generic_type::scalar_view    scalar_t;
   44387             :       typedef typename generic_type::vector_view    vector_t;
   44388             : 
   44389             :       using igfun_t::operator();
   44390             : 
   44391          32 :       copy()
   44392          64 :       : exprtk::igeneric_function<T>("VV|VTTVTT")
   44393             :         /*
   44394             :            Overloads:
   44395             :            0. VV     - x(vector), y(vector)
   44396             :            1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
   44397             :         */
   44398          32 :       {}
   44399             : 
   44400           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44401             :       {
   44402           4 :          const vector_t x(parameters[0]);
   44403           4 :                vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
   44404             : 
   44405           4 :          std::size_t xr0 = 0;
   44406           4 :          std::size_t xr1 = x.size() - 1;
   44407             : 
   44408           4 :          std::size_t yr0 = 0;
   44409           4 :          std::size_t yr1 = y.size() - 1;
   44410             : 
   44411           4 :          if (1 == ps_index)
   44412             :          {
   44413           3 :             if (
   44414           6 :                  !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
   44415           6 :                  !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
   44416             :                )
   44417           0 :                return T(0);
   44418             :          }
   44419             : 
   44420           4 :          const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
   44421             : 
   44422          12 :          std::copy(
   44423           4 :             x.begin() + xr0,
   44424           4 :             x.begin() + xr0 + n,
   44425           4 :             y.begin() + yr0);
   44426             : 
   44427           4 :          return T(n);
   44428             :       }
   44429             :    };
   44430             : 
   44431             :    template <typename T>
   44432             :    class rol exprtk_final : public exprtk::igeneric_function<T>
   44433             :    {
   44434             :    public:
   44435             : 
   44436             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44437             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44438             :       typedef typename igfun_t::generic_type        generic_type;
   44439             :       typedef typename generic_type::scalar_view    scalar_t;
   44440             :       typedef typename generic_type::vector_view    vector_t;
   44441             : 
   44442             :       using igfun_t::operator();
   44443             : 
   44444          32 :       rol()
   44445          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   44446             :         /*
   44447             :            Overloads:
   44448             :            0. VT   - vector, N
   44449             :            1. VTTT - vector, N, r0, r1
   44450             :         */
   44451          32 :       {}
   44452             : 
   44453           3 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44454             :       {
   44455           3 :          vector_t vec(parameters[0]);
   44456             : 
   44457           3 :          std::size_t n  = 0;
   44458           3 :          std::size_t r0 = 0;
   44459           3 :          std::size_t r1 = vec.size() - 1;
   44460             : 
   44461           3 :          if (!scalar_t(parameters[1]).to_uint(n))
   44462           0 :             return T(0);
   44463             : 
   44464           3 :          if (
   44465           4 :               (1 == ps_index) &&
   44466           4 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   44467             :             )
   44468           0 :             return T(0);
   44469             : 
   44470           3 :          const std::size_t dist  = r1 - r0 + 1;
   44471           3 :          const std::size_t shift = n % dist;
   44472             : 
   44473           9 :          std::rotate(
   44474           3 :             vec.begin() + r0,
   44475           3 :             vec.begin() + r0 + shift,
   44476           3 :             vec.begin() + r1 + 1);
   44477             : 
   44478           3 :          return T(1);
   44479             :       }
   44480             :    };
   44481             : 
   44482             :    template <typename T>
   44483             :    class ror exprtk_final : public exprtk::igeneric_function<T>
   44484             :    {
   44485             :    public:
   44486             : 
   44487             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44488             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44489             :       typedef typename igfun_t::generic_type        generic_type;
   44490             :       typedef typename generic_type::scalar_view    scalar_t;
   44491             :       typedef typename generic_type::vector_view    vector_t;
   44492             : 
   44493             :       using igfun_t::operator();
   44494             : 
   44495          32 :       ror()
   44496          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   44497             :         /*
   44498             :            Overloads:
   44499             :            0. VT   - vector, N
   44500             :            1. VTTT - vector, N, r0, r1
   44501             :         */
   44502          32 :       {}
   44503             : 
   44504           3 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44505             :       {
   44506           3 :          vector_t vec(parameters[0]);
   44507             : 
   44508           3 :          std::size_t n  = 0;
   44509           3 :          std::size_t r0 = 0;
   44510           3 :          std::size_t r1 = vec.size() - 1;
   44511             : 
   44512           3 :          if (!scalar_t(parameters[1]).to_uint(n))
   44513           0 :             return T(0);
   44514             : 
   44515           3 :          if (
   44516           4 :               (1 == ps_index) &&
   44517           4 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   44518             :             )
   44519           0 :             return T(0);
   44520             : 
   44521           3 :          const std::size_t dist  = r1 - r0 + 1;
   44522           3 :          const std::size_t shift = (dist - (n % dist)) % dist;
   44523             : 
   44524           9 :          std::rotate(
   44525           3 :             vec.begin() + r0,
   44526           3 :             vec.begin() + r0 + shift,
   44527           3 :             vec.begin() + r1 + 1);
   44528             : 
   44529           3 :          return T(1);
   44530             :       }
   44531             :    };
   44532             : 
   44533             :    template <typename T>
   44534             :    class reverse exprtk_final : public exprtk::igeneric_function<T>
   44535             :    {
   44536             :    public:
   44537             : 
   44538             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44539             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44540             :       typedef typename igfun_t::generic_type        generic_type;
   44541             :       typedef typename generic_type::scalar_view    scalar_t;
   44542             :       typedef typename generic_type::vector_view    vector_t;
   44543             : 
   44544             :       using igfun_t::operator();
   44545             : 
   44546          32 :       reverse()
   44547          64 :       : exprtk::igeneric_function<T>("V|VTT")
   44548             :         /*
   44549             :            Overloads:
   44550             :            0. V   - vector
   44551             :            1. VTT - vector, r0, r1
   44552             :         */
   44553          32 :       {}
   44554             : 
   44555         100 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44556             :       {
   44557         100 :          vector_t vec(parameters[0]);
   44558             : 
   44559         100 :          std::size_t r0 = 0;
   44560         100 :          std::size_t r1 = vec.size() - 1;
   44561             : 
   44562         100 :          if (
   44563         175 :               (1 == ps_index) &&
   44564         175 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44565             :             )
   44566           0 :             return T(0);
   44567             : 
   44568         100 :          std::reverse(vec.begin() + r0, vec.begin() + r1 + 1);
   44569             : 
   44570         100 :          return T(1);
   44571             :       }
   44572             :    };
   44573             : 
   44574             :    template <typename T>
   44575             :    class shift_left exprtk_final : public exprtk::igeneric_function<T>
   44576             :    {
   44577             :    public:
   44578             : 
   44579             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44580             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44581             :       typedef typename igfun_t::generic_type        generic_type;
   44582             :       typedef typename generic_type::scalar_view    scalar_t;
   44583             :       typedef typename generic_type::vector_view    vector_t;
   44584             : 
   44585             :       using igfun_t::operator();
   44586             : 
   44587          32 :       shift_left()
   44588          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   44589             :         /*
   44590             :            Overloads:
   44591             :            0. VT   - vector, N
   44592             :            1. VTTT - vector, N, r0, r1
   44593             :         */
   44594          32 :       {}
   44595             : 
   44596           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44597             :       {
   44598           4 :          vector_t vec(parameters[0]);
   44599             : 
   44600           4 :          std::size_t n  = 0;
   44601           4 :          std::size_t r0 = 0;
   44602           4 :          std::size_t r1 = vec.size() - 1;
   44603             : 
   44604           4 :          if (!scalar_t(parameters[1]).to_uint(n))
   44605           0 :             return T(0);
   44606             : 
   44607           4 :          if (
   44608           5 :               (1 == ps_index) &&
   44609           5 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   44610             :             )
   44611           0 :             return T(0);
   44612             : 
   44613           4 :          const std::size_t dist = r1 - r0 + 1;
   44614             : 
   44615           4 :          if (n > dist)
   44616           0 :             return T(0);
   44617             : 
   44618          12 :          std::rotate(
   44619           4 :             vec.begin() + r0,
   44620           4 :             vec.begin() + r0 + n,
   44621           4 :             vec.begin() + r1 + 1);
   44622             : 
   44623          16 :          for (std::size_t i = r1 - n + 1; i <= r1; ++i)
   44624             :          {
   44625          12 :             vec[i] = T(0);
   44626             :          }
   44627             : 
   44628           4 :          return T(1);
   44629             :       }
   44630             :    };
   44631             : 
   44632             :    template <typename T>
   44633             :    class shift_right exprtk_final : public exprtk::igeneric_function<T>
   44634             :    {
   44635             :    public:
   44636             : 
   44637             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44638             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44639             :       typedef typename igfun_t::generic_type        generic_type;
   44640             :       typedef typename generic_type::scalar_view    scalar_t;
   44641             :       typedef typename generic_type::vector_view    vector_t;
   44642             : 
   44643             :       using igfun_t::operator();
   44644             : 
   44645          32 :       shift_right()
   44646          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   44647             :         /*
   44648             :            Overloads:
   44649             :            0. VT   - vector, N
   44650             :            1. VTTT - vector, N, r0, r1
   44651             :         */
   44652          32 :       {}
   44653             : 
   44654           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44655             :       {
   44656           4 :          vector_t vec(parameters[0]);
   44657             : 
   44658           4 :          std::size_t n  = 0;
   44659           4 :          std::size_t r0 = 0;
   44660           4 :          std::size_t r1 = vec.size() - 1;
   44661             : 
   44662           4 :          if (!scalar_t(parameters[1]).to_uint(n))
   44663           0 :             return T(0);
   44664             : 
   44665           4 :          if (
   44666           5 :               (1 == ps_index) &&
   44667           5 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   44668             :             )
   44669           0 :             return T(0);
   44670             : 
   44671           4 :          const std::size_t dist = r1 - r0 + 1;
   44672             : 
   44673           4 :          if (n > dist)
   44674           0 :             return T(0);
   44675             : 
   44676           4 :          const std::size_t shift = (dist - (n % dist)) % dist;
   44677             : 
   44678          12 :          std::rotate(
   44679           4 :             vec.begin() + r0,
   44680           4 :             vec.begin() + r0 + shift,
   44681           4 :             vec.begin() + r1 + 1);
   44682             : 
   44683          16 :          for (std::size_t i = r0; i < r0 + n; ++i)
   44684             :          {
   44685          12 :             vec[i] = T(0);
   44686             :          }
   44687             : 
   44688           4 :          return T(1);
   44689             :       }
   44690             :    };
   44691             : 
   44692             :    template <typename T>
   44693             :    class sort exprtk_final : public exprtk::igeneric_function<T>
   44694             :    {
   44695             :    public:
   44696             : 
   44697             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44698             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44699             :       typedef typename igfun_t::generic_type        generic_type;
   44700             :       typedef typename generic_type::string_view    string_t;
   44701             :       typedef typename generic_type::vector_view    vector_t;
   44702             : 
   44703             :       using igfun_t::operator();
   44704             : 
   44705          32 :       sort()
   44706          64 :       : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
   44707             :         /*
   44708             :            Overloads:
   44709             :            0. V    - vector
   44710             :            1. VTT  - vector, r0, r1
   44711             :            2. VS   - vector, string
   44712             :            3. VSTT - vector, string, r0, r1
   44713             :         */
   44714          32 :       {}
   44715             : 
   44716          20 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44717             :       {
   44718          20 :          vector_t vec(parameters[0]);
   44719             : 
   44720          20 :          std::size_t r0 = 0;
   44721          20 :          std::size_t r1 = vec.size() - 1;
   44722             : 
   44723          20 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
   44724           0 :             return T(0);
   44725          20 :          if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   44726           0 :             return T(0);
   44727             : 
   44728          20 :          bool ascending = true;
   44729             : 
   44730          20 :          if ((2 == ps_index) || (3 == ps_index))
   44731             :          {
   44732          24 :             if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
   44733           6 :                ascending = true;
   44734          12 :             else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
   44735           6 :                ascending = false;
   44736             :             else
   44737           0 :                return T(0);
   44738             :          }
   44739             : 
   44740          20 :          if (ascending)
   44741          28 :             std::sort(
   44742          14 :                vec.begin() + r0,
   44743          14 :                vec.begin() + r1 + 1,
   44744             :                std::less<T>());
   44745             :          else
   44746          12 :             std::sort(
   44747           6 :                vec.begin() + r0,
   44748           6 :                vec.begin() + r1 + 1,
   44749             :                std::greater<T>());
   44750             : 
   44751          20 :          return T(1);
   44752             :       }
   44753             :    };
   44754             : 
   44755             :    template <typename T>
   44756             :    class nthelement exprtk_final : public exprtk::igeneric_function<T>
   44757             :    {
   44758             :    public:
   44759             : 
   44760             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44761             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44762             :       typedef typename igfun_t::generic_type        generic_type;
   44763             :       typedef typename generic_type::scalar_view    scalar_t;
   44764             :       typedef typename generic_type::vector_view    vector_t;
   44765             : 
   44766             :       using igfun_t::operator();
   44767             : 
   44768          32 :       nthelement()
   44769          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   44770             :         /*
   44771             :            Overloads:
   44772             :            0. VT   - vector, nth-element
   44773             :            1. VTTT - vector, nth-element, r0, r1
   44774             :         */
   44775          32 :       {}
   44776             : 
   44777           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44778             :       {
   44779           4 :          vector_t vec(parameters[0]);
   44780             : 
   44781           4 :          std::size_t n  = 0;
   44782           4 :          std::size_t r0 = 0;
   44783           4 :          std::size_t r1 = vec.size() - 1;
   44784             : 
   44785           4 :          if (!scalar_t(parameters[1]).to_uint(n))
   44786           0 :             return T(0);
   44787             : 
   44788           4 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   44789             :          {
   44790           0 :             return std::numeric_limits<T>::quiet_NaN();
   44791             :          }
   44792             : 
   44793          12 :          std::nth_element(
   44794           4 :             vec.begin() + r0,
   44795           4 :             vec.begin() + r0 + n ,
   44796           4 :             vec.begin() + r1 + 1);
   44797             : 
   44798           4 :          return T(1);
   44799             :       }
   44800             :    };
   44801             : 
   44802             :    template <typename T>
   44803             :    class assign exprtk_final : public exprtk::igeneric_function<T>
   44804             :    {
   44805             :    public:
   44806             : 
   44807             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44808             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44809             :       typedef typename igfun_t::generic_type        generic_type;
   44810             :       typedef typename generic_type::scalar_view    scalar_t;
   44811             :       typedef typename generic_type::vector_view    vector_t;
   44812             : 
   44813             :       using igfun_t::operator();
   44814             : 
   44815          32 :       assign()
   44816          64 :       : exprtk::igeneric_function<T>("VT|VTTT|VTTTT")
   44817             :         /*
   44818             :            Overloads:
   44819             :            0. VT    - vector, V
   44820             :            1. VTTT  - vector, V, r0, r1
   44821             :            2. VTTTT - vector, V, r0, r1, SS
   44822             :         */
   44823          32 :       {}
   44824             : 
   44825         380 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44826             :       {
   44827         380 :          vector_t vec(parameters[0]);
   44828             : 
   44829         380 :          const T assign_value = scalar_t(parameters[1]);
   44830             : 
   44831         380 :          const std::size_t step_size = (2 != ps_index) ? 1 :
   44832         230 :                                        static_cast<std::size_t>(scalar_t(parameters.back())());
   44833             : 
   44834         380 :          std::size_t r0 = 0;
   44835         380 :          std::size_t r1 = vec.size() - 1;
   44836             : 
   44837         380 :          if (
   44838         760 :               ((ps_index == 1) || (ps_index == 2)) &&
   44839         760 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   44840             :             )
   44841             :          {
   44842           0 :             return T(0);
   44843             :          }
   44844             : 
   44845        2080 :          for (std::size_t i = r0; i <= r1; i += step_size)
   44846             :          {
   44847        1700 :             vec[i] = assign_value;
   44848             :          }
   44849             : 
   44850         380 :          return T(1);
   44851             :       }
   44852             :    };
   44853             : 
   44854             :    template <typename T>
   44855             :    class iota exprtk_final : public exprtk::igeneric_function<T>
   44856             :    {
   44857             :    public:
   44858             : 
   44859             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44860             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44861             :       typedef typename igfun_t::generic_type        generic_type;
   44862             :       typedef typename generic_type::scalar_view    scalar_t;
   44863             :       typedef typename generic_type::vector_view    vector_t;
   44864             : 
   44865             :       using igfun_t::operator();
   44866             : 
   44867          32 :       iota()
   44868          64 :       : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT")
   44869             :         /*
   44870             :            Overloads:
   44871             :            0. VTT  - vector, SV, SS
   44872             :            1. VT   - vector, SV, SS (+1)
   44873             :            2. VTTT - vector, r0, r1, SV, SS
   44874             :            3. VTT  - vector, r0, r1, SV, SS (+1)
   44875             : 
   44876             :            Where:
   44877             :            1. SV - Start value
   44878             :            2. SS - Step size
   44879             :         */
   44880          32 :       {}
   44881             : 
   44882         318 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44883             :       {
   44884         318 :          vector_t vec(parameters[0]);
   44885             : 
   44886         636 :          const T start_value = (ps_index <= 1) ?
   44887          55 :                                scalar_t(parameters[1]) :
   44888         263 :                                scalar_t(parameters[3]) ;
   44889             : 
   44890         616 :          const T step_size = ((0 == ps_index) || (2 == ps_index)) ?
   44891         298 :                              scalar_t(parameters.back())() :
   44892             :                              T(1) ;
   44893             : 
   44894         318 :          std::size_t r0 = 0;
   44895         318 :          std::size_t r1 = vec.size() - 1;
   44896             : 
   44897         318 :          if (
   44898         581 :               ((ps_index == 2) || (ps_index == 3)) &&
   44899         581 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44900             :             )
   44901             :          {
   44902           0 :             return T(0);
   44903             :          }
   44904             : 
   44905        1820 :          for (std::size_t i = r0; i <= r1; ++i)
   44906             :          {
   44907        1502 :             vec[i] = start_value + ((i - r0) * step_size);
   44908             :          }
   44909             : 
   44910         318 :          return T(1);
   44911             :       }
   44912             :    };
   44913             : 
   44914             :    template <typename T>
   44915             :    class sumk exprtk_final : public exprtk::igeneric_function<T>
   44916             :    {
   44917             :    public:
   44918             : 
   44919             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44920             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44921             :       typedef typename igfun_t::generic_type        generic_type;
   44922             :       typedef typename generic_type::scalar_view    scalar_t;
   44923             :       typedef typename generic_type::vector_view    vector_t;
   44924             : 
   44925             :       using igfun_t::operator();
   44926             : 
   44927          32 :       sumk()
   44928          64 :       : exprtk::igeneric_function<T>("V|VTT|VTTT")
   44929             :         /*
   44930             :            Overloads:
   44931             :            0. V    - vector
   44932             :            1. VTT  - vector, r0, r1
   44933             :            2. VTTT - vector, r0, r1, stride
   44934             :         */
   44935          32 :       {}
   44936             : 
   44937          80 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44938             :       {
   44939          80 :          const vector_t vec(parameters[0]);
   44940             : 
   44941          80 :          const std::size_t stride = (2 != ps_index) ? 1 :
   44942          40 :                                     static_cast<std::size_t>(scalar_t(parameters[3])());
   44943             : 
   44944          80 :          std::size_t r0 = 0;
   44945          80 :          std::size_t r1 = vec.size() - 1;
   44946             : 
   44947          80 :          if (
   44948         140 :               ((1 == ps_index) || (2 == ps_index)) &&
   44949         140 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44950             :             )
   44951             :          {
   44952           0 :             return std::numeric_limits<T>::quiet_NaN();
   44953             :          }
   44954             : 
   44955          80 :          T result = T(0);
   44956          80 :          T error  = T(0);
   44957             : 
   44958         640 :          for (std::size_t i = r0; i <= r1; i += stride)
   44959             :          {
   44960         560 :             details::kahan_sum(result, error, vec[i]);
   44961             :          }
   44962             : 
   44963          80 :          return result;
   44964             :       }
   44965             :    };
   44966             : 
   44967             :    template <typename T>
   44968             :    class axpy exprtk_final : public exprtk::igeneric_function<T>
   44969             :    {
   44970             :    public:
   44971             : 
   44972             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44973             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44974             :       typedef typename igfun_t::generic_type        generic_type;
   44975             :       typedef typename generic_type::scalar_view    scalar_t;
   44976             :       typedef typename generic_type::vector_view    vector_t;
   44977             : 
   44978             :       using igfun_t::operator();
   44979             : 
   44980          32 :       axpy()
   44981          64 :       : exprtk::igeneric_function<T>("TVV|TVVTT")
   44982             :         /*
   44983             :            y <- ax + y
   44984             :            Overloads:
   44985             :            0. TVV   - a, x(vector), y(vector)
   44986             :            1. TVVTT - a, x(vector), y(vector), r0, r1
   44987             :         */
   44988          32 :       {}
   44989             : 
   44990          51 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44991             :       {
   44992          51 :          const vector_t x(parameters[1]);
   44993          51 :                vector_t y(parameters[2]);
   44994             : 
   44995          51 :          std::size_t r0 = 0;
   44996          51 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   44997             : 
   44998          51 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
   44999           0 :             return std::numeric_limits<T>::quiet_NaN();
   45000          51 :          else if (helper::invalid_range(y, r0, r1))
   45001           0 :             return std::numeric_limits<T>::quiet_NaN();
   45002             : 
   45003          51 :          const T a = scalar_t(parameters[0])();
   45004             : 
   45005         254 :          for (std::size_t i = r0; i <= r1; ++i)
   45006             :          {
   45007         203 :             y[i] = (a * x[i]) + y[i];
   45008             :          }
   45009             : 
   45010          51 :          return T(1);
   45011             :       }
   45012             :    };
   45013             : 
   45014             :    template <typename T>
   45015             :    class axpby exprtk_final : public exprtk::igeneric_function<T>
   45016             :    {
   45017             :    public:
   45018             : 
   45019             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45020             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45021             :       typedef typename igfun_t::generic_type        generic_type;
   45022             :       typedef typename generic_type::scalar_view    scalar_t;
   45023             :       typedef typename generic_type::vector_view    vector_t;
   45024             : 
   45025             :       using igfun_t::operator();
   45026             : 
   45027          32 :       axpby()
   45028          64 :       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
   45029             :         /*
   45030             :            y <- ax + by
   45031             :            Overloads:
   45032             :            0. TVTV   - a, x(vector), b, y(vector)
   45033             :            1. TVTVTT - a, x(vector), b, y(vector), r0, r1
   45034             :         */
   45035          32 :       {}
   45036             : 
   45037          41 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45038             :       {
   45039          41 :          const vector_t x(parameters[1]);
   45040          41 :                vector_t y(parameters[3]);
   45041             : 
   45042          41 :          std::size_t r0 = 0;
   45043          41 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45044             : 
   45045          41 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
   45046           0 :             return std::numeric_limits<T>::quiet_NaN();
   45047          41 :          else if (helper::invalid_range(y, r0, r1))
   45048           0 :             return std::numeric_limits<T>::quiet_NaN();
   45049             : 
   45050          41 :          const T a = scalar_t(parameters[0])();
   45051          41 :          const T b = scalar_t(parameters[2])();
   45052             : 
   45053         204 :          for (std::size_t i = r0; i <= r1; ++i)
   45054             :          {
   45055         163 :             y[i] = (a * x[i]) + (b * y[i]);
   45056             :          }
   45057             : 
   45058          41 :          return T(1);
   45059             :       }
   45060             :    };
   45061             : 
   45062             :    template <typename T>
   45063             :    class axpyz exprtk_final : public exprtk::igeneric_function<T>
   45064             :    {
   45065             :    public:
   45066             : 
   45067             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45068             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45069             :       typedef typename igfun_t::generic_type        generic_type;
   45070             :       typedef typename generic_type::scalar_view    scalar_t;
   45071             :       typedef typename generic_type::vector_view    vector_t;
   45072             : 
   45073             :       using igfun_t::operator();
   45074             : 
   45075          32 :       axpyz()
   45076          64 :       : exprtk::igeneric_function<T>("TVVV|TVVVTT")
   45077             :         /*
   45078             :            z <- ax + y
   45079             :            Overloads:
   45080             :            0. TVVV   - a, x(vector), y(vector), z(vector)
   45081             :            1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
   45082             :         */
   45083          32 :       {}
   45084             : 
   45085          41 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45086             :       {
   45087          41 :          const vector_t x(parameters[1]);
   45088          41 :          const vector_t y(parameters[2]);
   45089          41 :                vector_t z(parameters[3]);
   45090             : 
   45091          41 :          std::size_t r0 = 0;
   45092          41 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45093             : 
   45094          41 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
   45095           0 :             return std::numeric_limits<T>::quiet_NaN();
   45096          41 :          else if (helper::invalid_range(y, r0, r1))
   45097           0 :             return std::numeric_limits<T>::quiet_NaN();
   45098          41 :          else if (helper::invalid_range(z, r0, r1))
   45099           0 :             return std::numeric_limits<T>::quiet_NaN();
   45100             : 
   45101          41 :          const T a = scalar_t(parameters[0])();
   45102             : 
   45103         204 :          for (std::size_t i = r0; i <= r1; ++i)
   45104             :          {
   45105         163 :             z[i] = (a * x[i]) + y[i];
   45106             :          }
   45107             : 
   45108          41 :          return T(1);
   45109             :       }
   45110             :    };
   45111             : 
   45112             :    template <typename T>
   45113             :    class axpbyz exprtk_final : public exprtk::igeneric_function<T>
   45114             :    {
   45115             :    public:
   45116             : 
   45117             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45118             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45119             :       typedef typename igfun_t::generic_type        generic_type;
   45120             :       typedef typename generic_type::scalar_view    scalar_t;
   45121             :       typedef typename generic_type::vector_view    vector_t;
   45122             : 
   45123             :       using igfun_t::operator();
   45124             : 
   45125          32 :       axpbyz()
   45126          64 :       : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
   45127             :         /*
   45128             :            z <- ax + by
   45129             :            Overloads:
   45130             :            0. TVTVV   - a, x(vector), b, y(vector), z(vector)
   45131             :            1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
   45132             :         */
   45133          32 :       {}
   45134             : 
   45135          41 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45136             :       {
   45137          41 :          const vector_t x(parameters[1]);
   45138          41 :          const vector_t y(parameters[3]);
   45139          41 :                vector_t z(parameters[4]);
   45140             : 
   45141          41 :          std::size_t r0 = 0;
   45142          41 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45143             : 
   45144          41 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
   45145           0 :             return std::numeric_limits<T>::quiet_NaN();
   45146          41 :          else if (helper::invalid_range(y, r0, r1))
   45147           0 :             return std::numeric_limits<T>::quiet_NaN();
   45148          41 :          else if (helper::invalid_range(z, r0, r1))
   45149           0 :             return std::numeric_limits<T>::quiet_NaN();
   45150             : 
   45151          41 :          const T a = scalar_t(parameters[0])();
   45152          41 :          const T b = scalar_t(parameters[2])();
   45153             : 
   45154         204 :          for (std::size_t i = r0; i <= r1; ++i)
   45155             :          {
   45156         163 :             z[i] = (a * x[i]) + (b * y[i]);
   45157             :          }
   45158             : 
   45159          41 :          return T(1);
   45160             :       }
   45161             :    };
   45162             : 
   45163             :    template <typename T>
   45164             :    class axpbsy exprtk_final : public exprtk::igeneric_function<T>
   45165             :    {
   45166             :    public:
   45167             : 
   45168             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45169             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45170             :       typedef typename igfun_t::generic_type        generic_type;
   45171             :       typedef typename generic_type::scalar_view    scalar_t;
   45172             :       typedef typename generic_type::vector_view    vector_t;
   45173             : 
   45174             :       using igfun_t::operator();
   45175             : 
   45176          32 :       axpbsy()
   45177          64 :       : exprtk::igeneric_function<T>("TVTTV|TVTTVTT")
   45178             :         /*
   45179             :            y <- ax + by
   45180             :            Overloads:
   45181             :            0. TVTVV   - a, x(vector), b, shift, y(vector), z(vector)
   45182             :            1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
   45183             :         */
   45184          32 :       {}
   45185             : 
   45186           0 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45187             :       {
   45188           0 :          const vector_t x(parameters[1]);
   45189           0 :                vector_t y(parameters[4]);
   45190             : 
   45191           0 :          std::size_t r0 = 0;
   45192           0 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45193             : 
   45194           0 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
   45195           0 :             return std::numeric_limits<T>::quiet_NaN();
   45196           0 :          else if (helper::invalid_range(y, r0, r1))
   45197           0 :             return std::numeric_limits<T>::quiet_NaN();
   45198             : 
   45199           0 :          const T a = scalar_t(parameters[0])();
   45200           0 :          const T b = scalar_t(parameters[2])();
   45201             : 
   45202           0 :          const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
   45203             : 
   45204           0 :          for (std::size_t i = r0; i <= r1; ++i)
   45205             :          {
   45206           0 :             y[i] = (a * x[i]) + (b * y[i + s]);
   45207             :          }
   45208             : 
   45209           0 :          return T(1);
   45210             :       }
   45211             :    };
   45212             : 
   45213             :    template <typename T>
   45214             :    class axpbsyz exprtk_final : public exprtk::igeneric_function<T>
   45215             :    {
   45216             :    public:
   45217             : 
   45218             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45219             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45220             :       typedef typename igfun_t::generic_type        generic_type;
   45221             :       typedef typename generic_type::scalar_view    scalar_t;
   45222             :       typedef typename generic_type::vector_view    vector_t;
   45223             : 
   45224             :       using igfun_t::operator();
   45225             : 
   45226          32 :       axpbsyz()
   45227          64 :       : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT")
   45228             :         /*
   45229             :            z <- ax + by
   45230             :            Overloads:
   45231             :            0. TVTVV   - a, x(vector), b, shift, y(vector), z(vector)
   45232             :            1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
   45233             :         */
   45234          32 :       {}
   45235             : 
   45236           0 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45237             :       {
   45238           0 :          const vector_t x(parameters[1]);
   45239           0 :          const vector_t y(parameters[4]);
   45240           0 :                vector_t z(parameters[5]);
   45241             : 
   45242           0 :          std::size_t r0 = 0;
   45243           0 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45244             : 
   45245           0 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1))
   45246           0 :             return std::numeric_limits<T>::quiet_NaN();
   45247           0 :          else if (helper::invalid_range(y, r0, r1))
   45248           0 :             return std::numeric_limits<T>::quiet_NaN();
   45249           0 :          else if (helper::invalid_range(z, r0, r1))
   45250           0 :             return std::numeric_limits<T>::quiet_NaN();
   45251             : 
   45252           0 :          const T a = scalar_t(parameters[0])();
   45253           0 :          const T b = scalar_t(parameters[2])();
   45254             : 
   45255           0 :          const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
   45256             : 
   45257           0 :          for (std::size_t i = r0; i <= r1; ++i)
   45258             :          {
   45259           0 :             z[i] = (a * x[i]) + (b * y[i + s]);
   45260             :          }
   45261             : 
   45262           0 :          return T(1);
   45263             :       }
   45264             :    };
   45265             : 
   45266             :    template <typename T>
   45267             :    class axpbz exprtk_final : public exprtk::igeneric_function<T>
   45268             :    {
   45269             :    public:
   45270             : 
   45271             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45272             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45273             :       typedef typename igfun_t::generic_type        generic_type;
   45274             :       typedef typename generic_type::scalar_view    scalar_t;
   45275             :       typedef typename generic_type::vector_view    vector_t;
   45276             : 
   45277             :       using igfun_t::operator();
   45278             : 
   45279          32 :       axpbz()
   45280          64 :       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
   45281             :         /*
   45282             :            z <- ax + b
   45283             :            Overloads:
   45284             :            0. TVTV   - a, x(vector), b, z(vector)
   45285             :            1. TVTVTT - a, x(vector), b, z(vector), r0, r1
   45286             :         */
   45287          32 :       {}
   45288             : 
   45289          51 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45290             :       {
   45291          51 :          const vector_t x(parameters[1]);
   45292          51 :                vector_t z(parameters[3]);
   45293             : 
   45294          51 :          std::size_t r0 = 0;
   45295          51 :          std::size_t r1 = x.size() - 1;
   45296             : 
   45297          51 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
   45298           0 :             return std::numeric_limits<T>::quiet_NaN();
   45299          51 :          else if (helper::invalid_range(z, r0, r1))
   45300           0 :             return std::numeric_limits<T>::quiet_NaN();
   45301             : 
   45302          51 :          const T a = scalar_t(parameters[0])();
   45303          51 :          const T b = scalar_t(parameters[2])();
   45304             : 
   45305         254 :          for (std::size_t i = r0; i <= r1; ++i)
   45306             :          {
   45307         203 :             z[i] = (a * x[i]) + b;
   45308             :          }
   45309             : 
   45310          51 :          return T(1);
   45311             :       }
   45312             :    };
   45313             : 
   45314             :    template <typename T>
   45315             :    class diff exprtk_final : public exprtk::igeneric_function<T>
   45316             :    {
   45317             :    public:
   45318             : 
   45319             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45320             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45321             :       typedef typename igfun_t::generic_type        generic_type;
   45322             :       typedef typename generic_type::scalar_view    scalar_t;
   45323             :       typedef typename generic_type::vector_view    vector_t;
   45324             : 
   45325             :       using igfun_t::operator();
   45326             : 
   45327          32 :       diff()
   45328          64 :       : exprtk::igeneric_function<T>("VV|VVT")
   45329             :         /*
   45330             :            x_(i - stride) - x_i
   45331             :            Overloads:
   45332             :            0. VV  - x(vector), y(vector)
   45333             :            1. VVT - x(vector), y(vector), stride
   45334             :         */
   45335          32 :       {}
   45336             : 
   45337          20 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45338             :       {
   45339          20 :          const vector_t x(parameters[0]);
   45340          20 :                vector_t y(parameters[1]);
   45341             : 
   45342          20 :          const std::size_t r0 = 0;
   45343          20 :          const std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45344             : 
   45345          30 :          const std::size_t stride = (1 != ps_index) ? 1 :
   45346          10 :                                     std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])()));
   45347             : 
   45348          50 :          for (std::size_t i = 0; i < stride; ++i)
   45349             :          {
   45350          30 :             y[i] = std::numeric_limits<T>::quiet_NaN();
   45351             :          }
   45352             : 
   45353         150 :          for (std::size_t i = (r0 + stride); i <= r1; ++i)
   45354             :          {
   45355         130 :             y[i] = x[i] - x[i - stride];
   45356             :          }
   45357             : 
   45358          20 :          return T(1);
   45359             :       }
   45360             :    };
   45361             : 
   45362             :    template <typename T>
   45363             :    class dot exprtk_final : public exprtk::igeneric_function<T>
   45364             :    {
   45365             :    public:
   45366             : 
   45367             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45368             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45369             :       typedef typename igfun_t::generic_type        generic_type;
   45370             :       typedef typename generic_type::scalar_view    scalar_t;
   45371             :       typedef typename generic_type::vector_view    vector_t;
   45372             : 
   45373             :       using igfun_t::operator();
   45374             : 
   45375          32 :       dot()
   45376          64 :       : exprtk::igeneric_function<T>("VV|VVTT")
   45377             :         /*
   45378             :            Overloads:
   45379             :            0. VV   - x(vector), y(vector)
   45380             :            1. VVTT - x(vector), y(vector), r0, r1
   45381             :         */
   45382          32 :       {}
   45383             : 
   45384        1840 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45385             :       {
   45386        1840 :          const vector_t x(parameters[0]);
   45387        1840 :          const vector_t y(parameters[1]);
   45388             : 
   45389        1840 :          std::size_t r0 = 0;
   45390        1840 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45391             : 
   45392        1840 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   45393           0 :             return std::numeric_limits<T>::quiet_NaN();
   45394        1840 :          else if (helper::invalid_range(y, r0, r1))
   45395           0 :             return std::numeric_limits<T>::quiet_NaN();
   45396             : 
   45397        1840 :          T result = T(0);
   45398             : 
   45399       11080 :          for (std::size_t i = r0; i <= r1; ++i)
   45400             :          {
   45401        9240 :             result += (x[i] * y[i]);
   45402             :          }
   45403             : 
   45404        1840 :          return result;
   45405             :       }
   45406             :    };
   45407             : 
   45408             :    template <typename T>
   45409             :    class dotk exprtk_final : public exprtk::igeneric_function<T>
   45410             :    {
   45411             :    public:
   45412             : 
   45413             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45414             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45415             :       typedef typename igfun_t::generic_type        generic_type;
   45416             :       typedef typename generic_type::scalar_view    scalar_t;
   45417             :       typedef typename generic_type::vector_view    vector_t;
   45418             : 
   45419             :       using igfun_t::operator();
   45420             : 
   45421          32 :       dotk()
   45422          64 :       : exprtk::igeneric_function<T>("VV|VVTT")
   45423             :         /*
   45424             :            Overloads:
   45425             :            0. VV   - x(vector), y(vector)
   45426             :            1. VVTT - x(vector), y(vector), r0, r1
   45427             :         */
   45428          32 :       {}
   45429             : 
   45430           0 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45431             :       {
   45432           0 :          const vector_t x(parameters[0]);
   45433           0 :          const vector_t y(parameters[1]);
   45434             : 
   45435           0 :          std::size_t r0 = 0;
   45436           0 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   45437             : 
   45438           0 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   45439           0 :             return std::numeric_limits<T>::quiet_NaN();
   45440           0 :          else if (helper::invalid_range(y, r0, r1))
   45441           0 :             return std::numeric_limits<T>::quiet_NaN();
   45442             : 
   45443           0 :          T result = T(0);
   45444           0 :          T error  = T(0);
   45445             : 
   45446           0 :          for (std::size_t i = r0; i <= r1; ++i)
   45447             :          {
   45448           0 :             details::kahan_sum(result, error, (x[i] * y[i]));
   45449             :          }
   45450             : 
   45451           0 :          return result;
   45452             :       }
   45453             :    };
   45454             : 
   45455             :    template <typename T>
   45456             :    class threshold_below exprtk_final : public exprtk::igeneric_function<T>
   45457             :    {
   45458             :    public:
   45459             : 
   45460             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45461             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45462             :       typedef typename igfun_t::generic_type        generic_type;
   45463             :       typedef typename generic_type::scalar_view    scalar_t;
   45464             :       typedef typename generic_type::vector_view    vector_t;
   45465             : 
   45466             :       using igfun_t::operator();
   45467             : 
   45468          32 :       threshold_below()
   45469          64 :       : exprtk::igeneric_function<T>("VTT|VTTTT")
   45470             :       /*
   45471             :          Overloads:
   45472             :          0. VTT   - vector, TV, SV
   45473             :          1. VTTTT - vector, r0, r1, TV, SV
   45474             : 
   45475             :          Where:
   45476             :          TV - Threshold value
   45477             :          SV - Snap-to value
   45478             :       */
   45479          32 :       {}
   45480             : 
   45481           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45482             :       {
   45483           4 :          vector_t vec(parameters[0]);
   45484             : 
   45485           8 :          const T threshold_value = (0 == ps_index) ?
   45486           1 :                                    scalar_t(parameters[1]) :
   45487           3 :                                    scalar_t(parameters[3]) ;
   45488             : 
   45489           4 :          const T snap_value = scalar_t(parameters.back());
   45490             : 
   45491           4 :          std::size_t r0 = 0;
   45492           4 :          std::size_t r1 = vec.size() - 1;
   45493             : 
   45494           4 :          if (
   45495           7 :               (1 == ps_index) &&
   45496           7 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   45497             :             )
   45498             :          {
   45499           0 :             return T(0);
   45500             :          }
   45501             : 
   45502          22 :          for (std::size_t i = r0; i <= r1; ++i)
   45503             :          {
   45504          18 :             if (vec[i] < threshold_value)
   45505             :             {
   45506           6 :                vec[i] = snap_value;
   45507             :             }
   45508             :          }
   45509             : 
   45510           4 :          return T(1);
   45511             :       }
   45512             :    };
   45513             : 
   45514             :    template <typename T>
   45515             :    class threshold_above exprtk_final : public exprtk::igeneric_function<T>
   45516             :    {
   45517             :    public:
   45518             : 
   45519             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   45520             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   45521             :       typedef typename igfun_t::generic_type        generic_type;
   45522             :       typedef typename generic_type::scalar_view    scalar_t;
   45523             :       typedef typename generic_type::vector_view    vector_t;
   45524             : 
   45525             :       using igfun_t::operator();
   45526             : 
   45527          32 :       threshold_above()
   45528          64 :       : exprtk::igeneric_function<T>("VTT|VTTTT")
   45529             :       /*
   45530             :          Overloads:
   45531             :          0. VTT   - vector, TV, SV
   45532             :          1. VTTTT - vector, r0, r1, TV, SV
   45533             : 
   45534             :          Where:
   45535             :          TV - Threshold value
   45536             :          SV - Snap-to value
   45537             :       */
   45538          32 :       {}
   45539             : 
   45540           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   45541             :       {
   45542           4 :          vector_t vec(parameters[0]);
   45543             : 
   45544           8 :          const T threshold_value = (0 == ps_index) ?
   45545           1 :                                    scalar_t(parameters[1]) :
   45546           3 :                                    scalar_t(parameters[3]) ;
   45547             : 
   45548           4 :          const T snap_value = scalar_t(parameters.back());
   45549             : 
   45550           4 :          std::size_t r0 = 0;
   45551           4 :          std::size_t r1 = vec.size() - 1;
   45552             : 
   45553           4 :          if (
   45554           7 :               (1 == ps_index) &&
   45555           7 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   45556             :             )
   45557             :          {
   45558           0 :             return T(0);
   45559             :          }
   45560             : 
   45561          22 :          for (std::size_t i = r0; i <= r1; ++i)
   45562             :          {
   45563          18 :             if (vec[i] > threshold_value)
   45564             :             {
   45565           8 :                vec[i] = snap_value;
   45566             :             }
   45567             :          }
   45568             : 
   45569           4 :          return T(1);
   45570             :       }
   45571             :    };
   45572             : 
   45573             :    template <typename T>
   45574             :    struct package
   45575             :    {
   45576             :       all_true       <T> at;
   45577             :       all_false      <T> af;
   45578             :       any_true       <T> nt;
   45579             :       any_false      <T> nf;
   45580             :       count          <T>  c;
   45581             :       copy           <T> cp;
   45582             :       rol            <T> rl;
   45583             :       ror            <T> rr;
   45584             :       reverse        <T> rev;
   45585             :       shift_left     <T> sl;
   45586             :       shift_right    <T> sr;
   45587             :       sort           <T> st;
   45588             :       nthelement     <T> ne;
   45589             :       assign         <T> an;
   45590             :       iota           <T> ia;
   45591             :       sumk           <T> sk;
   45592             :       axpy           <T> b1_axpy;
   45593             :       axpby          <T> b1_axpby;
   45594             :       axpyz          <T> b1_axpyz;
   45595             :       axpbyz         <T> b1_axpbyz;
   45596             :       axpbsy         <T> b1_axpbsy;
   45597             :       axpbsyz        <T> b1_axpbsyz;
   45598             :       axpbz          <T> b1_axpbz;
   45599             :       diff           <T> df;
   45600             :       dot            <T> dt;
   45601             :       dotk           <T> dtk;
   45602             :       threshold_above<T> ta;
   45603             :       threshold_below<T> tb;
   45604             : 
   45605          32 :       bool register_package(exprtk::symbol_table<T>& symtab)
   45606             :       {
   45607             :          #define exprtk_register_function(FunctionName, FunctionType)                 \
   45608             :          if (!symtab.add_function(FunctionName,FunctionType))                         \
   45609             :          {                                                                            \
   45610             :             exprtk_debug((                                                            \
   45611             :               "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
   45612             :               FunctionName));                                                         \
   45613             :             return false;                                                             \
   45614             :          }                                                                            \
   45615             : 
   45616          96 :          exprtk_register_function("all_true"        , at        )
   45617          96 :          exprtk_register_function("all_false"       , af        )
   45618          96 :          exprtk_register_function("any_true"        , nt        )
   45619          96 :          exprtk_register_function("any_false"       , nf        )
   45620          96 :          exprtk_register_function("count"           , c         )
   45621          96 :          exprtk_register_function("copy"            , cp        )
   45622          96 :          exprtk_register_function("rotate_left"     , rl        )
   45623          96 :          exprtk_register_function("rol"             , rl        )
   45624          96 :          exprtk_register_function("rotate_right"    , rr        )
   45625          96 :          exprtk_register_function("ror"             , rr        )
   45626          96 :          exprtk_register_function("reverse"         , rev       )
   45627          96 :          exprtk_register_function("shftl"           , sl        )
   45628          96 :          exprtk_register_function("shftr"           , sr        )
   45629          96 :          exprtk_register_function("sort"            , st        )
   45630          96 :          exprtk_register_function("nth_element"     , ne        )
   45631          96 :          exprtk_register_function("assign"          , an        )
   45632          96 :          exprtk_register_function("iota"            , ia        )
   45633          96 :          exprtk_register_function("sumk"            , sk        )
   45634          96 :          exprtk_register_function("axpy"            , b1_axpy   )
   45635          96 :          exprtk_register_function("axpby"           , b1_axpby  )
   45636          96 :          exprtk_register_function("axpyz"           , b1_axpyz  )
   45637          96 :          exprtk_register_function("axpbyz"          , b1_axpbyz )
   45638          96 :          exprtk_register_function("axpbsy"          , b1_axpbsy )
   45639          96 :          exprtk_register_function("axpbsyz"         , b1_axpbsyz)
   45640          96 :          exprtk_register_function("axpbz"           , b1_axpbz  )
   45641          96 :          exprtk_register_function("diff"            , df        )
   45642          96 :          exprtk_register_function("dot"             , dt        )
   45643          96 :          exprtk_register_function("dotk"            , dtk       )
   45644          96 :          exprtk_register_function("threshold_above" , ta        )
   45645          96 :          exprtk_register_function("threshold_below" , tb        )
   45646             :          #undef exprtk_register_function
   45647             : 
   45648          32 :          return true;
   45649             :       }
   45650             :    };
   45651             : 
   45652             :    } // namespace exprtk::rtl::vecops
   45653             :    } // namespace exprtk::rtl
   45654             : }    // namespace exprtk
   45655             : #endif
   45656             : 
   45657             : namespace exprtk
   45658             : {
   45659             :    namespace information
   45660             :    {
   45661             :       using ::exprtk::details::char_cptr;
   45662             : 
   45663             :       static char_cptr library = "Mathematical Expression Toolkit";
   45664             :       static char_cptr version = "2.7182818284590452353602874713526624977"
   45665             :                                  "572470936999595749669676277240766303535"
   45666             :                                  "475945713821785251664274274663919320030"
   45667             :                                  "599218174135966290435729003342952605956";
   45668             :       static char_cptr date    = "20240101";
   45669             :       static char_cptr min_cpp = "199711L";
   45670             : 
   45671             :       static inline std::string data()
   45672             :       {
   45673             :          static const std::string info_str = std::string(library) +
   45674             :                                              std::string(" v") + std::string(version) +
   45675             :                                              std::string(" (") + date + std::string(")") +
   45676             :                                              std::string(" (") + min_cpp + std::string(")");
   45677             :          return info_str;
   45678             :       }
   45679             : 
   45680             :    } // namespace information
   45681             : 
   45682             :    #ifdef exprtk_debug
   45683             :    #undef exprtk_debug
   45684             :    #endif
   45685             : 
   45686             :    #ifdef exprtk_error_location
   45687             :    #undef exprtk_error_location
   45688             :    #endif
   45689             : 
   45690             :    #ifdef exprtk_fallthrough
   45691             :    #undef exprtk_fallthrough
   45692             :    #endif
   45693             : 
   45694             :    #ifdef exprtk_override
   45695             :    #undef exprtk_override
   45696             :    #endif
   45697             : 
   45698             :    #ifdef exprtk_final
   45699             :    #undef exprtk_final
   45700             :    #endif
   45701             : 
   45702             :    #ifdef exprtk_delete
   45703             :    #undef exprtk_delete
   45704             :    #endif
   45705             : 
   45706             : } // namespace exprtk
   45707             : 
   45708             : #endif

Generated by: LCOV version 1.14