Exprtk Code Coverage Report
Current view: exprtk.hpp Hit Total Coverage
Lines: 12573 16723 75.2 %
Functions: 12366 21550 57.4 %

          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    47997062 :       inline bool is_whitespace(const char_t c)
      98             :       {
      99    44818619 :          return (' '  == c) || ('\n' == c) ||
     100    44812791 :                 ('\r' == c) || ('\t' == c) ||
     101    92815681 :                 ('\b' == c) || ('\v' == c) ||
     102    47997062 :                 ('\f' == c) ;
     103             :       }
     104             : 
     105    15625846 :       inline bool is_operator_char(const char_t c)
     106             :       {
     107    14556021 :          return ('+' == c) || ('-' == c) ||
     108    13011259 :                 ('*' == c) || ('/' == c) ||
     109    12223976 :                 ('^' == c) || ('<' == c) ||
     110    12204251 :                 ('>' == c) || ('=' == c) ||
     111    11687914 :                 (',' == c) || ('!' == c) ||
     112     8692981 :                 ('(' == c) || (')' == c) ||
     113     5623285 :                 ('[' == c) || (']' == c) ||
     114     5497105 :                 ('{' == c) || ('}' == c) ||
     115     5460353 :                 ('%' == c) || (':' == c) ||
     116     5354403 :                 ('?' == c) || ('&' == c) ||
     117    30181867 :                 ('|' == c) || (';' == c) ;
     118             :       }
     119             : 
     120    33648717 :       inline bool is_letter(const char_t c)
     121             :       {
     122    34209631 :          return (('a' <= c) && (c <= 'z')) ||
     123    34209631 :                 (('A' <= c) && (c <= 'Z')) ;
     124             :       }
     125             : 
     126    23601291 :       inline bool is_digit(const char_t c)
     127             :       {
     128    23601291 :          return ('0' <= c) && (c <= '9');
     129             :       }
     130             : 
     131    11437838 :       inline bool is_letter_or_digit(const char_t c)
     132             :       {
     133    11437838 :          return is_letter(c) || is_digit(c);
     134             :       }
     135             : 
     136    33165997 :       inline bool is_left_bracket(const char_t c)
     137             :       {
     138    33165997 :          return ('(' == c) || ('[' == c) || ('{' == c);
     139             :       }
     140             : 
     141    37098029 :       inline bool is_right_bracket(const char_t c)
     142             :       {
     143    37098029 :          return (')' == c) || (']' == c) || ('}' == c);
     144             :       }
     145             : 
     146    12225347 :       inline bool is_bracket(const char_t c)
     147             :       {
     148    12225347 :          return is_left_bracket(c) || is_right_bracket(c);
     149             :       }
     150             : 
     151        2372 :       inline bool is_sign(const char_t c)
     152             :       {
     153        2372 :          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      374377 :       inline bool is_valid_string_char(const char_t c)
     170             :       {
     171      374677 :          return std::isprint(static_cast<uchar_t>(c)) ||
     172      374677 :                 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    55081489 :       inline bool imatch(const std::string& s1, const std::string& s2)
     190             :       {
     191    55081489 :          if (s1.size() == s2.size())
     192             :          {
     193     5874282 :             for (std::size_t i = 0; i < s1.size(); ++i)
     194             :             {
     195     5339113 :                if (std::tolower(s1[i]) != std::tolower(s2[i]))
     196             :                {
     197     4219270 :                   return false;
     198             :                }
     199             :             }
     200             : 
     201      535169 :             return true;
     202             :          }
     203             : 
     204    50327050 :          return false;
     205             :       }
     206             : 
     207             :       struct ilesscompare
     208             :       {
     209   163945958 :          inline bool operator() (const std::string& s1, const std::string& s2) const
     210             :          {
     211   163945958 :             const std::size_t length = std::min(s1.size(),s2.size());
     212             : 
     213   253463675 :             for (std::size_t i = 0; i < length;  ++i)
     214             :             {
     215   210766833 :                const char_t c1 = static_cast<char_t>(std::tolower(s1[i]));
     216   210766833 :                const char_t c2 = static_cast<char_t>(std::tolower(s2[i]));
     217             : 
     218   210766833 :                if (c1 < c2)
     219    65131182 :                   return true;
     220   145635651 :                else if (c2 < c1)
     221    56117934 :                   return false;
     222             :             }
     223             : 
     224    42696842 :             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     2090511 :       inline bool is_valid_sf_symbol(const std::string& symbol)
     252             :       {
     253             :          // Special function: $f12 or $F34
     254     2090511 :          return (4 == symbol.size())  &&
     255       11322 :                 ('$' == symbol[0])    &&
     256        8490 :                 imatch('f',symbol[1]) &&
     257     2101833 :                 is_digit(symbol[2])   &&
     258     2094756 :                 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      395685 :          {
     397      395685 :             data_.reserve(initial_size);
     398      395685 :          }
     399             : 
     400      852151 :          inline build_string& operator << (const std::string& s)
     401             :          {
     402      852151 :             data_ += s;
     403      852151 :             return (*this);
     404             :          }
     405             : 
     406     1247836 :          inline build_string& operator << (char_cptr s)
     407             :          {
     408     1247836 :             data_ += std::string(s);
     409     1247836 :             return (*this);
     410             :          }
     411             : 
     412      395685 :          inline operator std::string () const
     413             :          {
     414      395685 :             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             :          "break",  "case",  "continue",  "default",  "false",  "for",
     430             :          "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
     431             :          "not",  "null",  "or",   "repeat", "return",  "shl",  "shr",
     432             :          "swap", "switch", "true",  "until", "var",  "while", "xnor",
     433             :          "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", "atan",
     441             :          "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
     442             :          "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
     443             :          "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
     444             :          "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      102400 :          for (std::size_t i = 0; i < reserved_words_size; ++i)
     513             :          {
     514       99200 :             if (imatch(symbol, reserved_words[i]))
     515             :             {
     516           0 :                return true;
     517             :             }
     518             :          }
     519             : 
     520        3200 :          return false;
     521             :       }
     522             : 
     523       72299 :       inline bool is_reserved_symbol(const std::string& symbol)
     524             :       {
     525     6362266 :          for (std::size_t i = 0; i < reserved_symbols_size; ++i)
     526             :          {
     527     6289990 :             if (imatch(symbol, reserved_symbols[i]))
     528             :             {
     529          23 :                return true;
     530             :             }
     531             :          }
     532             : 
     533       72276 :          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       15660 :          static inline bool cmp(const char_t c0, const char_t c1)
     578             :          {
     579       15660 :             return (c0 == c1);
     580             :          }
     581             :       };
     582             : 
     583             :       struct cis_match
     584             :       {
     585       15660 :          static inline bool cmp(const char_t c0, const char_t c1)
     586             :          {
     587       15660 :             return (std::tolower(c0) == std::tolower(c1));
     588             :          }
     589             :       };
     590             : 
     591             :       template <typename Iterator, typename Compare>
     592        5930 :       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        5930 :          const Iterator null_itr(0);
     602             : 
     603        5930 :          Iterator p_itr  = pattern_begin;
     604        5930 :          Iterator d_itr  = data_begin;
     605        5930 :          Iterator np_itr = null_itr;
     606        5930 :          Iterator nd_itr = null_itr;
     607             : 
     608       23710 :          for ( ; ; )
     609             :          {
     610       29640 :             if (p_itr != pattern_end)
     611             :             {
     612       23660 :                const type c = *(p_itr);
     613             : 
     614       23660 :                if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c)))
     615             :                {
     616       18490 :                   ++d_itr;
     617       18490 :                   ++p_itr;
     618       18490 :                   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        5980 :             else if (data_end == d_itr)
     642        5820 :                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        5820 :          return true;
     652             :       }
     653             : 
     654        2965 :       inline bool wc_match(const std::string& wild_card,
     655             :                            const std::string& str)
     656             :       {
     657             :          return match_impl<char_cptr,cs_match>
     658        5930 :                 (
     659             :                    wild_card.data(),
     660        2965 :                    wild_card.data() + wild_card.size(),
     661             :                    str.data(),
     662        2965 :                    str.data() + str.size(),
     663        5930 :                    '*', '?'
     664        2965 :                 );
     665             :       }
     666             : 
     667        2965 :       inline bool wc_imatch(const std::string& wild_card,
     668             :                             const std::string& str)
     669             :       {
     670             :          return match_impl<char_cptr,cis_match>
     671        5930 :                 (
     672             :                    wild_card.data(),
     673        2965 :                    wild_card.data() + wild_card.size(),
     674             :                    str.data(),
     675        2965 :                    str.data() + str.size(),
     676        5930 :                    '*', '?'
     677        2965 :                 );
     678             :       }
     679             : 
     680        3327 :       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        3327 :          if (str.empty())
     686             :          {
     687          15 :             return ("Z" == pattern);
     688             :          }
     689        3312 :          else if ('*' == pattern[0])
     690           0 :             return false;
     691             : 
     692             :          typedef std::string::const_iterator itr_t;
     693             : 
     694        3312 :          itr_t p_itr = pattern.begin();
     695        3312 :          itr_t s_itr = str    .begin();
     696             : 
     697        3312 :          const itr_t p_end = pattern.end();
     698        3312 :          const itr_t s_end = str    .end();
     699             : 
     700        9957 :          while ((s_end != s_itr) && (p_end != p_itr))
     701             :          {
     702        7206 :             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        7176 :             else if (
     727       14352 :                       ('?' != *p_itr) &&
     728        7176 :                       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        6615 :             ++p_itr;
     738        6615 :             ++s_itr;
     739             :          }
     740             : 
     741             :          return (
     742        4706 :                   (s_end == s_itr) &&
     743             :                   (
     744        1928 :                     (p_end ==  p_itr) ||
     745          27 :                     ('*'   == *p_itr)
     746             :                   )
     747        2751 :                 );
     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        1756 :       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        1756 :       inline void set_zero_value(T* data, const std::size_t size)
     781             :       {
     782        1756 :          set_zero_value_impl<T>::process(data,size);
     783        1756 :       }
     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   305796690 :             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      261959 :             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      106458 :             inline int to_int32_impl(const T v, real_type_tag)
     880             :             {
     881      106458 :                return static_cast<int>(v);
     882             :             }
     883             : 
     884             :             template <typename T>
     885       55013 :             inline _int64_t to_int64_impl(const T v, real_type_tag)
     886             :             {
     887       55013 :                return static_cast<_int64_t>(v);
     888             :             }
     889             : 
     890             :             template <typename T>
     891    32863778 :             inline _uint64_t to_uint64_impl(const T v, real_type_tag)
     892             :             {
     893    32863778 :                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    11957591 :             inline T abs_impl(const T v, real_type_tag)
     910             :             {
     911    11957591 :                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      261938 :             inline T equal_impl(const T v0, const T v1, real_type_tag)
     928             :             {
     929      261938 :                const T epsilon = epsilon_type<T>::value();
     930      261938 :                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      118114 :             inline T modulus_impl(const T v0, const T v1, real_type_tag)
     984             :             {
     985      118114 :                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        7384 :             inline T pow_impl(const T v0, const T v1, real_type_tag)
     996             :             {
     997        7384 :                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    30000002 :             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    30000002 :             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    30000002 :                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           0 :             inline T ncdf_impl(const T v, real_type_tag)
    1310             :             {
    1311           0 :                const T cnd = T(0.5) * (T(1) +
    1312           0 :                              erf_impl(abs_impl(v,real_type_tag()) /
    1313             :                                       T(numeric::constant::sqrt2),real_type_tag()));
    1314           0 :                return  (v < T(0)) ? (T(1) - cnd) : cnd;
    1315             :             }
    1316             : 
    1317             :             template <typename T>
    1318             :             inline T ncdf_impl(const T v, int_type_tag)
    1319             :             {
    1320             :                return ncdf_impl(static_cast<double>(v),real_type_tag());
    1321             :             }
    1322             : 
    1323             :             template <typename T>
    1324           0 :             inline T sinc_impl(const T v, real_type_tag)
    1325             :             {
    1326           0 :                if (std::abs(v) >= std::numeric_limits<T>::epsilon())
    1327           0 :                    return(std::sin(v) / v);
    1328             :                else
    1329           0 :                   return T(1);
    1330             :             }
    1331             : 
    1332             :             template <typename T>
    1333             :             inline T sinc_impl(const T v, int_type_tag)
    1334             :             {
    1335             :                return sinc_impl(static_cast<double>(v),real_type_tag());
    1336             :             }
    1337             : 
    1338           0 :             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
    1339          15 :             template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
    1340           0 :             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
    1341          15 :             template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
    1342           0 :             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
    1343          15 :             template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
    1344          60 :             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
    1345    40000462 :             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
    1346          15 :             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
    1347          32 :             template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
    1348          60 :             template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
    1349         175 :             template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
    1350         175 :             template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
    1351          10 :             template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
    1352       96742 :             template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
    1353           0 :             template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
    1354   144040506 :             template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
    1355          15 :             template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
    1356     6002408 :             template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
    1357          27 :             template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
    1358          15 :             template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
    1359           0 :             template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
    1360           0 :             template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
    1361           0 :             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
    1362           0 :             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
    1363          90 :             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
    1364           0 :             template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); }
    1365           0 :             template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); }
    1366         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)); }
    1367         695 :             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
    1368       20599 :             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
    1369             : 
    1370           1 :             template <typename T> inline T   const_pi_impl(real_type_tag) { return T(numeric::constant::pi);            }
    1371             :             template <typename T> inline T    const_e_impl(real_type_tag) { return T(numeric::constant::e);             }
    1372             :             template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1373             : 
    1374             :             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
    1375             :             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
    1376             :             template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
    1377             :             template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
    1378             :             template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
    1379             :             template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
    1380             :             template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
    1381             :             template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
    1382             :             template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
    1383             :             template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
    1384             :             template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
    1385             :             template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
    1386             :             template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
    1387             :             template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
    1388             :             template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1389             :             template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1390             :             template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1391             :             template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1392             :             template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1393             :             template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1394             :             template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1395             :             template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1396             :             template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1397             :             template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1398             :             template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1399             :             template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1400             :             template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1401             :             template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1402             :             template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
    1403             : 
    1404             :             template <typename T>
    1405       87271 :             inline bool is_integer_impl(const T& v, real_type_tag)
    1406             :             {
    1407       87271 :                return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
    1408             :             }
    1409             : 
    1410             :             template <typename T>
    1411             :             inline bool is_integer_impl(const T&, int_type_tag)
    1412             :             {
    1413             :                return true;
    1414             :             }
    1415             :          }
    1416             : 
    1417             :          template <typename Type>
    1418             :          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
    1419             : 
    1420             :          template <> struct numeric_info<int        > { enum { length = 10, size = 16, bound_length = 9 }; };
    1421             :          template <> struct numeric_info<float      > { enum { min_exp =  -38, max_exp =  +38 }; };
    1422             :          template <> struct numeric_info<double     > { enum { min_exp = -308, max_exp = +308 }; };
    1423             :          template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; };
    1424             : 
    1425             :          template <typename T>
    1426      106458 :          inline int to_int32(const T v)
    1427             :          {
    1428      106458 :             const typename details::number_type<T>::type num_type;
    1429      106458 :             return to_int32_impl(v, num_type);
    1430             :          }
    1431             : 
    1432             :          template <typename T>
    1433       55013 :          inline _int64_t to_int64(const T v)
    1434             :          {
    1435       55013 :             const typename details::number_type<T>::type num_type;
    1436       55013 :             return to_int64_impl(v, num_type);
    1437             :          }
    1438             : 
    1439             :          template <typename T>
    1440    32863778 :          inline _uint64_t to_uint64(const T v)
    1441             :          {
    1442    32863778 :             const typename details::number_type<T>::type num_type;
    1443    32863778 :             return to_uint64_impl(v, num_type);
    1444             :          }
    1445             : 
    1446             :          template <typename T>
    1447         195 :          inline bool is_nan(const T v)
    1448             :          {
    1449         195 :             const typename details::number_type<T>::type num_type;
    1450         195 :             return is_nan_impl(v, num_type);
    1451             :          }
    1452             : 
    1453             :          template <typename T>
    1454             :          inline T min(const T v0, const T v1)
    1455             :          {
    1456             :             const typename details::number_type<T>::type num_type;
    1457             :             return min_impl(v0, v1, num_type);
    1458             :          }
    1459             : 
    1460             :          template <typename T>
    1461             :          inline T max(const T v0, const T v1)
    1462             :          {
    1463             :             const typename details::number_type<T>::type num_type;
    1464             :             return max_impl(v0, v1, num_type);
    1465             :          }
    1466             : 
    1467             :          template <typename T>
    1468      261938 :          inline T equal(const T v0, const T v1)
    1469             :          {
    1470      261938 :             const typename details::number_type<T>::type num_type;
    1471      261938 :             return equal_impl(v0, v1, num_type);
    1472             :          }
    1473             : 
    1474             :          template <typename T>
    1475          20 :          inline T nequal(const T v0, const T v1)
    1476             :          {
    1477          20 :             const typename details::number_type<T>::type num_type;
    1478          20 :             return nequal_impl(v0, v1, num_type);
    1479             :          }
    1480             : 
    1481             :          template <typename T>
    1482      118114 :          inline T modulus(const T v0, const T v1)
    1483             :          {
    1484      118114 :             const typename details::number_type<T>::type num_type;
    1485      118114 :             return modulus_impl(v0, v1, num_type);
    1486             :          }
    1487             : 
    1488             :          template <typename T>
    1489        7384 :          inline T pow(const T v0, const T v1)
    1490             :          {
    1491        7384 :             const typename details::number_type<T>::type num_type;
    1492        7384 :             return pow_impl(v0, v1, num_type);
    1493             :          }
    1494             : 
    1495             :          template <typename T>
    1496           0 :          inline T logn(const T v0, const T v1)
    1497             :          {
    1498           0 :             const typename details::number_type<T>::type num_type;
    1499           0 :             return logn_impl(v0, v1, num_type);
    1500             :          }
    1501             : 
    1502             :          template <typename T>
    1503         160 :          inline T root(const T v0, const T v1)
    1504             :          {
    1505         160 :             const typename details::number_type<T>::type num_type;
    1506         160 :             return root_impl(v0, v1, num_type);
    1507             :          }
    1508             : 
    1509             :          template <typename T>
    1510         120 :          inline T roundn(const T v0, const T v1)
    1511             :          {
    1512         120 :             const typename details::number_type<T>::type num_type;
    1513         240 :             return roundn_impl(v0, v1, num_type);
    1514             :          }
    1515             : 
    1516             :          template <typename T>
    1517          30 :          inline T hypot(const T v0, const T v1)
    1518             :          {
    1519          30 :             const typename details::number_type<T>::type num_type;
    1520          30 :             return hypot_impl(v0, v1, num_type);
    1521             :          }
    1522             : 
    1523             :          template <typename T>
    1524           0 :          inline T atan2(const T v0, const T v1)
    1525             :          {
    1526           0 :             const typename details::number_type<T>::type num_type;
    1527           0 :             return atan2_impl(v0, v1, num_type);
    1528             :          }
    1529             : 
    1530             :          template <typename T>
    1531           0 :          inline T shr(const T v0, const T v1)
    1532             :          {
    1533           0 :             const typename details::number_type<T>::type num_type;
    1534           0 :             return shr_impl(v0, v1, num_type);
    1535             :          }
    1536             : 
    1537             :          template <typename T>
    1538           0 :          inline T shl(const T v0, const T v1)
    1539             :          {
    1540           0 :             const typename details::number_type<T>::type num_type;
    1541           0 :             return shl_impl(v0, v1, num_type);
    1542             :          }
    1543             : 
    1544             :          template <typename T>
    1545         485 :          inline T and_opr(const T v0, const T v1)
    1546             :          {
    1547         485 :             const typename details::number_type<T>::type num_type;
    1548         485 :             return and_impl(v0, v1, num_type);
    1549             :          }
    1550             : 
    1551             :          template <typename T>
    1552         600 :          inline T nand_opr(const T v0, const T v1)
    1553             :          {
    1554         600 :             const typename details::number_type<T>::type num_type;
    1555         600 :             return nand_impl(v0, v1, num_type);
    1556             :          }
    1557             : 
    1558             :          template <typename T>
    1559         440 :          inline T or_opr(const T v0, const T v1)
    1560             :          {
    1561         440 :             const typename details::number_type<T>::type num_type;
    1562         440 :             return or_impl(v0, v1, num_type);
    1563             :          }
    1564             : 
    1565             :          template <typename T>
    1566         600 :          inline T nor_opr(const T v0, const T v1)
    1567             :          {
    1568         600 :             const typename details::number_type<T>::type num_type;
    1569         600 :             return nor_impl(v0, v1, num_type);
    1570             :          }
    1571             : 
    1572             :          template <typename T>
    1573         265 :          inline T xor_opr(const T v0, const T v1)
    1574             :          {
    1575         265 :             const typename details::number_type<T>::type num_type;
    1576         530 :             return xor_impl(v0, v1, num_type);
    1577             :          }
    1578             : 
    1579             :          template <typename T>
    1580          80 :          inline T xnor_opr(const T v0, const T v1)
    1581             :          {
    1582          80 :             const typename details::number_type<T>::type num_type;
    1583         160 :             return xnor_impl(v0, v1, num_type);
    1584             :          }
    1585             : 
    1586             :          template <typename T>
    1587       87271 :          inline bool is_integer(const T v)
    1588             :          {
    1589       87271 :             const typename details::number_type<T>::type num_type;
    1590       87271 :             return is_integer_impl(v, num_type);
    1591             :          }
    1592             : 
    1593             :          template <typename T, unsigned int N>
    1594             :          struct fast_exp
    1595             :          {
    1596        6615 :             static inline T result(T v)
    1597             :             {
    1598        6615 :                unsigned int k = N;
    1599        6615 :                T l = T(1);
    1600             : 
    1601       35475 :                while (k)
    1602             :                {
    1603       28860 :                   if (1 == (k % 2))
    1604             :                   {
    1605       17640 :                      l *= v;
    1606       17640 :                      --k;
    1607             :                   }
    1608             : 
    1609       28860 :                   v *= v;
    1610       28860 :                   k /= 2;
    1611             :                }
    1612             : 
    1613        6615 :                return l;
    1614             :             }
    1615             :          };
    1616             : 
    1617        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; } };
    1618        4455 :          template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } };
    1619       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; } };
    1620        6465 :          template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } };
    1621       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; } };
    1622       11730 :          template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } };
    1623       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; } };
    1624       24590 :          template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } };
    1625         241 :          template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v;     } };
    1626         120 :          template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v;         } };
    1627             :          template <typename T> struct fast_exp<T, 0> { static inline T result(const T  ) { return T(1);      } };
    1628             : 
    1629             :          #define exprtk_define_unary_function(FunctionName)        \
    1630             :          template <typename T>                                     \
    1631             :          inline T FunctionName (const T v)                         \
    1632             :          {                                                         \
    1633             :             const typename details::number_type<T>::type num_type; \
    1634             :             return  FunctionName##_impl(v,num_type);               \
    1635             :          }                                                         \
    1636             : 
    1637    11171717 :          exprtk_define_unary_function(abs  )
    1638           0 :          exprtk_define_unary_function(acos )
    1639          15 :          exprtk_define_unary_function(acosh)
    1640           0 :          exprtk_define_unary_function(asin )
    1641          15 :          exprtk_define_unary_function(asinh)
    1642           0 :          exprtk_define_unary_function(atan )
    1643          15 :          exprtk_define_unary_function(atanh)
    1644          60 :          exprtk_define_unary_function(ceil )
    1645    40000462 :          exprtk_define_unary_function(cos  )
    1646          15 :          exprtk_define_unary_function(cosh )
    1647          32 :          exprtk_define_unary_function(exp  )
    1648           0 :          exprtk_define_unary_function(expm1)
    1649          60 :          exprtk_define_unary_function(floor)
    1650         175 :          exprtk_define_unary_function(log  )
    1651         175 :          exprtk_define_unary_function(log10)
    1652          10 :          exprtk_define_unary_function(log2 )
    1653           0 :          exprtk_define_unary_function(log1p)
    1654       96742 :          exprtk_define_unary_function(neg  )
    1655           0 :          exprtk_define_unary_function(pos  )
    1656          60 :          exprtk_define_unary_function(round)
    1657   144040506 :          exprtk_define_unary_function(sin  )
    1658           0 :          exprtk_define_unary_function(sinc )
    1659          15 :          exprtk_define_unary_function(sinh )
    1660     6002408 :          exprtk_define_unary_function(sqrt )
    1661          27 :          exprtk_define_unary_function(tan  )
    1662          15 :          exprtk_define_unary_function(tanh )
    1663           0 :          exprtk_define_unary_function(cot  )
    1664           0 :          exprtk_define_unary_function(sec  )
    1665           0 :          exprtk_define_unary_function(csc  )
    1666           0 :          exprtk_define_unary_function(r2d  )
    1667          90 :          exprtk_define_unary_function(d2r  )
    1668           0 :          exprtk_define_unary_function(d2g  )
    1669           0 :          exprtk_define_unary_function(g2d  )
    1670         728 :          exprtk_define_unary_function(notl )
    1671         153 :          exprtk_define_unary_function(sgn  )
    1672    30000002 :          exprtk_define_unary_function(erf  )
    1673    30000002 :          exprtk_define_unary_function(erfc )
    1674           0 :          exprtk_define_unary_function(ncdf )
    1675         695 :          exprtk_define_unary_function(frac )
    1676       20599 :          exprtk_define_unary_function(trunc)
    1677             :          #undef exprtk_define_unary_function
    1678             :       }
    1679             : 
    1680             :       template <typename T>
    1681     2703833 :       inline T compute_pow10(T d, const int exponent)
    1682             :       {
    1683             :          static const double fract10[] =
    1684             :          {
    1685             :             0.0,
    1686             :             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,
    1687             :             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,
    1688             :             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,
    1689             :             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,
    1690             :             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,
    1691             :             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,
    1692             :             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,
    1693             :             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,
    1694             :             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,
    1695             :             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,
    1696             :             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,
    1697             :             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,
    1698             :             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,
    1699             :             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,
    1700             :             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,
    1701             :             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,
    1702             :             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,
    1703             :             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,
    1704             :             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,
    1705             :             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,
    1706             :             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,
    1707             :             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,
    1708             :             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,
    1709             :             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,
    1710             :             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,
    1711             :             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,
    1712             :             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,
    1713             :             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,
    1714             :             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,
    1715             :             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,
    1716             :             1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
    1717             :          };
    1718             : 
    1719             :          static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
    1720             : 
    1721     2703833 :          const int e = std::abs(exponent);
    1722             : 
    1723     2703833 :          if (exponent >= std::numeric_limits<T>::min_exponent10)
    1724             :          {
    1725     2703827 :             if (e < fract10_size)
    1726             :             {
    1727     2703827 :                if (exponent > 0)
    1728        1674 :                   return T(d * fract10[e]);
    1729             :                else
    1730     2702153 :                   return T(d / fract10[e]);
    1731             :             }
    1732             :             else
    1733           0 :                return T(d * std::pow(10.0, 10.0 * exponent));
    1734             :          }
    1735             :          else
    1736             :          {
    1737           6 :                      d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
    1738           6 :             return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
    1739             :          }
    1740             :       }
    1741             : 
    1742             :       template <typename Iterator, typename T>
    1743        1858 :       inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
    1744             :       {
    1745        1858 :          if (itr == end)
    1746           0 :             return false;
    1747             : 
    1748        1858 :          const bool negative = ('-' == (*itr));
    1749             : 
    1750        1858 :          if (negative || ('+' == (*itr)))
    1751             :          {
    1752        1626 :             if (end == ++itr)
    1753          14 :                return false;
    1754             :          }
    1755             : 
    1756             :          static const uchar_t zero = static_cast<uchar_t>('0');
    1757             : 
    1758        2090 :          while ((end != itr) && (zero == (*itr))) ++itr;
    1759             : 
    1760        1844 :          bool return_result = true;
    1761        1844 :          unsigned int digit = 0;
    1762        1844 :          const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
    1763             : 
    1764        1844 :          if (length <= 4)
    1765             :          {
    1766        1844 :             switch (length)
    1767             :             {
    1768             :                #ifdef exprtk_use_lut
    1769             : 
    1770             :                #define exprtk_process_digit                          \
    1771             :                if ((digit = details::digit_table[(int)*itr++]) < 10) \
    1772             :                   result = result * 10 + (digit);                    \
    1773             :                else                                                  \
    1774             :                {                                                     \
    1775             :                   return_result = false;                             \
    1776             :                   break;                                             \
    1777             :                }                                                     \
    1778             :                exprtk_fallthrough                                    \
    1779             : 
    1780             :                #else
    1781             : 
    1782             :                #define exprtk_process_digit        \
    1783             :                if ((digit = (*itr++ - zero)) < 10) \
    1784             :                   result = result * T(10) + digit; \
    1785             :                else                                \
    1786             :                {                                   \
    1787             :                   return_result = false;           \
    1788             :                   break;                           \
    1789             :                }                                   \
    1790             :                exprtk_fallthrough                  \
    1791             : 
    1792             :                #endif
    1793             : 
    1794           0 :                case 4 : exprtk_process_digit
    1795          12 :                case 3 : exprtk_process_digit
    1796          38 :                case 2 : exprtk_process_digit
    1797        1680 :                case 1 : if ((digit = (*itr - zero))>= 10)
    1798             :                         {
    1799           0 :                            digit = 0;
    1800           0 :                            return_result = false;
    1801             :                         }
    1802             : 
    1803             :                #undef exprtk_process_digit
    1804             :             }
    1805             :          }
    1806             :          else
    1807           0 :             return_result = false;
    1808             : 
    1809        1844 :          if (length && return_result)
    1810             :          {
    1811        1680 :             result = result * 10 + static_cast<T>(digit);
    1812        1680 :             ++itr;
    1813             :          }
    1814             : 
    1815        1844 :          result = negative ? -result : result;
    1816        1844 :          return return_result;
    1817             :       }
    1818             : 
    1819             :       template <typename Iterator, typename T>
    1820           0 :       static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
    1821             :       {
    1822             :          typedef typename std::iterator_traits<Iterator>::value_type type;
    1823             : 
    1824             :          static const std::size_t nan_length = 3;
    1825             : 
    1826           0 :          if (std::distance(itr,end) != static_cast<int>(nan_length))
    1827           0 :             return false;
    1828             : 
    1829           0 :          if (static_cast<type>('n') == (*itr))
    1830             :          {
    1831           0 :             if (
    1832           0 :                  (static_cast<type>('a') != *(itr + 1)) ||
    1833           0 :                  (static_cast<type>('n') != *(itr + 2))
    1834             :                )
    1835             :             {
    1836           0 :                return false;
    1837             :             }
    1838             :          }
    1839           0 :          else if (
    1840           0 :                    (static_cast<type>('A') != *(itr + 1)) ||
    1841           0 :                    (static_cast<type>('N') != *(itr + 2))
    1842             :                  )
    1843             :          {
    1844           0 :             return false;
    1845             :          }
    1846             : 
    1847           0 :          t = std::numeric_limits<T>::quiet_NaN();
    1848             : 
    1849           0 :          return true;
    1850             :       }
    1851             : 
    1852             :       template <typename Iterator, typename T>
    1853           0 :       static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative)
    1854             :       {
    1855             :          static const char_t inf_uc[] = "INFINITY";
    1856             :          static const char_t inf_lc[] = "infinity";
    1857             :          static const std::size_t inf_length = 8;
    1858             : 
    1859           0 :          const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
    1860             : 
    1861           0 :          if ((3 != length) && (inf_length != length))
    1862           0 :             return false;
    1863             : 
    1864           0 :          char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
    1865             : 
    1866           0 :          while (end != itr)
    1867             :          {
    1868           0 :             if (*inf_itr == static_cast<char_t>(*itr))
    1869             :             {
    1870           0 :                ++itr;
    1871           0 :                ++inf_itr;
    1872           0 :                continue;
    1873             :             }
    1874             :             else
    1875           0 :                return false;
    1876             :          }
    1877             : 
    1878           0 :          if (negative)
    1879           0 :             t = -std::numeric_limits<T>::infinity();
    1880             :          else
    1881           0 :             t =  std::numeric_limits<T>::infinity();
    1882             : 
    1883           0 :          return true;
    1884             :       }
    1885             : 
    1886             :       template <typename T>
    1887     6421065 :       inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
    1888             :       {
    1889             :          using namespace details::numeric;
    1890     6421065 :          return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp);
    1891             :       }
    1892             : 
    1893             :       template <typename Iterator, typename T>
    1894     3718926 :       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
    1895             :       {
    1896     3718926 :          if (end == itr_external) return false;
    1897             : 
    1898     3718926 :          Iterator itr = itr_external;
    1899             : 
    1900     3718926 :          T d = T(0);
    1901             : 
    1902     3718926 :          const bool negative = ('-' == (*itr));
    1903             : 
    1904     3718926 :          if (negative || '+' == (*itr))
    1905             :          {
    1906           0 :             if (end == ++itr)
    1907           0 :                return false;
    1908             :          }
    1909             : 
    1910     3718926 :          bool instate = false;
    1911             : 
    1912             :          static const char_t zero = static_cast<uchar_t>('0');
    1913             : 
    1914             :          #define parse_digit_1(d)          \
    1915             :          if ((digit = (*itr - zero)) < 10) \
    1916             :             { d = d * T(10) + digit; }     \
    1917             :          else                              \
    1918             :             { break; }                     \
    1919             :          if (end == ++itr) break;          \
    1920             : 
    1921             :          #define parse_digit_2(d)          \
    1922             :          if ((digit = (*itr - zero)) < 10) \
    1923             :             { d = d * T(10) + digit; }     \
    1924             :          else                              \
    1925             :             { break; }                     \
    1926             :             ++itr;                         \
    1927             : 
    1928     3718926 :          if ('.' != (*itr))
    1929             :          {
    1930     3718663 :             const Iterator curr = itr;
    1931             : 
    1932    10546409 :             while ((end != itr) && (zero == (*itr))) ++itr;
    1933             : 
    1934     3908533 :             while (end != itr)
    1935             :             {
    1936             :                unsigned int digit;
    1937     3847085 :                parse_digit_1(d)
    1938     2658037 :                parse_digit_1(d)
    1939      356531 :                parse_digit_2(d)
    1940             :             }
    1941             : 
    1942     3718663 :             if (curr != itr) instate = true;
    1943             :          }
    1944             : 
    1945     3718926 :          int exponent = 0;
    1946             : 
    1947     3718926 :          if (end != itr)
    1948             :          {
    1949     2703561 :             if ('.' == (*itr))
    1950             :             {
    1951     2703347 :                const Iterator curr = ++itr;
    1952     2703347 :                T tmp_d = T(0);
    1953             : 
    1954     8793589 :                while (end != itr)
    1955             :                {
    1956             :                   unsigned int digit;
    1957     6769095 :                   parse_digit_1(tmp_d)
    1958     6331664 :                   parse_digit_1(tmp_d)
    1959     6090246 :                   parse_digit_2(tmp_d)
    1960             :                }
    1961             : 
    1962     2703347 :                if (curr != itr)
    1963             :                {
    1964     2702153 :                   instate = true;
    1965             : 
    1966     2702153 :                   const int frac_exponent = static_cast<int>(-std::distance(curr, itr));
    1967             : 
    1968     2702153 :                   if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag()))
    1969           0 :                      return false;
    1970             : 
    1971     2702153 :                   d += compute_pow10(tmp_d, frac_exponent);
    1972             :                }
    1973             : 
    1974             :                #undef parse_digit_1
    1975             :                #undef parse_digit_2
    1976             :             }
    1977             : 
    1978     2703561 :             if (end != itr)
    1979             :             {
    1980        1858 :                typename std::iterator_traits<Iterator>::value_type c = (*itr);
    1981             : 
    1982        1858 :                if (('e' == c) || ('E' == c))
    1983             :                {
    1984        1858 :                   int exp = 0;
    1985             : 
    1986        1858 :                   if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
    1987             :                   {
    1988          14 :                      if (end == itr)
    1989          14 :                         return false;
    1990             :                      else
    1991           0 :                         c = (*itr);
    1992             :                   }
    1993             : 
    1994        1844 :                   exponent += exp;
    1995             :                }
    1996             : 
    1997        1844 :                if (end != itr)
    1998             :                {
    1999           0 :                   if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
    2000           0 :                      ++itr;
    2001           0 :                   else if ('#' == c)
    2002             :                   {
    2003           0 :                      if (end == ++itr)
    2004           0 :                         return false;
    2005           0 :                      else if (('I' <= (*itr)) && ((*itr) <= 'n'))
    2006             :                      {
    2007           0 :                         if (('i' == (*itr)) || ('I' == (*itr)))
    2008             :                         {
    2009           0 :                            return parse_inf(itr, end, t, negative);
    2010             :                         }
    2011           0 :                         else if (('n' == (*itr)) || ('N' == (*itr)))
    2012             :                         {
    2013           0 :                            return parse_nan(itr, end, t);
    2014             :                         }
    2015             :                         else
    2016           0 :                            return false;
    2017             :                      }
    2018             :                      else
    2019           0 :                         return false;
    2020             :                   }
    2021           0 :                   else if (('I' <= (*itr)) && ((*itr) <= 'n'))
    2022             :                   {
    2023           0 :                      if (('i' == (*itr)) || ('I' == (*itr)))
    2024             :                      {
    2025           0 :                         return parse_inf(itr, end, t, negative);
    2026             :                      }
    2027           0 :                      else if (('n' == (*itr)) || ('N' == (*itr)))
    2028             :                      {
    2029           0 :                         return parse_nan(itr, end, t);
    2030             :                      }
    2031             :                      else
    2032           0 :                         return false;
    2033             :                   }
    2034             :                   else
    2035           0 :                      return false;
    2036             :                }
    2037             :             }
    2038             :          }
    2039             : 
    2040     3718912 :          if ((end != itr) || (!instate))
    2041           0 :             return false;
    2042     3718912 :          else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
    2043           0 :             return false;
    2044     3718912 :          else if (exponent)
    2045        1680 :             d = compute_pow10(d,exponent);
    2046             : 
    2047     3718912 :          t = static_cast<T>((negative) ? -d : d);
    2048     3718912 :          return true;
    2049             :       }
    2050             : 
    2051             :       template <typename T>
    2052     3718926 :       inline bool string_to_real(const std::string& s, T& t)
    2053             :       {
    2054     3718926 :          const typename numeric::details::number_type<T>::type num_type;
    2055             : 
    2056     3718926 :          char_cptr begin = s.data();
    2057     3718926 :          char_cptr end   = s.data() + s.size();
    2058             : 
    2059     7437852 :          return string_to_real(begin, end, t, num_type);
    2060             :       }
    2061             : 
    2062             :       template <typename T>
    2063             :       struct functor_t
    2064             :       {
    2065             :          /*
    2066             :             Note: The following definitions for Type, may require tweaking
    2067             :                   based on the compiler and target architecture. The benchmark
    2068             :                   should provide enough information to make the right choice.
    2069             :          */
    2070             :          //typedef T Type;
    2071             :          //typedef const T Type;
    2072             :          typedef const T& Type;
    2073             :          typedef       T& RefType;
    2074             :          typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
    2075             :          typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
    2076             :          typedef T (*bfunc_t)(Type t0, Type t1);
    2077             :          typedef T (*ufunc_t)(Type t0);
    2078             :       };
    2079             : 
    2080             :    } // namespace details
    2081             : 
    2082             :    struct loop_runtime_check
    2083             :    {
    2084             :       enum loop_types
    2085             :       {
    2086             :          e_invalid           = 0,
    2087             :          e_for_loop          = 1,
    2088             :          e_while_loop        = 2,
    2089             :          e_repeat_until_loop = 4,
    2090             :          e_all_loops         = 7
    2091             :       };
    2092             : 
    2093             :       enum violation_type
    2094             :       {
    2095             :           e_unknown         = 0,
    2096             :           e_iteration_count = 1,
    2097             :           e_timeout         = 2
    2098             :       };
    2099             : 
    2100             :       loop_types loop_set;
    2101             : 
    2102             :       loop_runtime_check()
    2103             :       : loop_set(e_invalid)
    2104             :       , max_loop_iterations(0)
    2105             :       {}
    2106             : 
    2107             :       details::_uint64_t max_loop_iterations;
    2108             : 
    2109             :       struct violation_context
    2110             :       {
    2111             :          loop_types loop;
    2112             :          violation_type violation;
    2113             :          details::_uint64_t iteration_count;
    2114             :       };
    2115             : 
    2116             :       virtual bool check()
    2117             :       {
    2118             :          return true;
    2119             :       }
    2120             : 
    2121             :       virtual void handle_runtime_violation(const violation_context&)
    2122             :       {
    2123             :          throw std::runtime_error("ExprTk Loop runtime violation.");
    2124             :       }
    2125             : 
    2126             :       virtual ~loop_runtime_check()
    2127             :       {}
    2128             :    };
    2129             : 
    2130             :    typedef loop_runtime_check* loop_runtime_check_ptr;
    2131             : 
    2132             :    struct vector_access_runtime_check
    2133             :    {
    2134             :       struct violation_context
    2135             :       {
    2136             :          void* base_ptr;
    2137             :          void* end_ptr;
    2138             :          void* access_ptr;
    2139             :          std::size_t type_size;
    2140             :       };
    2141             : 
    2142          70 :       virtual ~vector_access_runtime_check()
    2143          70 :       {}
    2144             : 
    2145           0 :       virtual bool handle_runtime_violation(violation_context& /*context*/)
    2146             :       {
    2147           0 :          throw std::runtime_error("ExprTk runtime vector access violation.");
    2148             :          #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    2149             :          return false;
    2150             :          #endif
    2151             :       }
    2152             :    };
    2153             : 
    2154             :    typedef vector_access_runtime_check* vector_access_runtime_check_ptr;
    2155             : 
    2156             :    struct compilation_check
    2157             :    {
    2158             :       struct compilation_context
    2159             :       {
    2160             :          std::string error_message;
    2161             :       };
    2162             : 
    2163             :       virtual bool continue_compilation(compilation_context& /*context*/) = 0;
    2164             : 
    2165             :       virtual ~compilation_check()
    2166             :       {}
    2167             :    };
    2168             : 
    2169             :    typedef compilation_check* compilation_check_ptr;
    2170             : 
    2171             :    namespace lexer
    2172             :    {
    2173             :       struct token
    2174             :       {
    2175             :          enum token_type
    2176             :          {
    2177             :             e_none        =   0, e_error       =   1, e_err_symbol  =   2,
    2178             :             e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
    2179             :             e_eof         =   6, e_number      =   7, e_symbol      =   8,
    2180             :             e_string      =   9, e_assign      =  10, e_addass      =  11,
    2181             :             e_subass      =  12, e_mulass      =  13, e_divass      =  14,
    2182             :             e_modass      =  15, e_shr         =  16, e_shl         =  17,
    2183             :             e_lte         =  18, e_ne          =  19, e_gte         =  20,
    2184             :             e_swap        =  21, e_lt          = '<', e_gt          = '>',
    2185             :             e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
    2186             :             e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
    2187             :             e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
    2188             :             e_sub         = '-', e_div         = '/', e_mul         = '*',
    2189             :             e_mod         = '%', e_pow         = '^', e_colon       = ':',
    2190             :             e_ternary     = '?'
    2191             :          };
    2192             : 
    2193   126187847 :          token()
    2194   126187847 :          : type(e_none)
    2195   252375694 :          , value("")
    2196   126187847 :          , position(std::numeric_limits<std::size_t>::max())
    2197   126187847 :          {}
    2198             : 
    2199      370650 :          void clear()
    2200             :          {
    2201      370650 :             type     = e_none;
    2202      370650 :             value    = "";
    2203      370650 :             position = std::numeric_limits<std::size_t>::max();
    2204      370650 :          }
    2205             : 
    2206             :          template <typename Iterator>
    2207    10731345 :          inline token& set_operator(const token_type tt,
    2208             :                                     const Iterator begin, const Iterator end,
    2209             :                                     const Iterator base_begin = Iterator(0))
    2210             :          {
    2211    10731345 :             type = tt;
    2212    10731345 :             value.assign(begin,end);
    2213    10731345 :             if (base_begin)
    2214    10731345 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2215    10731345 :             return (*this);
    2216             :          }
    2217             : 
    2218             :          template <typename Iterator>
    2219     3232120 :          inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
    2220             :          {
    2221     3232120 :             type = e_symbol;
    2222     3232120 :             value.assign(begin,end);
    2223     3232120 :             if (base_begin)
    2224     3232120 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2225     3232120 :             return (*this);
    2226             :          }
    2227             : 
    2228             :          template <typename Iterator>
    2229     1981715 :          inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
    2230             :          {
    2231     1981715 :             type = e_number;
    2232     1981715 :             value.assign(begin,end);
    2233     1981715 :             if (base_begin)
    2234     1981715 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2235     1981715 :             return (*this);
    2236             :          }
    2237             : 
    2238             :          template <typename Iterator>
    2239       49998 :          inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
    2240             :          {
    2241       49998 :             type = e_string;
    2242       49998 :             value.assign(begin,end);
    2243       49998 :             if (base_begin)
    2244       49998 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2245       49998 :             return (*this);
    2246             :          }
    2247             : 
    2248        1350 :          inline token& set_string(const std::string& s, const std::size_t p)
    2249             :          {
    2250        1350 :             type     = e_string;
    2251        1350 :             value    = s;
    2252        1350 :             position = p;
    2253        1350 :             return (*this);
    2254             :          }
    2255             : 
    2256             :          template <typename Iterator>
    2257         788 :          inline token& set_error(const token_type et,
    2258             :                                  const Iterator begin, const Iterator end,
    2259             :                                  const Iterator base_begin = Iterator(0))
    2260             :          {
    2261         788 :             if (
    2262         297 :                  (e_error      == et) ||
    2263         297 :                  (e_err_symbol == et) ||
    2264         237 :                  (e_err_number == et) ||
    2265           0 :                  (e_err_string == et) ||
    2266             :                  (e_err_sfunc  == et)
    2267             :                )
    2268             :             {
    2269         788 :                type = et;
    2270             :             }
    2271             :             else
    2272           0 :                type = e_error;
    2273             : 
    2274         788 :             value.assign(begin,end);
    2275             : 
    2276         788 :             if (base_begin)
    2277         788 :                position = static_cast<std::size_t>(std::distance(base_begin,begin));
    2278             : 
    2279         788 :             return (*this);
    2280             :          }
    2281             : 
    2282           0 :          static inline std::string to_str(token_type t)
    2283             :          {
    2284           0 :             switch (t)
    2285             :             {
    2286           0 :                case e_none        : return "NONE";
    2287           0 :                case e_error       : return "ERROR";
    2288           0 :                case e_err_symbol  : return "ERROR_SYMBOL";
    2289           0 :                case e_err_number  : return "ERROR_NUMBER";
    2290           0 :                case e_err_string  : return "ERROR_STRING";
    2291           0 :                case e_eof         : return "EOF";
    2292           0 :                case e_number      : return "NUMBER";
    2293           0 :                case e_symbol      : return "SYMBOL";
    2294           0 :                case e_string      : return "STRING";
    2295           0 :                case e_assign      : return ":=";
    2296           0 :                case e_addass      : return "+=";
    2297           0 :                case e_subass      : return "-=";
    2298           0 :                case e_mulass      : return "*=";
    2299           0 :                case e_divass      : return "/=";
    2300           0 :                case e_modass      : return "%=";
    2301           0 :                case e_shr         : return ">>";
    2302           0 :                case e_shl         : return "<<";
    2303           0 :                case e_lte         : return "<=";
    2304           0 :                case e_ne          : return "!=";
    2305           0 :                case e_gte         : return ">=";
    2306           0 :                case e_lt          : return "<";
    2307           0 :                case e_gt          : return ">";
    2308           0 :                case e_eq          : return "=";
    2309           0 :                case e_rbracket    : return ")";
    2310           0 :                case e_lbracket    : return "(";
    2311           0 :                case e_rsqrbracket : return "]";
    2312           0 :                case e_lsqrbracket : return "[";
    2313           0 :                case e_rcrlbracket : return "}";
    2314           0 :                case e_lcrlbracket : return "{";
    2315           0 :                case e_comma       : return ",";
    2316           0 :                case e_add         : return "+";
    2317           0 :                case e_sub         : return "-";
    2318           0 :                case e_div         : return "/";
    2319           0 :                case e_mul         : return "*";
    2320           0 :                case e_mod         : return "%";
    2321           0 :                case e_pow         : return "^";
    2322           0 :                case e_colon       : return ":";
    2323           0 :                case e_ternary     : return "?";
    2324           0 :                case e_swap        : return "<=>";
    2325           0 :                default            : return "UNKNOWN";
    2326             :             }
    2327             :          }
    2328             : 
    2329    16619812 :          inline bool is_error() const
    2330             :          {
    2331             :             return (
    2332    33238642 :                      (e_error      == type) ||
    2333    16618830 :                      (e_err_symbol == type) ||
    2334    16618830 :                      (e_err_number == type) ||
    2335    49856878 :                      (e_err_string == type) ||
    2336    16618236 :                      (e_err_sfunc  == type)
    2337    16619812 :                    );
    2338             :          }
    2339             : 
    2340             :          token_type type;
    2341             :          std::string value;
    2342             :          std::size_t position;
    2343             :       };
    2344             : 
    2345             :       class generator
    2346             :       {
    2347             :       public:
    2348             : 
    2349             :          typedef token token_t;
    2350             :          typedef std::vector<token_t> token_list_t;
    2351             :          typedef token_list_t::iterator token_list_itr_t;
    2352             :          typedef details::char_t char_t;
    2353             : 
    2354      106542 :          generator()
    2355      213084 :          : base_itr_(0)
    2356      106542 :          , s_itr_   (0)
    2357      106542 :          , s_end_   (0)
    2358             :          {
    2359      106542 :             clear();
    2360      106542 :          }
    2361             : 
    2362      106542 :          inline void clear()
    2363             :          {
    2364      106542 :             base_itr_ = 0;
    2365      106542 :             s_itr_    = 0;
    2366      106542 :             s_end_    = 0;
    2367      106542 :             token_list_.clear();
    2368      106542 :             token_itr_ = token_list_.end();
    2369      106542 :             store_token_itr_ = token_list_.end();
    2370      106542 :          }
    2371             : 
    2372      371453 :          inline bool process(const std::string& str)
    2373             :          {
    2374      371453 :             base_itr_ = str.data();
    2375      371453 :             s_itr_    = str.data();
    2376      371453 :             s_end_    = str.data() + str.size();
    2377             : 
    2378      371453 :             eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
    2379      371453 :             token_list_.clear();
    2380             : 
    2381    16915193 :             while (!is_end(s_itr_))
    2382             :             {
    2383    16544528 :                scan_token();
    2384             : 
    2385    16544528 :                if (!token_list_.empty() && token_list_.back().is_error())
    2386         788 :                   return false;
    2387             :             }
    2388             : 
    2389      370665 :             return true;
    2390             :          }
    2391             : 
    2392      370665 :          inline bool empty() const
    2393             :          {
    2394      370665 :             return token_list_.empty();
    2395             :          }
    2396             : 
    2397       78215 :          inline std::size_t size() const
    2398             :          {
    2399       78215 :             return token_list_.size();
    2400             :          }
    2401             : 
    2402      731590 :          inline void begin()
    2403             :          {
    2404      731590 :             token_itr_ = token_list_.begin();
    2405      731590 :             store_token_itr_ = token_list_.begin();
    2406      731590 :          }
    2407             : 
    2408             :          inline void store()
    2409             :          {
    2410             :             store_token_itr_ = token_itr_;
    2411             :          }
    2412             : 
    2413             :          inline void restore()
    2414             :          {
    2415             :             token_itr_ = store_token_itr_;
    2416             :          }
    2417             : 
    2418    13180715 :          inline token_t& next_token()
    2419             :          {
    2420    13180715 :             if (token_list_.end() != token_itr_)
    2421             :             {
    2422    12835326 :                return *token_itr_++;
    2423             :             }
    2424             :             else
    2425      345389 :                return eof_token_;
    2426             :          }
    2427             : 
    2428     5731826 :          inline token_t& peek_next_token()
    2429             :          {
    2430     5731826 :             if (token_list_.end() != token_itr_)
    2431             :             {
    2432     5698196 :                return *token_itr_;
    2433             :             }
    2434             :             else
    2435       33630 :                return eof_token_;
    2436             :          }
    2437             : 
    2438   105837414 :          inline token_t& operator[](const std::size_t& index)
    2439             :          {
    2440   105837414 :             if (index < token_list_.size())
    2441   105837414 :                return token_list_[index];
    2442             :             else
    2443           0 :                return eof_token_;
    2444             :          }
    2445             : 
    2446             :          inline token_t operator[](const std::size_t& index) const
    2447             :          {
    2448             :             if (index < token_list_.size())
    2449             :                return token_list_[index];
    2450             :             else
    2451             :                return eof_token_;
    2452             :          }
    2453             : 
    2454      391824 :          inline bool finished() const
    2455             :          {
    2456      391824 :             return (token_list_.end() == token_itr_);
    2457             :          }
    2458             : 
    2459        4056 :          inline void insert_front(token_t::token_type tk_type)
    2460             :          {
    2461        4056 :             if (
    2462        8112 :                  !token_list_.empty() &&
    2463        8112 :                  (token_list_.end() != token_itr_)
    2464             :                )
    2465             :             {
    2466        4056 :                token_t t = *token_itr_;
    2467             : 
    2468        4056 :                t.type     = tk_type;
    2469        4056 :                token_itr_ = token_list_.insert(token_itr_,t);
    2470        4056 :             }
    2471        4056 :          }
    2472             : 
    2473      405014 :          inline std::string substr(const std::size_t& begin, const std::size_t& end) const
    2474             :          {
    2475      405014 :             const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
    2476      405014 :             const details::char_cptr end_itr   = ((base_itr_ + end  ) < s_end_) ? (base_itr_ + end  ) : s_end_;
    2477             : 
    2478      810028 :             return std::string(begin_itr,end_itr);
    2479             :          }
    2480             : 
    2481             :          inline std::string remaining() const
    2482             :          {
    2483             :             if (finished())
    2484             :                return "";
    2485             :             else if (token_list_.begin() != token_itr_)
    2486             :                return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
    2487             :             else
    2488             :                return std::string(base_itr_ + token_itr_->position, s_end_);
    2489             :          }
    2490             : 
    2491             :       private:
    2492             : 
    2493    83027820 :          inline bool is_end(details::char_cptr itr) const
    2494             :          {
    2495    83027820 :             return (s_end_ == itr);
    2496             :          }
    2497             : 
    2498             :          #ifndef exprtk_disable_comments
    2499    15626143 :          inline bool is_comment_start(details::char_cptr itr) const
    2500             :          {
    2501    15626143 :             const char_t c0 = *(itr + 0);
    2502    15626143 :             const char_t c1 = *(itr + 1);
    2503             : 
    2504    15626143 :             if ('#' == c0)
    2505         243 :                return true;
    2506    15625900 :             else if (!is_end(itr + 1))
    2507             :             {
    2508    15287422 :                if (('/' == c0) && ('/' == c1)) return true;
    2509    15287402 :                if (('/' == c0) && ('*' == c1)) return true;
    2510             :             }
    2511    15625846 :             return false;
    2512             :          }
    2513             :          #else
    2514             :          inline bool is_comment_start(details::char_cptr) const
    2515             :          {
    2516             :             return false;
    2517             :          }
    2518             :          #endif
    2519             : 
    2520      918385 :          inline void skip_whitespace()
    2521             :          {
    2522     2077345 :             while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
    2523             :             {
    2524     1158960 :                ++s_itr_;
    2525             :             }
    2526      918385 :          }
    2527             : 
    2528         297 :          inline void skip_comments()
    2529             :          {
    2530             :             #ifndef exprtk_disable_comments
    2531             :             // The following comment styles are supported:
    2532             :             // 1. // .... \n
    2533             :             // 2. #  .... \n
    2534             :             // 3. /* .... */
    2535             :             struct test
    2536             :             {
    2537         297 :                static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
    2538             :                {
    2539         297 :                   mode = 0;
    2540         297 :                   if      ('#' == c0)    { mode = 1; incr = 1; }
    2541          54 :                   else if ('/' == c0)
    2542             :                   {
    2543          54 :                      if      ('/' == c1) { mode = 1; incr = 2; }
    2544          34 :                      else if ('*' == c1) { mode = 2; incr = 2; }
    2545             :                   }
    2546         297 :                   return (0 != mode);
    2547             :                }
    2548             : 
    2549       31112 :                static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
    2550             :                {
    2551       31112 :                   if (
    2552       31112 :                        ((1 == mode) && ('\n' == c0)) ||
    2553       31106 :                        ((2 == mode) && ( '*' == c0) && ('/' == c1))
    2554             :                      )
    2555             :                   {
    2556          23 :                      mode = 0;
    2557          23 :                      return true;
    2558             :                   }
    2559             :                   else
    2560       31089 :                      return false;
    2561             :                }
    2562             :             };
    2563             : 
    2564         297 :             int mode      = 0;
    2565         297 :             int increment = 0;
    2566             : 
    2567         297 :             if (is_end(s_itr_))
    2568          23 :                return;
    2569         297 :             else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
    2570           0 :                return;
    2571             : 
    2572         297 :             details::char_cptr cmt_start = s_itr_;
    2573             : 
    2574         297 :             s_itr_ += increment;
    2575             : 
    2576       31403 :             while (!is_end(s_itr_))
    2577             :             {
    2578       31129 :                if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
    2579             :                {
    2580           6 :                   ++s_itr_;
    2581           6 :                   return;
    2582             :                }
    2583             : 
    2584       31123 :                if ((2 == mode))
    2585             :                {
    2586        1664 :                   if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
    2587             :                   {
    2588          17 :                      s_itr_ += 2;
    2589          17 :                      return;
    2590             :                   }
    2591             :                }
    2592             : 
    2593       31106 :                ++s_itr_;
    2594             :             }
    2595             : 
    2596         274 :             if (2 == mode)
    2597             :             {
    2598          17 :                token_t t;
    2599          17 :                t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
    2600          17 :                token_list_.push_back(t);
    2601          17 :             }
    2602             :             #endif
    2603             :          }
    2604             : 
    2605    16544528 :          inline void scan_token()
    2606             :          {
    2607    16544528 :             const char_t c = *s_itr_;
    2608             : 
    2609    16544528 :             if (details::is_whitespace(c))
    2610             :             {
    2611      918385 :                skip_whitespace();
    2612      918385 :                return;
    2613             :             }
    2614    15626143 :             else if (is_comment_start(s_itr_))
    2615             :             {
    2616         297 :                skip_comments();
    2617         297 :                return;
    2618             :             }
    2619    15625846 :             else if (details::is_operator_char(c))
    2620             :             {
    2621    10360969 :                scan_operator();
    2622    10360969 :                return;
    2623             :             }
    2624     5264877 :             else if (details::is_letter(c))
    2625             :             {
    2626     3215996 :                scan_symbol();
    2627     3215996 :                return;
    2628             :             }
    2629     2048881 :             else if (details::is_digit(c) || ('.' == c))
    2630             :             {
    2631     1981775 :                scan_number();
    2632     1981775 :                return;
    2633             :             }
    2634       67106 :             else if ('$' == c)
    2635             :             {
    2636        4245 :                scan_special_function();
    2637        4245 :                return;
    2638             :             }
    2639             :             #ifndef exprtk_disable_string_capabilities
    2640       62861 :             else if ('\'' == c)
    2641             :             {
    2642       51585 :                scan_string();
    2643       51585 :                return;
    2644             :             }
    2645             :             #endif
    2646       11276 :             else if ('~' == c)
    2647             :             {
    2648       10802 :                token_t t;
    2649       10802 :                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
    2650       10802 :                token_list_.push_back(t);
    2651       10802 :                ++s_itr_;
    2652       10802 :                return;
    2653       10802 :             }
    2654             :             else
    2655             :             {
    2656         474 :                token_t t;
    2657         474 :                t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
    2658         474 :                token_list_.push_back(t);
    2659         474 :                ++s_itr_;
    2660         474 :             }
    2661             :          }
    2662             : 
    2663    10360969 :          inline void scan_operator()
    2664             :          {
    2665    10360969 :             token_t t;
    2666             : 
    2667    10360969 :             const char_t c0 = s_itr_[0];
    2668             : 
    2669    10360969 :             if (!is_end(s_itr_ + 1))
    2670             :             {
    2671    10045911 :                const char_t c1 = s_itr_[1];
    2672             : 
    2673    10045911 :                if (!is_end(s_itr_ + 2))
    2674             :                {
    2675     9783192 :                   const char_t c2 = s_itr_[2];
    2676             : 
    2677     9783192 :                   if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
    2678             :                   {
    2679        2728 :                      t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
    2680        2728 :                      token_list_.push_back(t);
    2681        2728 :                      s_itr_ += 3;
    2682        2728 :                      return;
    2683             :                   }
    2684             :                }
    2685             : 
    2686    10043183 :                token_t::token_type ttype = token_t::e_none;
    2687             : 
    2688    10043183 :                if      ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
    2689    10040967 :                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
    2690    10040287 :                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
    2691    10040197 :                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
    2692    10037242 :                else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
    2693     9978449 :                else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
    2694     9913293 :                else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
    2695     9913293 :                else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
    2696     9913293 :                else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
    2697     9903373 :                else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
    2698     9902331 :                else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
    2699     9901991 :                else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
    2700     9901654 :                else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
    2701             : 
    2702    10043183 :                if (token_t::e_none != ttype)
    2703             :                {
    2704      141529 :                   t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
    2705      141529 :                   token_list_.push_back(t);
    2706      141529 :                   s_itr_ += 2;
    2707      141529 :                   return;
    2708             :                }
    2709             :             }
    2710             : 
    2711    10216712 :             if ('<' == c0)
    2712        7281 :                t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
    2713    10209431 :             else if ('>' == c0)
    2714        6730 :                t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
    2715    10202701 :             else if (';' == c0)
    2716       88449 :                t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
    2717    10114252 :             else if ('&' == c0)
    2718         657 :                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
    2719    10113595 :             else if ('|' == c0)
    2720         420 :                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
    2721             :             else
    2722    10113175 :                t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
    2723             : 
    2724    10216712 :             token_list_.push_back(t);
    2725    10216712 :             ++s_itr_;
    2726    10360969 :          }
    2727             : 
    2728     3215996 :          inline void scan_symbol()
    2729             :          {
    2730     3215996 :             details::char_cptr initial_itr = s_itr_;
    2731             : 
    2732     8730049 :             while (!is_end(s_itr_))
    2733             :             {
    2734     8717849 :                if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
    2735             :                {
    2736     3205316 :                   if ('.' != (*s_itr_))
    2737     3203796 :                      break;
    2738             :                   /*
    2739             :                      Permit symbols that contain a 'dot'
    2740             :                      Allowed   : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
    2741             :                      Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
    2742             :                   */
    2743        1520 :                   if (
    2744        3040 :                        (s_itr_ != initial_itr)                     &&
    2745        1520 :                        !is_end(s_itr_ + 1)                         &&
    2746        3040 :                        !details::is_letter_or_digit(*(s_itr_ + 1)) &&
    2747           0 :                        ('_' != (*(s_itr_ + 1)))
    2748             :                      )
    2749           0 :                      break;
    2750             :                }
    2751             : 
    2752     5514053 :                ++s_itr_;
    2753             :             }
    2754             : 
    2755     3215996 :             token_t t;
    2756     3215996 :             t.set_symbol(initial_itr, s_itr_, base_itr_);
    2757     3215996 :             token_list_.push_back(t);
    2758     3215996 :          }
    2759             : 
    2760     1981775 :          inline void scan_number()
    2761             :          {
    2762             :             /*
    2763             :                Attempt to match a valid numeric value in one of the following formats:
    2764             :                (01) 123456
    2765             :                (02) 123456.
    2766             :                (03) 123.456
    2767             :                (04) 123.456e3
    2768             :                (05) 123.456E3
    2769             :                (06) 123.456e+3
    2770             :                (07) 123.456E+3
    2771             :                (08) 123.456e-3
    2772             :                (09) 123.456E-3
    2773             :                (00) .1234
    2774             :                (11) .1234e3
    2775             :                (12) .1234E+3
    2776             :                (13) .1234e+3
    2777             :                (14) .1234E-3
    2778             :                (15) .1234e-3
    2779             :             */
    2780             : 
    2781     1981775 :             details::char_cptr initial_itr = s_itr_;
    2782     1981775 :             bool dot_found                 = false;
    2783     1981775 :             bool e_found                   = false;
    2784     1981775 :             bool post_e_sign_found         = false;
    2785     1981775 :             bool post_e_digit_found        = false;
    2786     1981775 :             token_t t;
    2787             : 
    2788    18807312 :             while (!is_end(s_itr_))
    2789             :             {
    2790    18791653 :                if ('.' == (*s_itr_))
    2791             :                {
    2792     1438917 :                   if (dot_found)
    2793             :                   {
    2794           0 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2795           0 :                      token_list_.push_back(t);
    2796             : 
    2797           0 :                      return;
    2798             :                   }
    2799             : 
    2800     1438917 :                   dot_found = true;
    2801     1438917 :                   ++s_itr_;
    2802             : 
    2803     1438917 :                   continue;
    2804             :                }
    2805    17352736 :                else if ('e' == std::tolower(*s_itr_))
    2806             :                {
    2807        1010 :                   const char_t& c = *(s_itr_ + 1);
    2808             : 
    2809        1010 :                   if (is_end(s_itr_ + 1))
    2810             :                   {
    2811           0 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2812           0 :                      token_list_.push_back(t);
    2813             : 
    2814           0 :                      return;
    2815             :                   }
    2816        1010 :                   else if (
    2817        1213 :                             ('+' != c) &&
    2818        1200 :                             ('-' != c) &&
    2819         190 :                             !details::is_digit(c)
    2820             :                           )
    2821             :                   {
    2822          60 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2823          60 :                      token_list_.push_back(t);
    2824             : 
    2825          60 :                      return;
    2826             :                   }
    2827             : 
    2828         950 :                   e_found = true;
    2829         950 :                   ++s_itr_;
    2830             : 
    2831         950 :                   continue;
    2832         950 :                }
    2833    17351726 :                else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
    2834             :                {
    2835         820 :                   if (post_e_sign_found)
    2836             :                   {
    2837           0 :                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
    2838           0 :                      token_list_.push_back(t);
    2839             : 
    2840           0 :                      return;
    2841             :                   }
    2842             : 
    2843         820 :                   post_e_sign_found = true;
    2844         820 :                   ++s_itr_;
    2845             : 
    2846         820 :                   continue;
    2847             :                }
    2848    17350906 :                else if (e_found && details::is_digit(*s_itr_))
    2849             :                {
    2850        1008 :                   post_e_digit_found = true;
    2851        1008 :                   ++s_itr_;
    2852             : 
    2853        1008 :                   continue;
    2854             :                }
    2855    17349898 :                else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
    2856     1966056 :                   break;
    2857             :                else
    2858    15383842 :                   ++s_itr_;
    2859             :             }
    2860             : 
    2861     1981715 :             t.set_numeric(initial_itr, s_itr_, base_itr_);
    2862     1981715 :             token_list_.push_back(t);
    2863             : 
    2864     1981715 :             return;
    2865     1981775 :          }
    2866             : 
    2867        4245 :          inline void scan_special_function()
    2868             :          {
    2869        4245 :             details::char_cptr initial_itr = s_itr_;
    2870        4245 :             token_t t;
    2871             : 
    2872             :             // $fdd(x,x,x) = at least 11 chars
    2873        8490 :             if (std::distance(s_itr_,s_end_) < 11)
    2874             :             {
    2875           0 :                t.set_error(
    2876             :                   token::e_err_sfunc,
    2877           0 :                   initial_itr, std::min(initial_itr + 11, s_end_),
    2878             :                   base_itr_);
    2879           0 :                token_list_.push_back(t);
    2880             : 
    2881           0 :                return;
    2882             :             }
    2883             : 
    2884        4245 :             if (
    2885        8490 :                  !(('$' == *s_itr_)                       &&
    2886        4245 :                    (details::imatch  ('f',*(s_itr_ + 1))) &&
    2887        4245 :                    (details::is_digit(*(s_itr_ + 2)))     &&
    2888        4245 :                    (details::is_digit(*(s_itr_ + 3))))
    2889             :                )
    2890             :             {
    2891           0 :                t.set_error(
    2892             :                   token::e_err_sfunc,
    2893           0 :                   initial_itr, std::min(initial_itr + 4, s_end_),
    2894             :                   base_itr_);
    2895           0 :                token_list_.push_back(t);
    2896             : 
    2897           0 :                return;
    2898             :             }
    2899             : 
    2900        4245 :             s_itr_ += 4; // $fdd = 4chars
    2901             : 
    2902        4245 :             t.set_symbol(initial_itr, s_itr_, base_itr_);
    2903        4245 :             token_list_.push_back(t);
    2904             : 
    2905        4245 :             return;
    2906        4245 :          }
    2907             : 
    2908             :          #ifndef exprtk_disable_string_capabilities
    2909       51585 :          inline void scan_string()
    2910             :          {
    2911       51585 :             details::char_cptr initial_itr = s_itr_ + 1;
    2912       51585 :             token_t t;
    2913             : 
    2914      103170 :             if (std::distance(s_itr_,s_end_) < 2)
    2915             :             {
    2916           1 :                t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
    2917           1 :                token_list_.push_back(t);
    2918             : 
    2919           1 :                return;
    2920             :             }
    2921             : 
    2922       51584 :             ++s_itr_;
    2923             : 
    2924       51584 :             bool escaped_found = false;
    2925       51584 :             bool escaped = false;
    2926             : 
    2927      374613 :             while (!is_end(s_itr_))
    2928             :             {
    2929      374377 :                if (!details::is_valid_string_char(*s_itr_))
    2930             :                {
    2931           0 :                   t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    2932           0 :                   token_list_.push_back(t);
    2933             : 
    2934           0 :                   return;
    2935             :                }
    2936      374377 :                else if (!escaped && ('\\' == *s_itr_))
    2937             :                {
    2938        3050 :                   escaped_found = true;
    2939        3050 :                   escaped = true;
    2940        3050 :                   ++s_itr_;
    2941             : 
    2942        3050 :                   continue;
    2943             :                }
    2944      371327 :                else if (!escaped)
    2945             :                {
    2946      368277 :                   if ('\'' == *s_itr_)
    2947       51348 :                      break;
    2948             :                }
    2949        3050 :                else if (escaped)
    2950             :                {
    2951        3050 :                   if (
    2952        5150 :                        !is_end(s_itr_) && ('0' == *(s_itr_)) &&
    2953        2100 :                        ((s_itr_ + 4) <= s_end_)
    2954             :                      )
    2955             :                   {
    2956        2100 :                      const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1)));
    2957             : 
    2958        4200 :                      const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
    2959        2100 :                                               details::is_hex_digit(*(s_itr_ + 3)) ;
    2960             : 
    2961        2100 :                      if (!(x_separator && both_digits))
    2962             :                      {
    2963           0 :                         t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    2964           0 :                         token_list_.push_back(t);
    2965             : 
    2966           0 :                         return;
    2967             :                      }
    2968             :                      else
    2969        2100 :                         s_itr_ += 3;
    2970             :                   }
    2971             : 
    2972        3050 :                   escaped = false;
    2973             :                }
    2974             : 
    2975      319979 :                ++s_itr_;
    2976             :             }
    2977             : 
    2978       51584 :             if (is_end(s_itr_))
    2979             :             {
    2980         236 :                t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    2981         236 :                token_list_.push_back(t);
    2982             : 
    2983         236 :                return;
    2984             :             }
    2985             : 
    2986       51348 :             if (!escaped_found)
    2987       49998 :                t.set_string(initial_itr, s_itr_, base_itr_);
    2988             :             else
    2989             :             {
    2990        1350 :                std::string parsed_string(initial_itr,s_itr_);
    2991             : 
    2992        1350 :                if (!details::cleanup_escapes(parsed_string))
    2993             :                {
    2994           0 :                   t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
    2995           0 :                   token_list_.push_back(t);
    2996             : 
    2997           0 :                   return;
    2998             :                }
    2999             : 
    3000        1350 :                t.set_string(
    3001             :                   parsed_string,
    3002        2700 :                   static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
    3003        1350 :             }
    3004             : 
    3005       51348 :             token_list_.push_back(t);
    3006       51348 :             ++s_itr_;
    3007             : 
    3008       51348 :             return;
    3009       51585 :          }
    3010             :          #endif
    3011             : 
    3012             :       private:
    3013             : 
    3014             :          token_list_t       token_list_;
    3015             :          token_list_itr_t   token_itr_;
    3016             :          token_list_itr_t   store_token_itr_;
    3017             :          token_t            eof_token_;
    3018             :          details::char_cptr base_itr_;
    3019             :          details::char_cptr s_itr_;
    3020             :          details::char_cptr s_end_;
    3021             : 
    3022             :          friend class token_scanner;
    3023             :          friend class token_modifier;
    3024             :          friend class token_inserter;
    3025             :          friend class token_joiner;
    3026             :       }; // class generator
    3027             : 
    3028             :       class helper_interface
    3029             :       {
    3030             :       public:
    3031             : 
    3032           0 :          virtual void init()                     {              }
    3033     2205329 :          virtual void reset()                    {              }
    3034     1482646 :          virtual bool result()                   { return true; }
    3035           0 :          virtual std::size_t process(generator&) { return 0;    }
    3036      852336 :          virtual ~helper_interface()             {              }
    3037             :       };
    3038             : 
    3039             :       class token_scanner : public helper_interface
    3040             :       {
    3041             :       public:
    3042             : 
    3043      426168 :          virtual ~token_scanner()
    3044      426168 :          {}
    3045             : 
    3046      426168 :          explicit token_scanner(const std::size_t& stride)
    3047      426168 :          : stride_(stride)
    3048             :          {
    3049      426168 :             if (stride > 4)
    3050             :             {
    3051           0 :                throw std::invalid_argument("token_scanner() - Invalid stride value");
    3052             :             }
    3053      426168 :          }
    3054             : 
    3055     1463997 :          inline std::size_t process(generator& g) exprtk_override
    3056             :          {
    3057     1463997 :             if (g.token_list_.size() >= stride_)
    3058             :             {
    3059    59337645 :                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
    3060             :                {
    3061    57880722 :                   token t;
    3062             : 
    3063    57880722 :                   switch (stride_)
    3064             :                   {
    3065    31128133 :                      case 1 :
    3066             :                               {
    3067    31128133 :                                  const token& t0 = g.token_list_[i];
    3068             : 
    3069    31128133 :                                  if (!operator()(t0))
    3070             :                                  {
    3071        4797 :                                     return i;
    3072             :                                  }
    3073             :                               }
    3074    31123336 :                               break;
    3075             : 
    3076    13633795 :                      case 2 :
    3077             :                               {
    3078    13633795 :                                  const token& t0 = g.token_list_[i    ];
    3079    13633795 :                                  const token& t1 = g.token_list_[i + 1];
    3080             : 
    3081    13633795 :                                  if (!operator()(t0, t1))
    3082             :                                  {
    3083           0 :                                     return i;
    3084             :                                  }
    3085             :                               }
    3086    13633795 :                               break;
    3087             : 
    3088    13118794 :                      case 3 :
    3089             :                               {
    3090    13118794 :                                  const token& t0 = g.token_list_[i    ];
    3091    13118794 :                                  const token& t1 = g.token_list_[i + 1];
    3092    13118794 :                                  const token& t2 = g.token_list_[i + 2];
    3093             : 
    3094    13118794 :                                  if (!operator()(t0, t1, t2))
    3095             :                                  {
    3096           0 :                                     return i;
    3097             :                                  }
    3098             :                               }
    3099    13118794 :                               break;
    3100             : 
    3101           0 :                      case 4 :
    3102             :                               {
    3103           0 :                                  const token& t0 = g.token_list_[i    ];
    3104           0 :                                  const token& t1 = g.token_list_[i + 1];
    3105           0 :                                  const token& t2 = g.token_list_[i + 2];
    3106           0 :                                  const token& t3 = g.token_list_[i + 3];
    3107             : 
    3108           0 :                                  if (!operator()(t0, t1, t2, t3))
    3109             :                                  {
    3110           0 :                                     return i;
    3111             :                                  }
    3112             :                               }
    3113           0 :                               break;
    3114             :                   }
    3115    57880722 :                }
    3116             :             }
    3117             : 
    3118     1459200 :             return (g.token_list_.size() - stride_ + 1);
    3119             :          }
    3120             : 
    3121           0 :          virtual bool operator() (const token&)
    3122             :          {
    3123           0 :             return false;
    3124             :          }
    3125             : 
    3126           0 :          virtual bool operator() (const token&, const token&)
    3127             :          {
    3128           0 :             return false;
    3129             :          }
    3130             : 
    3131           0 :          virtual bool operator() (const token&, const token&, const token&)
    3132             :          {
    3133           0 :             return false;
    3134             :          }
    3135             : 
    3136           0 :          virtual bool operator() (const token&, const token&, const token&, const token&)
    3137             :          {
    3138           0 :             return false;
    3139             :          }
    3140             : 
    3141             :       private:
    3142             : 
    3143             :          const std::size_t stride_;
    3144             :       }; // class token_scanner
    3145             : 
    3146             :       class token_modifier : public helper_interface
    3147             :       {
    3148             :       public:
    3149             : 
    3150      370664 :          inline std::size_t process(generator& g) exprtk_override
    3151             :          {
    3152      370664 :             std::size_t changes = 0;
    3153             : 
    3154    16061854 :             for (std::size_t i = 0; i < g.token_list_.size(); ++i)
    3155             :             {
    3156    15691190 :                if (modify(g.token_list_[i])) changes++;
    3157             :             }
    3158             : 
    3159      370664 :             return changes;
    3160             :          }
    3161             : 
    3162             :          virtual bool modify(token& t) = 0;
    3163             :       };
    3164             : 
    3165             :       class token_inserter : public helper_interface
    3166             :       {
    3167             :       public:
    3168             : 
    3169      106542 :          explicit token_inserter(const std::size_t& stride)
    3170      106542 :          : stride_(stride)
    3171             :          {
    3172      106542 :             if (stride > 5)
    3173             :             {
    3174           0 :                throw std::invalid_argument("token_inserter() - Invalid stride value");
    3175             :             }
    3176      106542 :          }
    3177             : 
    3178      370654 :          inline std::size_t process(generator& g) exprtk_override
    3179             :          {
    3180      370654 :             if (g.token_list_.empty())
    3181           0 :                return 0;
    3182      370654 :             else if (g.token_list_.size() < stride_)
    3183         708 :                return 0;
    3184             : 
    3185      369946 :             std::size_t changes = 0;
    3186             : 
    3187             :             typedef std::pair<std::size_t, token> insert_t;
    3188      369946 :             std::vector<insert_t> insert_list;
    3189      369946 :             insert_list.reserve(10000);
    3190             : 
    3191    15547421 :             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
    3192             :             {
    3193    15177475 :                int insert_index = -1;
    3194    15177475 :                token t;
    3195             : 
    3196    15177475 :                switch (stride_)
    3197             :                {
    3198           0 :                   case 1 : insert_index = insert(g.token_list_[i],t);
    3199           0 :                            break;
    3200             : 
    3201    15177475 :                   case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
    3202    15177475 :                            break;
    3203             : 
    3204           0 :                   case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
    3205           0 :                            break;
    3206             : 
    3207           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);
    3208           0 :                            break;
    3209             : 
    3210           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);
    3211           0 :                            break;
    3212             :                }
    3213             : 
    3214    15177475 :                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
    3215             :                {
    3216      150383 :                   insert_list.push_back(insert_t(i, t));
    3217      150383 :                   changes++;
    3218             :                }
    3219    15177475 :             }
    3220             : 
    3221      369946 :             if (!insert_list.empty())
    3222             :             {
    3223       36509 :                generator::token_list_t token_list;
    3224             : 
    3225       36509 :                std::size_t insert_index = 0;
    3226             : 
    3227     4745650 :                for (std::size_t i = 0; i < g.token_list_.size(); ++i)
    3228             :                {
    3229     4709141 :                   token_list.push_back(g.token_list_[i]);
    3230             : 
    3231     4709141 :                   if (
    3232     6285125 :                        (insert_index < insert_list.size()) &&
    3233     1575984 :                        (insert_list[insert_index].first == i)
    3234             :                      )
    3235             :                   {
    3236      150383 :                      token_list.push_back(insert_list[insert_index].second);
    3237      150383 :                      insert_index++;
    3238             :                   }
    3239             :                }
    3240             : 
    3241       36509 :                std::swap(g.token_list_,token_list);
    3242       36509 :             }
    3243             : 
    3244      369946 :             return changes;
    3245      369946 :          }
    3246             : 
    3247             :          #define token_inserter_empty_body \
    3248             :          {                                 \
    3249             :             return -1;                     \
    3250             :          }                                 \
    3251             : 
    3252           0 :          inline virtual int insert(const token&, token&)
    3253           0 :          token_inserter_empty_body
    3254             : 
    3255           0 :          inline virtual int insert(const token&, const token&, token&)
    3256           0 :          token_inserter_empty_body
    3257             : 
    3258           0 :          inline virtual int insert(const token&, const token&, const token&, token&)
    3259           0 :          token_inserter_empty_body
    3260             : 
    3261           0 :          inline virtual int insert(const token&, const token&, const token&, const token&, token&)
    3262           0 :          token_inserter_empty_body
    3263             : 
    3264           0 :          inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
    3265           0 :          token_inserter_empty_body
    3266             : 
    3267             :          #undef token_inserter_empty_body
    3268             : 
    3269             :       private:
    3270             : 
    3271             :          const std::size_t stride_;
    3272             :       };
    3273             : 
    3274             :       class token_joiner : public helper_interface
    3275             :       {
    3276             :       public:
    3277             : 
    3278      213084 :          explicit token_joiner(const std::size_t& stride)
    3279      213084 :          : stride_(stride)
    3280      213084 :          {}
    3281             : 
    3282      741328 :          inline std::size_t process(generator& g) exprtk_override
    3283             :          {
    3284      741328 :             if (g.token_list_.empty())
    3285           0 :                return 0;
    3286             : 
    3287      741328 :             switch (stride_)
    3288             :             {
    3289      370664 :                case 2  : return process_stride_2(g);
    3290      370664 :                case 3  : return process_stride_3(g);
    3291           0 :                default : return 0;
    3292             :             }
    3293             :          }
    3294             : 
    3295           0 :          virtual bool join(const token&, const token&, token&)               { return false; }
    3296           0 :          virtual bool join(const token&, const token&, const token&, token&) { return false; }
    3297             : 
    3298             :       private:
    3299             : 
    3300      370664 :          inline std::size_t process_stride_2(generator& g)
    3301             :          {
    3302      370664 :             if (g.token_list_.size() < 2)
    3303         708 :                return 0;
    3304             : 
    3305      369956 :             std::size_t changes = 0;
    3306             : 
    3307      369956 :             generator::token_list_t token_list;
    3308      369956 :             token_list.reserve(10000);
    3309             : 
    3310    15684687 :             for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 1); ++i)
    3311             :             {
    3312    15314731 :                token t;
    3313             : 
    3314             :                for ( ; ; )
    3315             :                {
    3316    15320922 :                   if (!join(g[i], g[i + 1], t))
    3317             :                   {
    3318    15313685 :                      token_list.push_back(g[i]);
    3319    15313685 :                      break;
    3320             :                   }
    3321             : 
    3322        7237 :                   token_list.push_back(t);
    3323             : 
    3324        7237 :                   ++changes;
    3325             : 
    3326        7237 :                   i += 2;
    3327             : 
    3328        7237 :                   if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1))
    3329        1046 :                      break;
    3330             :                }
    3331    15314731 :             }
    3332             : 
    3333      369956 :             token_list.push_back(g.token_list_.back());
    3334             : 
    3335      369956 :             assert(token_list.size() <= g.token_list_.size());
    3336             : 
    3337      369956 :             std::swap(token_list, g.token_list_);
    3338             : 
    3339      369956 :             return changes;
    3340      369956 :          }
    3341             : 
    3342      370664 :          inline std::size_t process_stride_3(generator& g)
    3343             :          {
    3344      370664 :             if (g.token_list_.size() < 3)
    3345        1577 :                return 0;
    3346             : 
    3347      369087 :             std::size_t changes = 0;
    3348             : 
    3349      369087 :             generator::token_list_t token_list;
    3350      369087 :             token_list.reserve(10000);
    3351             : 
    3352    15319459 :             for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 2); ++i)
    3353             :             {
    3354    14950372 :                token t;
    3355             : 
    3356             :                for ( ; ; )
    3357             :                {
    3358    14950570 :                   if (!join(g[i], g[i + 1], g[i + 2], t))
    3359             :                   {
    3360    14950370 :                      token_list.push_back(g[i]);
    3361    14950370 :                      break;
    3362             :                   }
    3363             : 
    3364         200 :                   token_list.push_back(t);
    3365             : 
    3366         200 :                   ++changes;
    3367             : 
    3368         200 :                   i += 3;
    3369             : 
    3370         200 :                   if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2))
    3371           2 :                      break;
    3372             :                }
    3373    14950372 :             }
    3374             : 
    3375      369087 :             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
    3376      369087 :             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
    3377             : 
    3378      369087 :             assert(token_list.size() <= g.token_list_.size());
    3379             : 
    3380      369087 :             std::swap(token_list, g.token_list_);
    3381             : 
    3382      369087 :             return changes;
    3383      369087 :          }
    3384             : 
    3385             :          const std::size_t stride_;
    3386             :       };
    3387             : 
    3388             :       namespace helper
    3389             :       {
    3390             : 
    3391             :          inline void dump(const lexer::generator& generator)
    3392             :          {
    3393             :             for (std::size_t i = 0; i < generator.size(); ++i)
    3394             :             {
    3395             :                const lexer::token& t = generator[i];
    3396             :                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
    3397             :                       static_cast<int>(i),
    3398             :                       static_cast<int>(t.position),
    3399             :                       t.to_str(t.type).c_str(),
    3400             :                       t.value.c_str());
    3401             :             }
    3402             :          }
    3403             : 
    3404             :          class commutative_inserter : public lexer::token_inserter
    3405             :          {
    3406             :          public:
    3407             : 
    3408             :             using lexer::token_inserter::insert;
    3409             : 
    3410      106542 :             commutative_inserter()
    3411      106542 :             : lexer::token_inserter(2)
    3412      106542 :             {}
    3413             : 
    3414     3302771 :             inline void ignore_symbol(const std::string& symbol)
    3415             :             {
    3416     3302771 :                ignore_set_.insert(symbol);
    3417     3302771 :             }
    3418             : 
    3419    15177475 :             inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override
    3420             :             {
    3421    15177475 :                bool match         = false;
    3422    15177475 :                new_token.type     = lexer::token::e_mul;
    3423    15177475 :                new_token.value    = "*";
    3424    15177475 :                new_token.position = t1.position;
    3425             : 
    3426    15177475 :                if (t0.type == lexer::token::e_symbol)
    3427             :                {
    3428     3200869 :                   if (ignore_set_.end() != ignore_set_.find(t0.value))
    3429             :                   {
    3430       98509 :                      return -1;
    3431             :                   }
    3432     3102360 :                   else if (!t0.value.empty() && ('$' == t0.value[0]))
    3433             :                   {
    3434        4245 :                      return -1;
    3435             :                   }
    3436             :                }
    3437             : 
    3438    15074721 :                if (t1.type == lexer::token::e_symbol)
    3439             :                {
    3440     2843566 :                   if (ignore_set_.end() != ignore_set_.find(t1.value))
    3441             :                   {
    3442       70437 :                      return -1;
    3443             :                   }
    3444             :                }
    3445    15004284 :                if      ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
    3446    14901474 :                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
    3447    14859696 :                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
    3448    14859649 :                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
    3449    14859602 :                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
    3450    14859558 :                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
    3451    14858287 :                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
    3452    14858241 :                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
    3453    14858195 :                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
    3454    14854117 :                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
    3455    14854060 :                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
    3456    14854005 :                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_symbol     )) match = true;
    3457             : 
    3458    15004284 :                return (match) ? 1 : -1;
    3459             :             }
    3460             : 
    3461             :          private:
    3462             : 
    3463             :             std::set<std::string,details::ilesscompare> ignore_set_;
    3464             :          };
    3465             : 
    3466             :          class operator_joiner exprtk_final : public token_joiner
    3467             :          {
    3468             :          public:
    3469             : 
    3470      213084 :             explicit operator_joiner(const std::size_t& stride)
    3471      213084 :             : token_joiner(stride)
    3472      213084 :             {}
    3473             : 
    3474    15320922 :             inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override
    3475             :             {
    3476             :                // ': =' --> ':='
    3477    15320922 :                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
    3478             :                {
    3479           0 :                   t.type     = lexer::token::e_assign;
    3480           0 :                   t.value    = ":=";
    3481           0 :                   t.position = t0.position;
    3482             : 
    3483           0 :                   return true;
    3484             :                }
    3485             :                // '+ =' --> '+='
    3486    15320922 :                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
    3487             :                {
    3488           0 :                   t.type     = lexer::token::e_addass;
    3489           0 :                   t.value    = "+=";
    3490           0 :                   t.position = t0.position;
    3491             : 
    3492           0 :                   return true;
    3493             :                }
    3494             :                // '- =' --> '-='
    3495    15320922 :                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
    3496             :                {
    3497           0 :                   t.type     = lexer::token::e_subass;
    3498           0 :                   t.value    = "-=";
    3499           0 :                   t.position = t0.position;
    3500             : 
    3501           0 :                   return true;
    3502             :                }
    3503             :                // '* =' --> '*='
    3504    15320922 :                else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
    3505             :                {
    3506           0 :                   t.type     = lexer::token::e_mulass;
    3507           0 :                   t.value    = "*=";
    3508           0 :                   t.position = t0.position;
    3509             : 
    3510           0 :                   return true;
    3511             :                }
    3512             :                // '/ =' --> '/='
    3513    15320922 :                else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
    3514             :                {
    3515           0 :                   t.type     = lexer::token::e_divass;
    3516           0 :                   t.value    = "/=";
    3517           0 :                   t.position = t0.position;
    3518             : 
    3519           0 :                   return true;
    3520             :                }
    3521             :                // '% =' --> '%='
    3522    15320922 :                else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
    3523             :                {
    3524           0 :                   t.type     = lexer::token::e_modass;
    3525           0 :                   t.value    = "%=";
    3526           0 :                   t.position = t0.position;
    3527             : 
    3528           0 :                   return true;
    3529             :                }
    3530             :                // '> =' --> '>='
    3531    15320922 :                else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
    3532             :                {
    3533           0 :                   t.type     = lexer::token::e_gte;
    3534           0 :                   t.value    = ">=";
    3535           0 :                   t.position = t0.position;
    3536             : 
    3537           0 :                   return true;
    3538             :                }
    3539             :                // '< =' --> '<='
    3540    15320922 :                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
    3541             :                {
    3542           0 :                   t.type     = lexer::token::e_lte;
    3543           0 :                   t.value    = "<=";
    3544           0 :                   t.position = t0.position;
    3545             : 
    3546           0 :                   return true;
    3547             :                }
    3548             :                // '= =' --> '=='
    3549    15320922 :                else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
    3550             :                {
    3551           4 :                   t.type     = lexer::token::e_eq;
    3552           4 :                   t.value    = "==";
    3553           4 :                   t.position = t0.position;
    3554             : 
    3555           4 :                   return true;
    3556             :                }
    3557             :                // '! =' --> '!='
    3558    15320918 :                else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
    3559             :                {
    3560           0 :                   t.type     = lexer::token::e_ne;
    3561           0 :                   t.value    = "!=";
    3562           0 :                   t.position = t0.position;
    3563             : 
    3564           0 :                   return true;
    3565             :                }
    3566             :                // '< >' --> '<>'
    3567    15320918 :                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
    3568             :                {
    3569           0 :                   t.type     = lexer::token::e_ne;
    3570           0 :                   t.value    = "<>";
    3571           0 :                   t.position = t0.position;
    3572             : 
    3573           0 :                   return true;
    3574             :                }
    3575             :                // '<= >' --> '<=>'
    3576    15320918 :                else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
    3577             :                {
    3578           0 :                   t.type     = lexer::token::e_swap;
    3579           0 :                   t.value    = "<=>";
    3580           0 :                   t.position = t0.position;
    3581             : 
    3582           0 :                   return true;
    3583             :                }
    3584             :                // '+ -' --> '-'
    3585    15320918 :                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
    3586             :                {
    3587        3578 :                   t.type     = lexer::token::e_sub;
    3588        3578 :                   t.value    = "-";
    3589        3578 :                   t.position = t0.position;
    3590             : 
    3591        3578 :                   return true;
    3592             :                }
    3593             :                // '- +' --> '-'
    3594    15317340 :                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
    3595             :                {
    3596          39 :                   t.type     = lexer::token::e_sub;
    3597          39 :                   t.value    = "-";
    3598          39 :                   t.position = t0.position;
    3599             : 
    3600          39 :                   return true;
    3601             :                }
    3602             :                // '- -' --> '+'
    3603    15317301 :                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
    3604             :                {
    3605             :                   /*
    3606             :                      Note: May need to reconsider this when wanting to implement
    3607             :                      pre/postfix decrement operator
    3608             :                   */
    3609        3616 :                   t.type     = lexer::token::e_add;
    3610        3616 :                   t.value    = "+";
    3611        3616 :                   t.position = t0.position;
    3612             : 
    3613        3616 :                   return true;
    3614             :                }
    3615             :                else
    3616    15313685 :                   return false;
    3617             :             }
    3618             : 
    3619    14950570 :             inline bool join(const lexer::token& t0,
    3620             :                              const lexer::token& t1,
    3621             :                              const lexer::token& t2,
    3622             :                              lexer::token& t) exprtk_override
    3623             :             {
    3624             :                // '[ * ]' --> '[*]'
    3625    14950570 :                if (
    3626    14950570 :                     (t0.type == lexer::token::e_lsqrbracket) &&
    3627       89681 :                     (t1.type == lexer::token::e_mul        ) &&
    3628         210 :                     (t2.type == lexer::token::e_rsqrbracket)
    3629             :                   )
    3630             :                {
    3631         200 :                   t.type     = lexer::token::e_symbol;
    3632         200 :                   t.value    = "[*]";
    3633         200 :                   t.position = t0.position;
    3634             : 
    3635         200 :                   return true;
    3636             :                }
    3637             :                else
    3638    14950370 :                   return false;
    3639             :             }
    3640             :          };
    3641             : 
    3642             :          class bracket_checker exprtk_final : public lexer::token_scanner
    3643             :          {
    3644             :          public:
    3645             : 
    3646             :             using lexer::token_scanner::operator();
    3647             : 
    3648      106542 :             bracket_checker()
    3649           0 :             : token_scanner(1)
    3650      106542 :             , state_(true)
    3651      106542 :             {}
    3652             : 
    3653      370650 :             bool result() exprtk_override
    3654             :             {
    3655      370650 :                if (!stack_.empty())
    3656             :                {
    3657        5025 :                   lexer::token t;
    3658        5025 :                   t.value      = stack_.top().first;
    3659        5025 :                   t.position   = stack_.top().second;
    3660        5025 :                   error_token_ = t;
    3661        5025 :                   state_       = false;
    3662             : 
    3663        5025 :                   return false;
    3664        5025 :                }
    3665             :                else
    3666      365625 :                   return state_;
    3667             :             }
    3668             : 
    3669       17788 :             lexer::token error_token()
    3670             :             {
    3671       17788 :                return error_token_;
    3672             :             }
    3673             : 
    3674      370650 :             void reset() exprtk_override
    3675             :             {
    3676             :                // Why? because msvc doesn't support swap properly.
    3677      370650 :                stack_ = std::stack<std::pair<char,std::size_t> >();
    3678      370650 :                state_ = true;
    3679      370650 :                error_token_.clear();
    3680      370650 :             }
    3681             : 
    3682    15436943 :             bool operator() (const lexer::token& t) exprtk_override
    3683             :             {
    3684    15436943 :                if (
    3685    15436943 :                     !t.value.empty()                       &&
    3686    15427503 :                     (lexer::token::e_string != t.type)     &&
    3687    43089793 :                     (lexer::token::e_symbol != t.type)     &&
    3688    12225347 :                     exprtk::details::is_bracket(t.value[0])
    3689             :                   )
    3690             :                {
    3691     6059197 :                   details::char_t c = t.value[0];
    3692             : 
    3693     6059197 :                   if      (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));
    3694     3148683 :                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
    3695     3112468 :                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
    3696     3022703 :                   else if (exprtk::details::is_right_bracket(c))
    3697             :                   {
    3698     3022703 :                      if (stack_.empty())
    3699             :                      {
    3700        3869 :                         state_       = false;
    3701        3869 :                         error_token_ = t;
    3702             : 
    3703        3869 :                         return false;
    3704             :                      }
    3705     3018834 :                      else if (c != stack_.top().first)
    3706             :                      {
    3707         928 :                         state_       = false;
    3708         928 :                         error_token_ = t;
    3709             : 
    3710         928 :                         return false;
    3711             :                      }
    3712             :                      else
    3713     3017906 :                         stack_.pop();
    3714             :                   }
    3715             :                }
    3716             : 
    3717    15432146 :                return true;
    3718             :             }
    3719             : 
    3720             :          private:
    3721             : 
    3722             :             bool state_;
    3723             :             std::stack<std::pair<char,std::size_t> > stack_;
    3724             :             lexer::token error_token_;
    3725             :          };
    3726             : 
    3727             :          template <typename T>
    3728             :          class numeric_checker exprtk_final : public lexer::token_scanner
    3729             :          {
    3730             :          public:
    3731             : 
    3732             :             using lexer::token_scanner::operator();
    3733             : 
    3734      106542 :             numeric_checker()
    3735      213084 :             : token_scanner (1)
    3736      106542 :             , current_index_(0)
    3737      106542 :             {}
    3738             : 
    3739      370664 :             bool result() exprtk_override
    3740             :             {
    3741      370664 :                return error_list_.empty();
    3742             :             }
    3743             : 
    3744      370664 :             void reset() exprtk_override
    3745             :             {
    3746      370664 :                error_list_.clear();
    3747      370664 :                current_index_ = 0;
    3748      370664 :             }
    3749             : 
    3750    15691190 :             bool operator() (const lexer::token& t) exprtk_override
    3751             :             {
    3752    15691190 :                if (token::e_number == t.type)
    3753             :                {
    3754             :                   T v;
    3755             : 
    3756     1979129 :                   if (!exprtk::details::string_to_real(t.value,v))
    3757             :                   {
    3758          14 :                      error_list_.push_back(current_index_);
    3759             :                   }
    3760             :                }
    3761             : 
    3762    15691190 :                ++current_index_;
    3763             : 
    3764    15691190 :                return true;
    3765             :             }
    3766             : 
    3767          42 :             std::size_t error_count() const
    3768             :             {
    3769          42 :                return error_list_.size();
    3770             :             }
    3771             : 
    3772          14 :             std::size_t error_index(const std::size_t& i)
    3773             :             {
    3774          14 :                if (i < error_list_.size())
    3775          14 :                   return error_list_[i];
    3776             :                else
    3777           0 :                   return std::numeric_limits<std::size_t>::max();
    3778             :             }
    3779             : 
    3780          14 :             void clear_errors()
    3781             :             {
    3782          14 :                error_list_.clear();
    3783          14 :             }
    3784             : 
    3785             :          private:
    3786             : 
    3787             :             std::size_t current_index_;
    3788             :             std::vector<std::size_t> error_list_;
    3789             :          };
    3790             : 
    3791             :          class symbol_replacer exprtk_final : public lexer::token_modifier
    3792             :          {
    3793             :          private:
    3794             : 
    3795             :             typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
    3796             : 
    3797             :          public:
    3798             : 
    3799             :             bool remove(const std::string& target_symbol)
    3800             :             {
    3801             :                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
    3802             : 
    3803             :                if (replace_map_.end() == itr)
    3804             :                   return false;
    3805             : 
    3806             :                replace_map_.erase(itr);
    3807             : 
    3808             :                return true;
    3809             :             }
    3810             : 
    3811      216284 :             bool add_replace(const std::string& target_symbol,
    3812             :                              const std::string& replace_symbol,
    3813             :                              const lexer::token::token_type token_type = lexer::token::e_symbol)
    3814             :             {
    3815      216284 :                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
    3816             : 
    3817      216284 :                if (replace_map_.end() != itr)
    3818             :                {
    3819           0 :                   return false;
    3820             :                }
    3821             : 
    3822      216284 :                replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
    3823             : 
    3824      216284 :                return true;
    3825             :             }
    3826             : 
    3827      106542 :             void clear()
    3828             :             {
    3829      106542 :                replace_map_.clear();
    3830      106542 :             }
    3831             : 
    3832             :          private:
    3833             : 
    3834    15691190 :             bool modify(lexer::token& t) exprtk_override
    3835             :             {
    3836    15691190 :                if (lexer::token::e_symbol == t.type)
    3837             :                {
    3838     3217529 :                   if (replace_map_.empty())
    3839        8223 :                      return false;
    3840             : 
    3841     3217529 :                   const replace_map_t::iterator itr = replace_map_.find(t.value);
    3842             : 
    3843     3217529 :                   if (replace_map_.end() != itr)
    3844             :                   {
    3845        8223 :                      t.value = itr->second.first;
    3846        8223 :                      t.type  = itr->second.second;
    3847             : 
    3848        8223 :                      return true;
    3849             :                   }
    3850             :                }
    3851             : 
    3852    15682967 :                return false;
    3853             :             }
    3854             : 
    3855             :             replace_map_t replace_map_;
    3856             :          };
    3857             : 
    3858             :          class sequence_validator exprtk_final : public lexer::token_scanner
    3859             :          {
    3860             :          private:
    3861             : 
    3862             :             typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
    3863             :             typedef std::set<token_pair_t> set_t;
    3864             : 
    3865             :          public:
    3866             : 
    3867             :             using lexer::token_scanner::operator();
    3868             : 
    3869      106542 :             sequence_validator()
    3870      106542 :             : lexer::token_scanner(2)
    3871             :             {
    3872      106542 :                add_invalid(lexer::token::e_number, lexer::token::e_number);
    3873      106542 :                add_invalid(lexer::token::e_string, lexer::token::e_string);
    3874      106542 :                add_invalid(lexer::token::e_number, lexer::token::e_string);
    3875      106542 :                add_invalid(lexer::token::e_string, lexer::token::e_number);
    3876             : 
    3877      106542 :                add_invalid_set1(lexer::token::e_assign );
    3878      106542 :                add_invalid_set1(lexer::token::e_shr    );
    3879      106542 :                add_invalid_set1(lexer::token::e_shl    );
    3880      106542 :                add_invalid_set1(lexer::token::e_lte    );
    3881      106542 :                add_invalid_set1(lexer::token::e_ne     );
    3882      106542 :                add_invalid_set1(lexer::token::e_gte    );
    3883      106542 :                add_invalid_set1(lexer::token::e_lt     );
    3884      106542 :                add_invalid_set1(lexer::token::e_gt     );
    3885      106542 :                add_invalid_set1(lexer::token::e_eq     );
    3886      106542 :                add_invalid_set1(lexer::token::e_comma  );
    3887      106542 :                add_invalid_set1(lexer::token::e_add    );
    3888      106542 :                add_invalid_set1(lexer::token::e_sub    );
    3889      106542 :                add_invalid_set1(lexer::token::e_div    );
    3890      106542 :                add_invalid_set1(lexer::token::e_mul    );
    3891      106542 :                add_invalid_set1(lexer::token::e_mod    );
    3892      106542 :                add_invalid_set1(lexer::token::e_pow    );
    3893      106542 :                add_invalid_set1(lexer::token::e_colon  );
    3894      106542 :                add_invalid_set1(lexer::token::e_ternary);
    3895      106542 :             }
    3896             : 
    3897      361756 :             bool result() exprtk_override
    3898             :             {
    3899      361756 :                return error_list_.empty();
    3900             :             }
    3901             : 
    3902    13633795 :             bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override
    3903             :             {
    3904    13633795 :                const set_t::value_type p = std::make_pair(t0.type,t1.type);
    3905             : 
    3906    13633795 :                if (invalid_bracket_check(t0.type,t1.type))
    3907             :                {
    3908         559 :                   error_list_.push_back(std::make_pair(t0,t1));
    3909             :                }
    3910    13633236 :                else if (invalid_comb_.find(p) != invalid_comb_.end())
    3911             :                {
    3912         443 :                   error_list_.push_back(std::make_pair(t0,t1));
    3913             :                }
    3914             : 
    3915    13633795 :                return true;
    3916             :             }
    3917             : 
    3918        2660 :             std::size_t error_count() const
    3919             :             {
    3920        2660 :                return error_list_.size();
    3921             :             }
    3922             : 
    3923        1002 :             std::pair<lexer::token,lexer::token> error(const std::size_t index)
    3924             :             {
    3925        1002 :                if (index < error_list_.size())
    3926             :                {
    3927        1002 :                   return error_list_[index];
    3928             :                }
    3929             :                else
    3930             :                {
    3931           0 :                   static const lexer::token error_token;
    3932           0 :                   return std::make_pair(error_token,error_token);
    3933             :                }
    3934             :             }
    3935             : 
    3936         829 :             void clear_errors()
    3937             :             {
    3938         829 :                error_list_.clear();
    3939         829 :             }
    3940             : 
    3941             :          private:
    3942             : 
    3943    29192508 :             void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t)
    3944             :             {
    3945    29192508 :                invalid_comb_.insert(std::make_pair(base,t));
    3946    29192508 :             }
    3947             : 
    3948     1917756 :             void add_invalid_set1(const lexer::token::token_type t)
    3949             :             {
    3950     1917756 :                add_invalid(t, lexer::token::e_assign);
    3951     1917756 :                add_invalid(t, lexer::token::e_shr   );
    3952     1917756 :                add_invalid(t, lexer::token::e_shl   );
    3953     1917756 :                add_invalid(t, lexer::token::e_lte   );
    3954     1917756 :                add_invalid(t, lexer::token::e_ne    );
    3955     1917756 :                add_invalid(t, lexer::token::e_gte   );
    3956     1917756 :                add_invalid(t, lexer::token::e_lt    );
    3957     1917756 :                add_invalid(t, lexer::token::e_gt    );
    3958     1917756 :                add_invalid(t, lexer::token::e_eq    );
    3959     1917756 :                add_invalid(t, lexer::token::e_comma );
    3960     1917756 :                add_invalid(t, lexer::token::e_div   );
    3961     1917756 :                add_invalid(t, lexer::token::e_mul   );
    3962     1917756 :                add_invalid(t, lexer::token::e_mod   );
    3963     1917756 :                add_invalid(t, lexer::token::e_pow   );
    3964     1917756 :                add_invalid(t, lexer::token::e_colon );
    3965     1917756 :             }
    3966             : 
    3967    13633795 :             bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t)
    3968             :             {
    3969    13633795 :                if (details::is_right_bracket(static_cast<details::char_t>(base)))
    3970             :                {
    3971     2381117 :                   switch (t)
    3972             :                   {
    3973       24709 :                      case lexer::token::e_assign : return (']' != base);
    3974          35 :                      case lexer::token::e_string : return (')' != base);
    3975     2356373 :                      default                     : return false;
    3976             :                   }
    3977             :                }
    3978    11252678 :                else if (details::is_left_bracket(static_cast<details::char_t>(base)))
    3979             :                {
    3980     2692494 :                   if (details::is_right_bracket(static_cast<details::char_t>(t)))
    3981        9812 :                      return false;
    3982     2682682 :                   else if (details::is_left_bracket(static_cast<details::char_t>(t)))
    3983     1213399 :                      return false;
    3984             :                   else
    3985             :                   {
    3986     1469283 :                      switch (t)
    3987             :                      {
    3988      569957 :                         case lexer::token::e_number  : return false;
    3989      796756 :                         case lexer::token::e_symbol  : return false;
    3990        2977 :                         case lexer::token::e_string  : return false;
    3991        1613 :                         case lexer::token::e_add     : return false;
    3992       87609 :                         case lexer::token::e_sub     : return false;
    3993       10169 :                         case lexer::token::e_colon   : return false;
    3994          19 :                         case lexer::token::e_ternary : return false;
    3995         183 :                         default                      : return true ;
    3996             :                      }
    3997             :                   }
    3998             :                }
    3999     8560184 :                else if (details::is_right_bracket(static_cast<details::char_t>(t)))
    4000             :                {
    4001     1554894 :                   switch (base)
    4002             :                   {
    4003      792124 :                      case lexer::token::e_number  : return false;
    4004      735217 :                      case lexer::token::e_symbol  : return false;
    4005        9136 :                      case lexer::token::e_string  : return false;
    4006        6581 :                      case lexer::token::e_eof     : return false;
    4007       11430 :                      case lexer::token::e_colon   : return false;
    4008          30 :                      case lexer::token::e_ternary : return false;
    4009         376 :                      default                      : return true ;
    4010             :                   }
    4011             :                }
    4012     7005290 :                else if (details::is_left_bracket(static_cast<details::char_t>(t)))
    4013             :                {
    4014     1438731 :                   switch (base)
    4015             :                   {
    4016           0 :                      case lexer::token::e_rbracket    : return true;
    4017           0 :                      case lexer::token::e_rsqrbracket : return true;
    4018           0 :                      case lexer::token::e_rcrlbracket : return true;
    4019     1438731 :                      default                          : return false;
    4020             :                   }
    4021             :                }
    4022             : 
    4023     5566559 :                return false;
    4024             :             }
    4025             : 
    4026             :             set_t invalid_comb_;
    4027             :             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
    4028             :          };
    4029             : 
    4030             :          class sequence_validator_3tokens exprtk_final : public lexer::token_scanner
    4031             :          {
    4032             :          private:
    4033             : 
    4034             :             typedef lexer::token::token_type token_t;
    4035             :             typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
    4036             :             typedef std::set<token_triplet_t> set_t;
    4037             : 
    4038             :          public:
    4039             : 
    4040             :             using lexer::token_scanner::operator();
    4041             : 
    4042      106542 :             sequence_validator_3tokens()
    4043      106542 :             : lexer::token_scanner(3)
    4044             :             {
    4045      106542 :                add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number);
    4046      106542 :                add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string);
    4047      106542 :                add_invalid(lexer::token::e_comma  , lexer::token::e_comma  , lexer::token::e_comma );
    4048             : 
    4049      106542 :                add_invalid(lexer::token::e_add    , lexer::token::e_add    , lexer::token::e_add   );
    4050      106542 :                add_invalid(lexer::token::e_sub    , lexer::token::e_sub    , lexer::token::e_sub   );
    4051      106542 :                add_invalid(lexer::token::e_div    , lexer::token::e_div    , lexer::token::e_div   );
    4052      106542 :                add_invalid(lexer::token::e_mul    , lexer::token::e_mul    , lexer::token::e_mul   );
    4053      106542 :                add_invalid(lexer::token::e_mod    , lexer::token::e_mod    , lexer::token::e_mod   );
    4054      106542 :                add_invalid(lexer::token::e_pow    , lexer::token::e_pow    , lexer::token::e_pow   );
    4055             : 
    4056      106542 :                add_invalid(lexer::token::e_add    , lexer::token::e_sub    , lexer::token::e_add   );
    4057      106542 :                add_invalid(lexer::token::e_sub    , lexer::token::e_add    , lexer::token::e_sub   );
    4058      106542 :                add_invalid(lexer::token::e_div    , lexer::token::e_mul    , lexer::token::e_div   );
    4059      106542 :                add_invalid(lexer::token::e_mul    , lexer::token::e_div    , lexer::token::e_mul   );
    4060      106542 :                add_invalid(lexer::token::e_mod    , lexer::token::e_pow    , lexer::token::e_mod   );
    4061      106542 :                add_invalid(lexer::token::e_pow    , lexer::token::e_mod    , lexer::token::e_pow   );
    4062      106542 :             }
    4063             : 
    4064      360927 :             bool result() exprtk_override
    4065             :             {
    4066      360927 :                return error_list_.empty();
    4067             :             }
    4068             : 
    4069    13118794 :             bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override
    4070             :             {
    4071    13118794 :                const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
    4072             : 
    4073    13118794 :                if (invalid_comb_.find(p) != invalid_comb_.end())
    4074             :                {
    4075           4 :                   error_list_.push_back(std::make_pair(t0,t1));
    4076             :                }
    4077             : 
    4078    13118794 :                return true;
    4079             :             }
    4080             : 
    4081           8 :             std::size_t error_count() const
    4082             :             {
    4083           8 :                return error_list_.size();
    4084             :             }
    4085             : 
    4086           4 :             std::pair<lexer::token,lexer::token> error(const std::size_t index)
    4087             :             {
    4088           4 :                if (index < error_list_.size())
    4089             :                {
    4090           4 :                   return error_list_[index];
    4091             :                }
    4092             :                else
    4093             :                {
    4094           0 :                   static const lexer::token error_token;
    4095           0 :                   return std::make_pair(error_token,error_token);
    4096             :                }
    4097             :             }
    4098             : 
    4099           2 :             void clear_errors()
    4100             :             {
    4101           2 :                error_list_.clear();
    4102           2 :             }
    4103             : 
    4104             :          private:
    4105             : 
    4106     1598130 :             void add_invalid(const token_t t0, const token_t t1, const token_t t2)
    4107             :             {
    4108     1598130 :                invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
    4109     1598130 :             }
    4110             : 
    4111             :             set_t invalid_comb_;
    4112             :             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
    4113             :          };
    4114             : 
    4115             :          struct helper_assembly
    4116             :          {
    4117      426168 :             inline bool register_scanner(lexer::token_scanner* scanner)
    4118             :             {
    4119      426168 :                if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
    4120             :                                                          token_scanner_list.end  (),
    4121             :                                                          scanner))
    4122             :                {
    4123           0 :                   return false;
    4124             :                }
    4125             : 
    4126      426168 :                token_scanner_list.push_back(scanner);
    4127             : 
    4128      426168 :                return true;
    4129             :             }
    4130             : 
    4131      106542 :             inline bool register_modifier(lexer::token_modifier* modifier)
    4132             :             {
    4133      106542 :                if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
    4134             :                                                           token_modifier_list.end  (),
    4135             :                                                           modifier))
    4136             :                {
    4137           0 :                   return false;
    4138             :                }
    4139             : 
    4140      106542 :                token_modifier_list.push_back(modifier);
    4141             : 
    4142      106542 :                return true;
    4143             :             }
    4144             : 
    4145      213084 :             inline bool register_joiner(lexer::token_joiner* joiner)
    4146             :             {
    4147      213084 :                if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
    4148             :                                                         token_joiner_list.end  (),
    4149             :                                                         joiner))
    4150             :                {
    4151           0 :                   return false;
    4152             :                }
    4153             : 
    4154      213084 :                token_joiner_list.push_back(joiner);
    4155             : 
    4156      213084 :                return true;
    4157             :             }
    4158             : 
    4159      106541 :             inline bool register_inserter(lexer::token_inserter* inserter)
    4160             :             {
    4161      106541 :                if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
    4162             :                                                           token_inserter_list.end  (),
    4163             :                                                           inserter))
    4164             :                {
    4165           0 :                   return false;
    4166             :                }
    4167             : 
    4168      106541 :                token_inserter_list.push_back(inserter);
    4169             : 
    4170      106541 :                return true;
    4171             :             }
    4172             : 
    4173      370664 :             inline bool run_modifiers(lexer::generator& g)
    4174             :             {
    4175      370664 :                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
    4176             : 
    4177      741328 :                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
    4178             :                {
    4179      370664 :                   lexer::token_modifier& modifier = (*token_modifier_list[i]);
    4180             : 
    4181      370664 :                   modifier.reset();
    4182      370664 :                   modifier.process(g);
    4183             : 
    4184      370664 :                   if (!modifier.result())
    4185             :                   {
    4186           0 :                      error_token_modifier = token_modifier_list[i];
    4187             : 
    4188           0 :                      return false;
    4189             :                   }
    4190             :                }
    4191             : 
    4192      370664 :                return true;
    4193             :             }
    4194             : 
    4195      370664 :             inline bool run_joiners(lexer::generator& g)
    4196             :             {
    4197      370664 :                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
    4198             : 
    4199     1111992 :                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
    4200             :                {
    4201      741328 :                   lexer::token_joiner& joiner = (*token_joiner_list[i]);
    4202             : 
    4203      741328 :                   joiner.reset();
    4204      741328 :                   joiner.process(g);
    4205             : 
    4206      741328 :                   if (!joiner.result())
    4207             :                   {
    4208           0 :                      error_token_joiner = token_joiner_list[i];
    4209             : 
    4210           0 :                      return false;
    4211             :                   }
    4212             :                }
    4213             : 
    4214      370664 :                return true;
    4215             :             }
    4216             : 
    4217      370654 :             inline bool run_inserters(lexer::generator& g)
    4218             :             {
    4219      370654 :                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
    4220             : 
    4221      741308 :                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
    4222             :                {
    4223      370654 :                   lexer::token_inserter& inserter = (*token_inserter_list[i]);
    4224             : 
    4225      370654 :                   inserter.reset();
    4226      370654 :                   inserter.process(g);
    4227             : 
    4228      370654 :                   if (!inserter.result())
    4229             :                   {
    4230           0 :                      error_token_inserter = token_inserter_list[i];
    4231             : 
    4232           0 :                      return false;
    4233             :                   }
    4234             :                }
    4235             : 
    4236      370654 :                return true;
    4237             :             }
    4238             : 
    4239      370664 :             inline bool run_scanners(lexer::generator& g)
    4240             :             {
    4241      370664 :                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
    4242             : 
    4243     1824922 :                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
    4244             :                {
    4245     1463997 :                   lexer::token_scanner& scanner = (*token_scanner_list[i]);
    4246             : 
    4247     1463997 :                   scanner.reset();
    4248     1463997 :                   scanner.process(g);
    4249             : 
    4250     1463997 :                   if (!scanner.result())
    4251             :                   {
    4252        9739 :                      error_token_scanner = token_scanner_list[i];
    4253             : 
    4254        9739 :                      return false;
    4255             :                   }
    4256             :                }
    4257             : 
    4258      360925 :                return true;
    4259             :             }
    4260             : 
    4261             :             std::vector<lexer::token_scanner*>  token_scanner_list;
    4262             :             std::vector<lexer::token_modifier*> token_modifier_list;
    4263             :             std::vector<lexer::token_joiner*>   token_joiner_list;
    4264             :             std::vector<lexer::token_inserter*> token_inserter_list;
    4265             : 
    4266             :             lexer::token_scanner*  error_token_scanner;
    4267             :             lexer::token_modifier* error_token_modifier;
    4268             :             lexer::token_joiner*   error_token_joiner;
    4269             :             lexer::token_inserter* error_token_inserter;
    4270             :          };
    4271             :       }
    4272             : 
    4273             :       class parser_helper
    4274             :       {
    4275             :       public:
    4276             : 
    4277             :          typedef token     token_t;
    4278             :          typedef generator generator_t;
    4279             : 
    4280      371453 :          inline bool init(const std::string& str)
    4281             :          {
    4282      371453 :             if (!lexer_.process(str))
    4283             :             {
    4284         788 :                return false;
    4285             :             }
    4286             : 
    4287      370665 :             lexer_.begin();
    4288             : 
    4289      370665 :             next_token();
    4290             : 
    4291      370665 :             return true;
    4292             :          }
    4293             : 
    4294     3173150 :          inline generator_t& lexer()
    4295             :          {
    4296     3173150 :             return lexer_;
    4297             :          }
    4298             : 
    4299             :          inline const generator_t& lexer() const
    4300             :          {
    4301             :             return lexer_;
    4302             :          }
    4303             : 
    4304             :          inline void store_token()
    4305             :          {
    4306             :             lexer_.store();
    4307             :             store_current_token_ = current_token_;
    4308             :          }
    4309             : 
    4310             :          inline void restore_token()
    4311             :          {
    4312             :             lexer_.restore();
    4313             :             current_token_ = store_current_token_;
    4314             :          }
    4315             : 
    4316    13180715 :          inline void next_token()
    4317             :          {
    4318    13180715 :             current_token_ = lexer_.next_token();
    4319    13180715 :          }
    4320             : 
    4321    61861533 :          inline const token_t& current_token() const
    4322             :          {
    4323    61861533 :             return current_token_;
    4324             :          }
    4325             : 
    4326             :          inline const token_t& peek_next_token()
    4327             :          {
    4328             :             return lexer_.peek_next_token();
    4329             :          }
    4330             : 
    4331             :          enum token_advance_mode
    4332             :          {
    4333             :             e_hold    = 0,
    4334             :             e_advance = 1
    4335             :          };
    4336             : 
    4337     3905325 :          inline void advance_token(const token_advance_mode mode)
    4338             :          {
    4339     3905325 :             if (e_advance == mode)
    4340             :             {
    4341     3431713 :                next_token();
    4342             :             }
    4343     3905325 :          }
    4344             : 
    4345    18035526 :          inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
    4346             :          {
    4347    18035526 :             if (current_token().type != ttype)
    4348             :             {
    4349    14130284 :                return false;
    4350             :             }
    4351             : 
    4352     3905242 :             advance_token(mode);
    4353             : 
    4354     3905242 :             return true;
    4355             :          }
    4356             : 
    4357          80 :          inline bool token_is(const token_t::token_type& ttype,
    4358             :                               const std::string& value,
    4359             :                               const token_advance_mode mode = e_advance)
    4360             :          {
    4361          80 :             if (
    4362         160 :                  (current_token().type != ttype) ||
    4363          80 :                  !exprtk::details::imatch(value,current_token().value)
    4364             :                )
    4365             :             {
    4366           0 :                return false;
    4367             :             }
    4368             : 
    4369          80 :             advance_token(mode);
    4370             : 
    4371          80 :             return true;
    4372             :          }
    4373             : 
    4374          43 :          inline bool token_is(const std::string& value,
    4375             :                               const token_advance_mode mode = e_advance)
    4376             :          {
    4377          43 :             if (!exprtk::details::imatch(value,current_token().value))
    4378             :             {
    4379          40 :                return false;
    4380             :             }
    4381             : 
    4382           3 :             advance_token(mode);
    4383             : 
    4384           3 :             return true;
    4385             :          }
    4386             : 
    4387          10 :          inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance)
    4388             :          {
    4389          10 :             switch (current_token().type)
    4390             :             {
    4391           0 :                case token_t::e_add :
    4392             :                case token_t::e_sub :
    4393             :                case token_t::e_div :
    4394             :                case token_t::e_mul :
    4395             :                case token_t::e_mod :
    4396           0 :                case token_t::e_pow : break;
    4397          10 :                default             : return false;
    4398             :             }
    4399             : 
    4400           0 :             advance_token(mode);
    4401             : 
    4402           0 :             return true;
    4403             :          }
    4404             : 
    4405          10 :          inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance)
    4406             :          {
    4407          10 :             switch (current_token().type)
    4408             :             {
    4409           0 :                case token_t::e_eq  :
    4410             :                case token_t::e_lte :
    4411             :                case token_t::e_ne  :
    4412             :                case token_t::e_gte :
    4413             :                case token_t::e_lt  :
    4414           0 :                case token_t::e_gt  : break;
    4415          10 :                default             : return false;
    4416             :             }
    4417             : 
    4418           0 :             advance_token(mode);
    4419             : 
    4420           0 :             return true;
    4421             :          }
    4422             : 
    4423             :          inline bool token_is_left_bracket(const token_advance_mode mode = e_advance)
    4424             :          {
    4425             :             switch (current_token().type)
    4426             :             {
    4427             :                case token_t::e_lbracket    :
    4428             :                case token_t::e_lcrlbracket :
    4429             :                case token_t::e_lsqrbracket : break;
    4430             :                default                     : return false;
    4431             :             }
    4432             : 
    4433             :             advance_token(mode);
    4434             : 
    4435             :             return true;
    4436             :          }
    4437             : 
    4438          10 :          inline bool token_is_right_bracket(const token_advance_mode mode = e_advance)
    4439             :          {
    4440          10 :             switch (current_token().type)
    4441             :             {
    4442           0 :                case token_t::e_rbracket    :
    4443             :                case token_t::e_rcrlbracket :
    4444           0 :                case token_t::e_rsqrbracket : break;
    4445          10 :                default                     : return false;
    4446             :             }
    4447             : 
    4448           0 :             advance_token(mode);
    4449             : 
    4450           0 :             return true;
    4451             :          }
    4452             : 
    4453          10 :          inline bool token_is_loop(const token_advance_mode mode = e_advance)
    4454             :          {
    4455          30 :             return token_is("for"   , mode) ||
    4456          60 :                    token_is("while" , mode) ||
    4457          40 :                    token_is("repeat", mode) ;
    4458             :          }
    4459             : 
    4460     5731771 :          inline bool peek_token_is(const token_t::token_type& ttype)
    4461             :          {
    4462     5731771 :             return (lexer_.peek_next_token().type == ttype);
    4463             :          }
    4464             : 
    4465          55 :          inline bool peek_token_is(const std::string& s)
    4466             :          {
    4467          55 :             return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
    4468             :          }
    4469             : 
    4470             :       private:
    4471             : 
    4472             :          generator_t lexer_;
    4473             :          token_t     current_token_;
    4474             :          token_t     store_current_token_;
    4475             :       };
    4476             :    }
    4477             : 
    4478             :    template <typename T>
    4479             :    class vector_view
    4480             :    {
    4481             :    public:
    4482             : 
    4483             :       typedef T* data_ptr_t;
    4484             : 
    4485        4195 :       vector_view(data_ptr_t data, const std::size_t& size)
    4486        4195 :       : base_size_(size)
    4487        4195 :       , size_(size)
    4488        4195 :       , data_(data)
    4489        8390 :       , data_ref_(0)
    4490             :       {
    4491        4195 :          assert(size_ > 0);
    4492        4195 :       }
    4493             : 
    4494             :       vector_view(const vector_view<T>& vv)
    4495             :       : base_size_(vv.base_size_)
    4496             :       , size_(vv.size_)
    4497             :       , data_(vv.data_)
    4498             :       , data_ref_(0)
    4499             :       {
    4500             :          assert(size_ > 0);
    4501             :       }
    4502             : 
    4503        6800 :       inline void rebase(data_ptr_t data)
    4504             :       {
    4505        6800 :          data_ = data;
    4506             : 
    4507        6800 :          if (!data_ref_.empty())
    4508             :          {
    4509       11027 :             for (std::size_t i = 0; i < data_ref_.size(); ++i)
    4510             :             {
    4511        8547 :                (*data_ref_[i]) = data;
    4512             :             }
    4513             :          }
    4514        6800 :       }
    4515             : 
    4516           6 :       inline data_ptr_t data() const
    4517             :       {
    4518           6 :          return data_;
    4519             :       }
    4520             : 
    4521        4172 :       inline std::size_t base_size() const
    4522             :       {
    4523        4172 :          return base_size_;
    4524             :       }
    4525             : 
    4526       32851 :       inline std::size_t size() const
    4527             :       {
    4528       32851 :          return size_;
    4529             :       }
    4530             : 
    4531             :       inline const T& operator[](const std::size_t index) const
    4532             :       {
    4533             :          assert(index < size_);
    4534             :          return data_[index];
    4535             :       }
    4536             : 
    4537        7555 :       inline T& operator[](const std::size_t index)
    4538             :       {
    4539        7555 :          assert(index < size_);
    4540        7555 :          return data_[index];
    4541             :       }
    4542             : 
    4543        3670 :       void set_ref(data_ptr_t* data_ref)
    4544             :       {
    4545        3670 :          data_ref_.push_back(data_ref);
    4546             :          exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %lu\n",
    4547             :                        reinterpret_cast<void*>(data_ref),
    4548             :                        data_ref_.size()));
    4549        3670 :       }
    4550             : 
    4551        3670 :       void remove_ref(data_ptr_t* data_ref)
    4552             :       {
    4553        7340 :          data_ref_.erase(
    4554        3670 :             std::remove(data_ref_.begin(), data_ref_.end(), data_ref),
    4555        3670 :             data_ref_.end());
    4556             :          exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %lu\n",
    4557             :                        reinterpret_cast<void*>(data_ref),
    4558             :                        data_ref_.size()));
    4559        3670 :       }
    4560             : 
    4561         240 :       bool set_size(const std::size_t new_size)
    4562             :       {
    4563         240 :          if ((new_size > 0) && (new_size <= base_size_))
    4564             :          {
    4565         240 :             size_ = new_size;
    4566             :             exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n",
    4567             :                           reinterpret_cast<void*>(data_),
    4568             :                           size_));
    4569         240 :             return true;
    4570             :          }
    4571             : 
    4572             :          exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu  base_size: %lu\n",
    4573             :                        new_size,
    4574             :                        base_size_));
    4575           0 :          return false;
    4576             :       }
    4577             : 
    4578             :    private:
    4579             : 
    4580             :       const std::size_t base_size_;
    4581             :       std::size_t size_;
    4582             :       data_ptr_t  data_;
    4583             :       std::vector<data_ptr_t*> data_ref_;
    4584             :    };
    4585             : 
    4586             :    template <typename T>
    4587        4137 :    inline vector_view<T> make_vector_view(T* data,
    4588             :                                           const std::size_t size, const std::size_t offset = 0)
    4589             :    {
    4590        4137 :       return vector_view<T>(data + offset, size);
    4591             :    }
    4592             : 
    4593             :    template <typename T>
    4594          58 :    inline vector_view<T> make_vector_view(std::vector<T>& v,
    4595             :                                           const std::size_t size, const std::size_t offset = 0)
    4596             :    {
    4597          58 :       return vector_view<T>(v.data() + offset, size);
    4598             :    }
    4599             : 
    4600             :    template <typename T> class results_context;
    4601             : 
    4602             :    template <typename T>
    4603             :    struct type_store
    4604             :    {
    4605             :       enum store_type
    4606             :       {
    4607             :          e_unknown,
    4608             :          e_scalar ,
    4609             :          e_vector ,
    4610             :          e_string
    4611             :       };
    4612             : 
    4613        2049 :       type_store()
    4614        2049 :       : data(0)
    4615        2049 :       , size(0)
    4616        2049 :       , type(e_unknown)
    4617        2049 :       {}
    4618             : 
    4619             :       union
    4620             :       {
    4621             :          void* data;
    4622             :          T*    vec_data;
    4623             :       };
    4624             : 
    4625             :       std::size_t size;
    4626             :       store_type  type;
    4627             : 
    4628             :       class parameter_list
    4629             :       {
    4630             :       public:
    4631             : 
    4632        3603 :          explicit parameter_list(std::vector<type_store>& pl)
    4633        3603 :          : parameter_list_(pl)
    4634        3603 :          {}
    4635             : 
    4636             :          inline bool empty() const
    4637             :          {
    4638             :             return parameter_list_.empty();
    4639             :          }
    4640             : 
    4641        1222 :          inline std::size_t size() const
    4642             :          {
    4643        1222 :             return parameter_list_.size();
    4644             :          }
    4645             : 
    4646        7643 :          inline type_store& operator[](const std::size_t& index)
    4647             :          {
    4648        7643 :             return parameter_list_[index];
    4649             :          }
    4650             : 
    4651             :          inline const type_store& operator[](const std::size_t& index) const
    4652             :          {
    4653             :             return parameter_list_[index];
    4654             :          }
    4655             : 
    4656             :          inline type_store& front()
    4657             :          {
    4658             :             return parameter_list_[0];
    4659             :          }
    4660             : 
    4661             :          inline const type_store& front() const
    4662             :          {
    4663             :             return parameter_list_[0];
    4664             :          }
    4665             : 
    4666         301 :          inline type_store& back()
    4667             :          {
    4668         301 :             return parameter_list_.back();
    4669             :          }
    4670             : 
    4671             :          inline const type_store& back() const
    4672             :          {
    4673             :             return parameter_list_.back();
    4674             :          }
    4675             : 
    4676             :       private:
    4677             : 
    4678             :          std::vector<type_store>& parameter_list_;
    4679             : 
    4680             :          friend class results_context<T>;
    4681             :       };
    4682             : 
    4683             :       template <typename ViewType>
    4684             :       struct type_view
    4685             :       {
    4686             :          typedef type_store<T> type_store_t;
    4687             :          typedef ViewType      value_t;
    4688             : 
    4689        5882 :          explicit type_view(type_store_t& ts)
    4690        5882 :          : ts_(ts)
    4691        5882 :          , data_(reinterpret_cast<value_t*>(ts_.data))
    4692        5882 :          {}
    4693             : 
    4694           2 :          explicit type_view(const type_store_t& ts)
    4695           2 :          : ts_(const_cast<type_store_t&>(ts))
    4696           2 :          , data_(reinterpret_cast<value_t*>(ts_.data))
    4697           2 :          {}
    4698             : 
    4699       10724 :          inline std::size_t size() const
    4700             :          {
    4701       10724 :             return ts_.size;
    4702             :          }
    4703             : 
    4704        3195 :          inline value_t& operator[](const std::size_t& i)
    4705             :          {
    4706        3195 :             return data_[i];
    4707             :          }
    4708             : 
    4709       24811 :          inline const value_t& operator[](const std::size_t& i) const
    4710             :          {
    4711       24811 :             return data_[i];
    4712             :          }
    4713             : 
    4714          57 :          inline const value_t* begin() const { return data_; }
    4715         100 :          inline       value_t* begin()       { return data_; }
    4716             : 
    4717             :          inline const value_t* end() const
    4718             :          {
    4719             :             return static_cast<value_t*>(data_ + ts_.size);
    4720             :          }
    4721             : 
    4722           2 :          inline value_t* end()
    4723             :          {
    4724           2 :             return static_cast<value_t*>(data_ + ts_.size);
    4725             :          }
    4726             : 
    4727             :          type_store_t& ts_;
    4728             :          value_t* data_;
    4729             :       };
    4730             : 
    4731             :       typedef type_view<T>    vector_view;
    4732             :       typedef type_view<char> string_view;
    4733             : 
    4734             :       struct scalar_view
    4735             :       {
    4736             :          typedef type_store<T> type_store_t;
    4737             :          typedef T value_t;
    4738             : 
    4739        1786 :          explicit scalar_view(type_store_t& ts)
    4740        1786 :          : v_(*reinterpret_cast<value_t*>(ts.data))
    4741        1786 :          {}
    4742             : 
    4743          16 :          explicit scalar_view(const type_store_t& ts)
    4744          16 :          : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
    4745          16 :          {}
    4746             : 
    4747         586 :          inline value_t& operator() ()
    4748             :          {
    4749         586 :             return v_;
    4750             :          }
    4751             : 
    4752           2 :          inline const value_t& operator() () const
    4753             :          {
    4754           2 :             return v_;
    4755             :          }
    4756             : 
    4757             :          inline operator value_t() const
    4758             :          {
    4759             :             return v_;
    4760             :          }
    4761             : 
    4762         404 :          inline operator value_t()
    4763             :          {
    4764         404 :             return v_;
    4765             :          }
    4766             : 
    4767             :          template <typename IntType>
    4768             :          inline bool to_int(IntType& i) const
    4769             :          {
    4770             :             if (!exprtk::details::numeric::is_integer(v_))
    4771             :                return false;
    4772             : 
    4773             :             i = static_cast<IntType>(v_);
    4774             : 
    4775             :             return true;
    4776             :          }
    4777             : 
    4778             :          template <typename UIntType>
    4779         810 :          inline bool to_uint(UIntType& u) const
    4780             :          {
    4781         810 :             if (v_ < T(0))
    4782           0 :                return false;
    4783         810 :             else if (!exprtk::details::numeric::is_integer(v_))
    4784           0 :                return false;
    4785             : 
    4786         810 :             u = static_cast<UIntType>(v_);
    4787             : 
    4788         810 :             return true;
    4789             :          }
    4790             : 
    4791             :          T& v_;
    4792             :       };
    4793             :    };
    4794             : 
    4795             :    template <typename StringView>
    4796          48 :    inline std::string to_str(const StringView& view)
    4797             :    {
    4798          96 :       return std::string(view.begin(),view.size());
    4799             :    }
    4800             : 
    4801             :    #ifndef exprtk_disable_return_statement
    4802             :    namespace details
    4803             :    {
    4804             :       template <typename T> class return_node;
    4805             :       template <typename T> class return_envelope_node;
    4806             :    }
    4807             :    #endif
    4808             : 
    4809             :    template <typename T>
    4810             :    class results_context
    4811             :    {
    4812             :    public:
    4813             : 
    4814             :       typedef type_store<T> type_store_t;
    4815             :       typedef typename type_store_t::scalar_view scalar_t;
    4816             :       typedef typename type_store_t::vector_view vector_t;
    4817             :       typedef typename type_store_t::string_view string_t;
    4818             : 
    4819         111 :       results_context()
    4820         111 :       : results_available_(false)
    4821         111 :       {}
    4822             : 
    4823          97 :       inline std::size_t count() const
    4824             :       {
    4825          97 :          if (results_available_)
    4826          97 :             return parameter_list_.size();
    4827             :          else
    4828           0 :             return 0;
    4829             :       }
    4830             : 
    4831             :       inline type_store_t& operator[](const std::size_t& index)
    4832             :       {
    4833             :          return parameter_list_[index];
    4834             :       }
    4835             : 
    4836          80 :       inline const type_store_t& operator[](const std::size_t& index) const
    4837             :       {
    4838          80 :          return parameter_list_[index];
    4839             :       }
    4840             : 
    4841           2 :       inline bool get_scalar(const std::size_t& index, T& out) const
    4842             :       {
    4843           2 :          if (
    4844           4 :               (index < parameter_list_.size()) &&
    4845           2 :               (parameter_list_[index].type == type_store_t::e_scalar)
    4846             :             )
    4847             :          {
    4848           2 :             const scalar_t scalar(parameter_list_[index]);
    4849           2 :             out = scalar();
    4850           2 :             return true;
    4851             :          }
    4852             : 
    4853           0 :          return false;
    4854             :       }
    4855             : 
    4856             :       template <typename OutputIterator>
    4857           1 :       inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const
    4858             :       {
    4859           1 :          if (
    4860           2 :               (index < parameter_list_.size()) &&
    4861           1 :               (parameter_list_[index].type == type_store_t::e_vector)
    4862             :             )
    4863             :          {
    4864           1 :             const vector_t vector(parameter_list_[index]);
    4865           5 :             for (std::size_t i = 0; i < vector.size(); ++i)
    4866             :             {
    4867           4 :                *(out_itr++) = vector[i];
    4868             :             }
    4869             : 
    4870           1 :             return true;
    4871             :          }
    4872             : 
    4873           0 :          return false;
    4874             :       }
    4875             : 
    4876           1 :       inline bool get_vector(const std::size_t& index, std::vector<T>& out) const
    4877             :       {
    4878           1 :          return get_vector(index,std::back_inserter(out));
    4879             :       }
    4880             : 
    4881           1 :       inline bool get_string(const std::size_t& index, std::string& out) const
    4882             :       {
    4883           1 :          if (
    4884           2 :               (index < parameter_list_.size()) &&
    4885           1 :               (parameter_list_[index].type == type_store_t::e_string)
    4886             :             )
    4887             :          {
    4888           1 :             const string_t str(parameter_list_[index]);
    4889           1 :             out.assign(str.begin(),str.size());
    4890           1 :             return true;
    4891             :          }
    4892             : 
    4893           0 :          return false;
    4894             :       }
    4895             : 
    4896             :    private:
    4897             : 
    4898         111 :       inline void clear()
    4899             :       {
    4900         111 :          results_available_ = false;
    4901         111 :       }
    4902             : 
    4903             :       typedef std::vector<type_store_t> ts_list_t;
    4904             :       typedef typename type_store_t::parameter_list parameter_list_t;
    4905             : 
    4906          31 :       inline void assign(const parameter_list_t& pl)
    4907             :       {
    4908          31 :          parameter_list_    = pl.parameter_list_;
    4909          31 :          results_available_ = true;
    4910          31 :       }
    4911             : 
    4912             :       bool results_available_;
    4913             :       ts_list_t parameter_list_;
    4914             : 
    4915             :       #ifndef exprtk_disable_return_statement
    4916             :       friend class details::return_node<T>;
    4917             :       friend class details::return_envelope_node<T>;
    4918             :       #endif
    4919             :    };
    4920             : 
    4921             :    namespace details
    4922             :    {
    4923             :       enum operator_type
    4924             :       {
    4925             :          e_default , e_null    , e_add     , e_sub     ,
    4926             :          e_mul     , e_div     , e_mod     , e_pow     ,
    4927             :          e_atan2   , e_min     , e_max     , e_avg     ,
    4928             :          e_sum     , e_prod    , e_lt      , e_lte     ,
    4929             :          e_eq      , e_equal   , e_ne      , e_nequal  ,
    4930             :          e_gte     , e_gt      , e_and     , e_nand    ,
    4931             :          e_or      , e_nor     , e_xor     , e_xnor    ,
    4932             :          e_mand    , e_mor     , e_scand   , e_scor    ,
    4933             :          e_shr     , e_shl     , e_abs     , e_acos    ,
    4934             :          e_acosh   , e_asin    , e_asinh   , e_atan    ,
    4935             :          e_atanh   , e_ceil    , e_cos     , e_cosh    ,
    4936             :          e_exp     , e_expm1   , e_floor   , e_log     ,
    4937             :          e_log10   , e_log2    , e_log1p   , e_logn    ,
    4938             :          e_neg     , e_pos     , e_round   , e_roundn  ,
    4939             :          e_root    , e_sqrt    , e_sin     , e_sinc    ,
    4940             :          e_sinh    , e_sec     , e_csc     , e_tan     ,
    4941             :          e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
    4942             :          e_inrange , e_sgn     , e_r2d     , e_d2r     ,
    4943             :          e_d2g     , e_g2d     , e_hypot   , e_notl    ,
    4944             :          e_erf     , e_erfc    , e_ncdf    , e_frac    ,
    4945             :          e_trunc   , e_assign  , e_addass  , e_subass  ,
    4946             :          e_mulass  , e_divass  , e_modass  , e_in      ,
    4947             :          e_like    , e_ilike   , e_multi   , e_smulti  ,
    4948             :          e_swap    ,
    4949             : 
    4950             :          // Do not add new functions/operators after this point.
    4951             :          e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
    4952             :          e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
    4953             :          e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
    4954             :          e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
    4955             :          e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
    4956             :          e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
    4957             :          e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
    4958             :          e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
    4959             :          e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
    4960             :          e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
    4961             :          e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
    4962             :          e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
    4963             :          e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
    4964             :          e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
    4965             :          e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
    4966             :          e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
    4967             :          e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
    4968             :          e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
    4969             :          e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
    4970             :          e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
    4971             :          e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
    4972             :          e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
    4973             :          e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
    4974             :          e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
    4975             :          e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
    4976             :          e_sffinal  = 1100,
    4977             :          e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
    4978             :          e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
    4979             :          e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
    4980             :          e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
    4981             :          e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
    4982             :          e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
    4983             :          e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
    4984             :          e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
    4985             :          e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
    4986             :          e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
    4987             :          e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
    4988             :          e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
    4989             :          e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
    4990             :          e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
    4991             :          e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
    4992             :          e_sf4ext60 = 2060, e_sf4ext61 = 2061
    4993             :       };
    4994             : 
    4995           3 :       inline std::string to_str(const operator_type opr)
    4996             :       {
    4997           3 :          switch (opr)
    4998             :          {
    4999           0 :             case e_add    : return  "+"  ;
    5000           0 :             case e_sub    : return  "-"  ;
    5001           0 :             case e_mul    : return  "*"  ;
    5002           0 :             case e_div    : return  "/"  ;
    5003           0 :             case e_mod    : return  "%"  ;
    5004           0 :             case e_pow    : return  "^"  ;
    5005           0 :             case e_assign : return ":="  ;
    5006           0 :             case e_addass : return "+="  ;
    5007           9 :             case e_subass : return "-="  ;
    5008           0 :             case e_mulass : return "*="  ;
    5009           0 :             case e_divass : return "/="  ;
    5010           0 :             case e_modass : return "%="  ;
    5011           0 :             case e_lt     : return  "<"  ;
    5012           0 :             case e_lte    : return "<="  ;
    5013           0 :             case e_eq     : return "=="  ;
    5014           0 :             case e_equal  : return  "="  ;
    5015           0 :             case e_ne     : return "!="  ;
    5016           0 :             case e_nequal : return "<>"  ;
    5017           0 :             case e_gte    : return ">="  ;
    5018           0 :             case e_gt     : return  ">"  ;
    5019           0 :             case e_and    : return "and" ;
    5020           0 :             case e_or     : return "or"  ;
    5021           0 :             case e_xor    : return "xor" ;
    5022           0 :             case e_nand   : return "nand";
    5023           0 :             case e_nor    : return "nor" ;
    5024           0 :             case e_xnor   : return "xnor";
    5025           0 :             default       : return "N/A" ;
    5026             :          }
    5027             :       }
    5028             : 
    5029             :       struct base_operation_t
    5030             :       {
    5031     5540184 :          base_operation_t(const operator_type t, const unsigned int& np)
    5032     5540184 :          : type(t)
    5033     5540184 :          , num_params(np)
    5034     5540184 :          {}
    5035             : 
    5036             :          operator_type type;
    5037             :          unsigned int num_params;
    5038             :       };
    5039             : 
    5040             :       namespace loop_unroll
    5041             :       {
    5042             :          const unsigned int global_loop_batch_size =
    5043             :          #ifndef exprtk_disable_superscalar_unroll
    5044             :          16;
    5045             :          #else
    5046             :           4;
    5047             :          #endif
    5048             : 
    5049             :          struct details
    5050             :          {
    5051       25283 :             explicit details(const std::size_t& vsize,
    5052             :                              const unsigned int loop_batch_size = global_loop_batch_size)
    5053       25283 :             : batch_size(loop_batch_size   )
    5054       25283 :             , remainder (vsize % batch_size)
    5055       25283 :             , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
    5056       25283 :             {}
    5057             : 
    5058             :             unsigned int batch_size;
    5059             :             int remainder;
    5060             :             int upper_bound;
    5061             :          };
    5062             :       }
    5063             : 
    5064             :       #ifdef exprtk_enable_debugging
    5065             :       inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
    5066             :       {
    5067             :          if (size)
    5068             :             exprtk_debug(("%s - addr: %p size: %d\n",
    5069             :                           s.c_str(),
    5070             :                           ptr,
    5071             :                           static_cast<unsigned int>(size)));
    5072             :          else
    5073             :             exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr));
    5074             :       }
    5075             : 
    5076             :       template <typename T>
    5077             :       inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size)
    5078             :       {
    5079             :          printf("----- %s (%p) -----\n",
    5080             :                 vec_name.c_str(),
    5081             :                 static_cast<const void*>(data));
    5082             :          printf("[ ");
    5083             :          for (std::size_t i = 0; i <  size; ++i)
    5084             :          {
    5085             :             printf("%8.3f\t", data[i]);
    5086             :          }
    5087             :          printf(" ]\n");
    5088             :          printf("---------------------\n");
    5089             :       }
    5090             :       #else
    5091     1089979 :       inline void dump_ptr(const std::string&, const void*) {}
    5092        9157 :       inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
    5093             :       template <typename T>
    5094             :       inline void dump_vector(const std::string&, const T*, const std::size_t) {}
    5095             :       #endif
    5096             : 
    5097             :       template <typename T>
    5098             :       class vec_data_store
    5099             :       {
    5100             :       public:
    5101             : 
    5102             :          typedef vec_data_store<T> type;
    5103             :          typedef T* data_t;
    5104             : 
    5105             :       private:
    5106             : 
    5107             :          struct control_block
    5108             :          {
    5109       21044 :             control_block()
    5110       21044 :             : ref_count(1)
    5111       21044 :             , size     (0)
    5112       21044 :             , data     (0)
    5113       21044 :             , destruct (true)
    5114       21044 :             {}
    5115             : 
    5116        9157 :             explicit control_block(const std::size_t& dsize)
    5117        9157 :             : ref_count(1    )
    5118        9157 :             , size     (dsize)
    5119        9157 :             , data     (0    )
    5120        9157 :             , destruct (true )
    5121        9157 :             { create_data(); }
    5122             : 
    5123       41607 :             control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
    5124       41607 :             : ref_count(1     )
    5125       41607 :             , size     (dsize )
    5126       41607 :             , data     (dptr  )
    5127       41607 :             , destruct (dstrct)
    5128       41607 :             {}
    5129             : 
    5130       71808 :            ~control_block()
    5131             :             {
    5132       71808 :                if (data && destruct && (0 == ref_count))
    5133             :                {
    5134       18314 :                   dump_ptr("~vec_data_store::control_block() data",data);
    5135        9157 :                   delete[] data;
    5136        9157 :                   data = reinterpret_cast<data_t>(0);
    5137             :                }
    5138       71808 :             }
    5139             : 
    5140       71808 :             static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
    5141             :             {
    5142       71808 :                if (dsize)
    5143             :                {
    5144       50764 :                   if (0 == data_ptr)
    5145        9157 :                      return (new control_block(dsize));
    5146             :                   else
    5147       41607 :                      return (new control_block(dsize, data_ptr, dstrct));
    5148             :                }
    5149             :                else
    5150       21044 :                   return (new control_block);
    5151             :             }
    5152             : 
    5153      112315 :             static inline void destroy(control_block*& cntrl_blck)
    5154             :             {
    5155      112315 :                if (cntrl_blck)
    5156             :                {
    5157      112315 :                   if (
    5158      224630 :                        (0 !=   cntrl_blck->ref_count) &&
    5159      112315 :                        (0 == --cntrl_blck->ref_count)
    5160             :                      )
    5161             :                   {
    5162       71808 :                      delete cntrl_blck;
    5163             :                   }
    5164             : 
    5165      112315 :                   cntrl_blck = 0;
    5166             :                }
    5167      112315 :             }
    5168             : 
    5169             :             std::size_t ref_count;
    5170             :             std::size_t size;
    5171             :             data_t      data;
    5172             :             bool        destruct;
    5173             : 
    5174             :          private:
    5175             : 
    5176             :             control_block(const control_block&) exprtk_delete;
    5177             :             control_block& operator=(const control_block&) exprtk_delete;
    5178             : 
    5179        9157 :             inline void create_data()
    5180             :             {
    5181        9157 :                destruct = true;
    5182        9157 :                data     = new T[size];
    5183        9157 :                std::fill_n(data, size, T(0));
    5184       18314 :                dump_ptr("control_block::create_data() - data", data, size);
    5185        9157 :             }
    5186             :          };
    5187             : 
    5188             :       public:
    5189             : 
    5190       21044 :          vec_data_store()
    5191       21044 :          : control_block_(control_block::create(0))
    5192       21044 :          {}
    5193             : 
    5194        9157 :          explicit vec_data_store(const std::size_t& size)
    5195        9157 :          : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true))
    5196        9157 :          {}
    5197             : 
    5198       41607 :          vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
    5199       41607 :          : control_block_(control_block::create(size, data, dstrct))
    5200       41607 :          {}
    5201             : 
    5202       18752 :          vec_data_store(const type& vds)
    5203             :          {
    5204       18752 :             control_block_ = vds.control_block_;
    5205       18752 :             control_block_->ref_count++;
    5206       18752 :          }
    5207             : 
    5208       90560 :         ~vec_data_store()
    5209             :          {
    5210       90560 :             control_block::destroy(control_block_);
    5211       90560 :          }
    5212             : 
    5213       22422 :          type& operator=(const type& vds)
    5214             :          {
    5215       22422 :             if (this != &vds)
    5216             :             {
    5217       22422 :                const std::size_t final_size = min_size(control_block_, vds.control_block_);
    5218             : 
    5219       22422 :                vds.control_block_->size = final_size;
    5220       22422 :                    control_block_->size = final_size;
    5221             : 
    5222       22422 :                if (control_block_->destruct || (0 == control_block_->data))
    5223             :                {
    5224       21755 :                   control_block::destroy(control_block_);
    5225             : 
    5226       21755 :                   control_block_ = vds.control_block_;
    5227       21755 :                   control_block_->ref_count++;
    5228             :                }
    5229             :             }
    5230             : 
    5231       22422 :             return (*this);
    5232             :          }
    5233             : 
    5234       35805 :          inline data_t data()
    5235             :          {
    5236       35805 :             return control_block_->data;
    5237             :          }
    5238             : 
    5239    32948858 :          inline data_t data() const
    5240             :          {
    5241    32948858 :             return control_block_->data;
    5242             :          }
    5243             : 
    5244       32942 :          inline std::size_t size() const
    5245             :          {
    5246       32942 :             return control_block_->size;
    5247             :          }
    5248             : 
    5249       99143 :          inline data_t& ref()
    5250             :          {
    5251       99143 :             return control_block_->data;
    5252             :          }
    5253             : 
    5254             :          inline void dump() const
    5255             :          {
    5256             :             #ifdef exprtk_enable_debugging
    5257             :             exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
    5258             :                           size(),
    5259             :                           data(),
    5260             :                           (control_block_->destruct ? 'T' : 'F')));
    5261             : 
    5262             :             for (std::size_t i = 0; i < size(); ++i)
    5263             :             {
    5264             :                if (5 == i)
    5265             :                   exprtk_debug(("\n"));
    5266             : 
    5267             :                exprtk_debug(("%15.10f ", data()[i]));
    5268             :             }
    5269             :             exprtk_debug(("\n"));
    5270             :             #endif
    5271             :          }
    5272             : 
    5273         499 :          static inline void match_sizes(type& vds0, type& vds1)
    5274             :          {
    5275         499 :             const std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
    5276         499 :             vds0.control_block_->size = size;
    5277         499 :             vds1.control_block_->size = size;
    5278         499 :          }
    5279             : 
    5280             :       private:
    5281             : 
    5282       22921 :          static inline std::size_t min_size(const control_block* cb0, const control_block* cb1)
    5283             :          {
    5284       22921 :             const std::size_t size0 = cb0->size;
    5285       22921 :             const std::size_t size1 = cb1->size;
    5286             : 
    5287       22921 :             if (size0 && size1)
    5288        1877 :                return std::min(size0,size1);
    5289             :             else
    5290       21044 :                return (size0) ? size0 : size1;
    5291             :          }
    5292             : 
    5293             :          control_block* control_block_;
    5294             :       };
    5295             : 
    5296             :       namespace numeric
    5297             :       {
    5298             :          namespace details
    5299             :          {
    5300             :             template <typename T>
    5301       97415 :             inline T process_impl(const operator_type operation, const T arg)
    5302             :             {
    5303       97415 :                switch (operation)
    5304             :                {
    5305         160 :                   case e_abs   : return numeric::abs  (arg);
    5306           0 :                   case e_acos  : return numeric::acos (arg);
    5307          15 :                   case e_acosh : return numeric::acosh(arg);
    5308           0 :                   case e_asin  : return numeric::asin (arg);
    5309          15 :                   case e_asinh : return numeric::asinh(arg);
    5310           0 :                   case e_atan  : return numeric::atan (arg);
    5311          15 :                   case e_atanh : return numeric::atanh(arg);
    5312          60 :                   case e_ceil  : return numeric::ceil (arg);
    5313         156 :                   case e_cos   : return numeric::cos  (arg);
    5314          15 :                   case e_cosh  : return numeric::cosh (arg);
    5315          32 :                   case e_exp   : return numeric::exp  (arg);
    5316           0 :                   case e_expm1 : return numeric::expm1(arg);
    5317          60 :                   case e_floor : return numeric::floor(arg);
    5318          45 :                   case e_log   : return numeric::log  (arg);
    5319          45 :                   case e_log10 : return numeric::log10(arg);
    5320          10 :                   case e_log2  : return numeric::log2 (arg);
    5321           0 :                   case e_log1p : return numeric::log1p(arg);
    5322       93938 :                   case e_neg   : return numeric::neg  (arg);
    5323           0 :                   case e_pos   : return numeric::pos  (arg);
    5324          60 :                   case e_round : return numeric::round(arg);
    5325         150 :                   case e_sin   : return numeric::sin  (arg);
    5326           0 :                   case e_sinc  : return numeric::sinc (arg);
    5327          15 :                   case e_sinh  : return numeric::sinh (arg);
    5328        1688 :                   case e_sqrt  : return numeric::sqrt (arg);
    5329          27 :                   case e_tan   : return numeric::tan  (arg);
    5330          15 :                   case e_tanh  : return numeric::tanh (arg);
    5331           0 :                   case e_cot   : return numeric::cot  (arg);
    5332           0 :                   case e_sec   : return numeric::sec  (arg);
    5333           0 :                   case e_csc   : return numeric::csc  (arg);
    5334           0 :                   case e_r2d   : return numeric::r2d  (arg);
    5335          90 :                   case e_d2r   : return numeric::d2r  (arg);
    5336           0 :                   case e_d2g   : return numeric::d2g  (arg);
    5337           0 :                   case e_g2d   : return numeric::g2d  (arg);
    5338         720 :                   case e_notl  : return numeric::notl (arg);
    5339          45 :                   case e_sgn   : return numeric::sgn  (arg);
    5340           1 :                   case e_erf   : return numeric::erf  (arg);
    5341           1 :                   case e_erfc  : return numeric::erfc (arg);
    5342           0 :                   case e_ncdf  : return numeric::ncdf (arg);
    5343          15 :                   case e_frac  : return numeric::frac (arg);
    5344          22 :                   case e_trunc : return numeric::trunc(arg);
    5345             : 
    5346           0 :                   default      : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
    5347           0 :                                  return std::numeric_limits<T>::quiet_NaN();
    5348             :                }
    5349             :             }
    5350             : 
    5351             :             template <typename T>
    5352      441216 :             inline T process_impl(const operator_type operation, const T arg0, const T arg1)
    5353             :             {
    5354      441216 :                switch (operation)
    5355             :                {
    5356       38524 :                   case e_add    : return (arg0 + arg1);
    5357       31952 :                   case e_sub    : return (arg0 - arg1);
    5358       47276 :                   case e_mul    : return (arg0 * arg1);
    5359       48112 :                   case e_div    : return (arg0 / arg1);
    5360          11 :                   case e_mod    : return modulus<T>(arg0,arg1);
    5361        6004 :                   case e_pow    : return pow<T>(arg0,arg1);
    5362           0 :                   case e_atan2  : return atan2<T>(arg0,arg1);
    5363           0 :                   case e_min    : return std::min<T>(arg0,arg1);
    5364           0 :                   case e_max    : return std::max<T>(arg0,arg1);
    5365           0 :                   case e_logn   : return logn<T>(arg0,arg1);
    5366        1066 :                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
    5367         335 :                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
    5368        2357 :                   case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
    5369         285 :                   case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
    5370         130 :                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
    5371         886 :                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
    5372         485 :                   case e_and    : return and_opr <T>(arg0,arg1);
    5373         600 :                   case e_nand   : return nand_opr<T>(arg0,arg1);
    5374         440 :                   case e_or     : return or_opr  <T>(arg0,arg1);
    5375         600 :                   case e_nor    : return nor_opr <T>(arg0,arg1);
    5376         240 :                   case e_xor    : return xor_opr <T>(arg0,arg1);
    5377          80 :                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
    5378         160 :                   case e_root   : return root    <T>(arg0,arg1);
    5379         120 :                   case e_roundn : return roundn  <T>(arg0,arg1);
    5380      261503 :                   case e_equal  : return equal   <T>(arg0,arg1);
    5381          20 :                   case e_nequal : return nequal  <T>(arg0,arg1);
    5382          30 :                   case e_hypot  : return hypot   <T>(arg0,arg1);
    5383           0 :                   case e_shr    : return shr     <T>(arg0,arg1);
    5384           0 :                   case e_shl    : return shl     <T>(arg0,arg1);
    5385             : 
    5386           0 :                   default       : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
    5387           0 :                                   return std::numeric_limits<T>::quiet_NaN();
    5388             :                }
    5389             :             }
    5390             : 
    5391             :             template <typename T>
    5392             :             inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
    5393             :             {
    5394             :                switch (operation)
    5395             :                {
    5396             :                   case e_add    : return (arg0 + arg1);
    5397             :                   case e_sub    : return (arg0 - arg1);
    5398             :                   case e_mul    : return (arg0 * arg1);
    5399             :                   case e_div    : return (arg0 / arg1);
    5400             :                   case e_mod    : return arg0 % arg1;
    5401             :                   case e_pow    : return pow<T>(arg0,arg1);
    5402             :                   case e_min    : return std::min<T>(arg0,arg1);
    5403             :                   case e_max    : return std::max<T>(arg0,arg1);
    5404             :                   case e_logn   : return logn<T>(arg0,arg1);
    5405             :                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
    5406             :                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
    5407             :                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
    5408             :                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
    5409             :                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
    5410             :                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
    5411             :                   case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
    5412             :                   case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
    5413             :                   case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
    5414             :                   case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
    5415             :                   case e_xor    : return arg0 ^ arg1;
    5416             :                   case e_xnor   : return !(arg0 ^ arg1);
    5417             :                   case e_root   : return root<T>(arg0,arg1);
    5418             :                   case e_equal  : return arg0 == arg1;
    5419             :                   case e_nequal : return arg0 != arg1;
    5420             :                   case e_hypot  : return hypot<T>(arg0,arg1);
    5421             :                   case e_shr    : return arg0 >> arg1;
    5422             :                   case e_shl    : return arg0 << arg1;
    5423             : 
    5424             :                   default       : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
    5425             :                                   return std::numeric_limits<T>::quiet_NaN();
    5426             :                }
    5427             :             }
    5428             :          }
    5429             : 
    5430             :          template <typename T>
    5431       97415 :          inline T process(const operator_type operation, const T arg)
    5432             :          {
    5433       97415 :             return exprtk::details::numeric::details::process_impl(operation,arg);
    5434             :          }
    5435             : 
    5436             :          template <typename T>
    5437      441216 :          inline T process(const operator_type operation, const T arg0, const T arg1)
    5438             :          {
    5439      441216 :             return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
    5440             :          }
    5441             :       }
    5442             : 
    5443             :       template <typename Node>
    5444             :       struct node_collector_interface
    5445             :       {
    5446             :          typedef Node* node_ptr_t;
    5447             :          typedef Node** node_pp_t;
    5448             :          typedef std::vector<node_pp_t> noderef_list_t;
    5449             : 
    5450     6406822 :          virtual ~node_collector_interface()
    5451     6406822 :          {}
    5452             : 
    5453     3925757 :          virtual void collect_nodes(noderef_list_t&)
    5454     3925757 :          {}
    5455             :       };
    5456             : 
    5457             :       template <typename Node>
    5458             :       struct node_depth_base;
    5459             : 
    5460             :       template <typename T>
    5461             :       class expression_node : public node_collector_interface<expression_node<T> >
    5462             :                             , public node_depth_base<expression_node<T> >
    5463             :       {
    5464             :       public:
    5465             : 
    5466             :          enum node_type
    5467             :          {
    5468             :             e_none          , e_null          , e_constant    , e_unary        ,
    5469             :             e_binary        , e_binary_ext    , e_trinary     , e_quaternary   ,
    5470             :             e_vararg        , e_conditional   , e_while       , e_repeat       ,
    5471             :             e_for           , e_switch        , e_mswitch     , e_return       ,
    5472             :             e_retenv        , e_variable      , e_stringvar   , e_stringconst  ,
    5473             :             e_stringvarrng  , e_cstringvarrng , e_strgenrange , e_strconcat    ,
    5474             :             e_stringvarsize , e_strswap       , e_stringsize  , e_stringvararg ,
    5475             :             e_function      , e_vafunction    , e_genfunction , e_strfunction  ,
    5476             :             e_strcondition  , e_strccondition , e_add         , e_sub          ,
    5477             :             e_mul           , e_div           , e_mod         , e_pow          ,
    5478             :             e_lt            , e_lte           , e_gt          , e_gte          ,
    5479             :             e_eq            , e_ne            , e_and         , e_nand         ,
    5480             :             e_or            , e_nor           , e_xor         , e_xnor         ,
    5481             :             e_in            , e_like          , e_ilike       , e_inranges     ,
    5482             :             e_ipow          , e_ipowinv       , e_abs         , e_acos         ,
    5483             :             e_acosh         , e_asin          , e_asinh       , e_atan         ,
    5484             :             e_atanh         , e_ceil          , e_cos         , e_cosh         ,
    5485             :             e_exp           , e_expm1         , e_floor       , e_log          ,
    5486             :             e_log10         , e_log2          , e_log1p       , e_neg          ,
    5487             :             e_pos           , e_round         , e_sin         , e_sinc         ,
    5488             :             e_sinh          , e_sqrt          , e_tan         , e_tanh         ,
    5489             :             e_cot           , e_sec           , e_csc         , e_r2d          ,
    5490             :             e_d2r           , e_d2g           , e_g2d         , e_notl         ,
    5491             :             e_sgn           , e_erf           , e_erfc        , e_ncdf         ,
    5492             :             e_frac          , e_trunc         , e_uvouv       , e_vov          ,
    5493             :             e_cov           , e_voc           , e_vob         , e_bov          ,
    5494             :             e_cob           , e_boc           , e_vovov       , e_vovoc        ,
    5495             :             e_vocov         , e_covov         , e_covoc       , e_vovovov      ,
    5496             :             e_vovovoc       , e_vovocov       , e_vocovov     , e_covovov      ,
    5497             :             e_covocov       , e_vocovoc       , e_covovoc     , e_vococov      ,
    5498             :             e_sf3ext        , e_sf4ext        , e_nulleq      , e_strass       ,
    5499             :             e_vector        , e_vecsize       , e_vecelem     , e_veccelem     ,
    5500             :             e_vecelemrtc    , e_veccelemrtc   , e_rbvecelem   , e_rbvecelemrtc ,
    5501             :             e_rbveccelem    , e_rbveccelemrtc ,  e_vecdefass  , e_vecvalass    ,
    5502             :             e_vecvecass     , e_vecopvalass   , e_vecopvecass , e_vecfunc      ,
    5503             :             e_vecvecswap    , e_vecvecineq    , e_vecvalineq  , e_valvecineq   ,
    5504             :             e_vecvecarith   , e_vecvalarith   , e_valvecarith , e_vecunaryop   ,
    5505             :             e_vecondition   , e_break         , e_continue    , e_swap
    5506             :          };
    5507             : 
    5508             :          typedef T value_type;
    5509             :          typedef expression_node<T>* expression_ptr;
    5510             :          typedef node_collector_interface<expression_node<T> > nci_t;
    5511             :          typedef typename nci_t::noderef_list_t noderef_list_t;
    5512             :          typedef node_depth_base<expression_node<T> > ndb_t;
    5513             : 
    5514     6406822 :          virtual ~expression_node()
    5515     6406822 :          {}
    5516             : 
    5517           0 :          inline virtual T value() const
    5518             :          {
    5519           0 :             return std::numeric_limits<T>::quiet_NaN();
    5520             :          }
    5521             : 
    5522           0 :          inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
    5523             :          {
    5524           0 :             return reinterpret_cast<expression_ptr>(index * 0);
    5525             :          }
    5526             : 
    5527    22961942 :          inline virtual node_type type() const
    5528             :          {
    5529    22961942 :             return e_none;
    5530             :          }
    5531             : 
    5532     5300990 :          inline virtual bool valid() const
    5533             :          {
    5534     5300990 :             return true;
    5535             :          }
    5536             :       }; // class expression_node
    5537             : 
    5538             :       template <typename T>
    5539             :       inline bool is_generally_string_node(const expression_node<T>* node);
    5540             : 
    5541    20651200 :       inline bool is_true(const double v)
    5542             :       {
    5543    20651200 :          return std::not_equal_to<double>()(0.0,v);
    5544             :       }
    5545             : 
    5546             :       inline bool is_true(const long double v)
    5547             :       {
    5548             :          return std::not_equal_to<long double>()(0.0L,v);
    5549             :       }
    5550             : 
    5551             :       inline bool is_true(const float v)
    5552             :       {
    5553             :          return std::not_equal_to<float>()(0.0f,v);
    5554             :       }
    5555             : 
    5556             :       template <typename T>
    5557    20744450 :       inline bool is_true(const expression_node<T>* node)
    5558             :       {
    5559    20744450 :          return std::not_equal_to<T>()(T(0),node->value());
    5560             :       }
    5561             : 
    5562             :       template <typename T>
    5563   166324190 :       inline bool is_true(const std::pair<expression_node<T>*,bool>& node)
    5564             :       {
    5565   166324190 :          return std::not_equal_to<T>()(T(0),node.first->value());
    5566             :       }
    5567             : 
    5568             :       template <typename T>
    5569        1215 :       inline bool is_false(const expression_node<T>* node)
    5570             :       {
    5571        1215 :          return std::equal_to<T>()(T(0),node->value());
    5572             :       }
    5573             : 
    5574             :       template <typename T>
    5575             :       inline bool is_false(const std::pair<expression_node<T>*,bool>& node)
    5576             :       {
    5577             :          return std::equal_to<T>()(T(0),node.first->value());
    5578             :       }
    5579             : 
    5580             :       template <typename T>
    5581             :       inline bool is_literal_node(const expression_node<T>* node)
    5582             :       {
    5583             :          return node && (details::expression_node<T>::e_constant == node->type());
    5584             :       }
    5585             : 
    5586             :       template <typename T>
    5587             :       inline bool is_unary_node(const expression_node<T>* node)
    5588             :       {
    5589             :          return node && (details::expression_node<T>::e_unary == node->type());
    5590             :       }
    5591             : 
    5592             :       template <typename T>
    5593      910752 :       inline bool is_neg_unary_node(const expression_node<T>* node)
    5594             :       {
    5595      910752 :          return node && (details::expression_node<T>::e_neg == node->type());
    5596             :       }
    5597             : 
    5598             :       template <typename T>
    5599             :       inline bool is_binary_node(const expression_node<T>* node)
    5600             :       {
    5601             :          return node && (details::expression_node<T>::e_binary == node->type());
    5602             :       }
    5603             : 
    5604             :       template <typename T>
    5605    14691910 :       inline bool is_variable_node(const expression_node<T>* node)
    5606             :       {
    5607    14691910 :          return node && (details::expression_node<T>::e_variable == node->type());
    5608             :       }
    5609             : 
    5610             :       template <typename T>
    5611        5456 :       inline bool is_ivariable_node(const expression_node<T>* node)
    5612             :       {
    5613       10912 :          return node &&
    5614             :                 (
    5615        5456 :                   details::expression_node<T>::e_variable      == node->type() ||
    5616        4816 :                   details::expression_node<T>::e_vecelem       == node->type() ||
    5617        4336 :                   details::expression_node<T>::e_veccelem      == node->type() ||
    5618        4336 :                   details::expression_node<T>::e_vecelemrtc    == node->type() ||
    5619        4324 :                   details::expression_node<T>::e_veccelemrtc   == node->type() ||
    5620        4324 :                   details::expression_node<T>::e_rbvecelem     == node->type() ||
    5621        4324 :                   details::expression_node<T>::e_rbveccelem    == node->type() ||
    5622        4324 :                   details::expression_node<T>::e_rbvecelemrtc  == node->type() ||
    5623        4324 :                   details::expression_node<T>::e_rbveccelemrtc == node->type()
    5624        5456 :                 );
    5625             :       }
    5626             : 
    5627             :       template <typename T>
    5628       29739 :       inline bool is_vector_elem_node(const expression_node<T>* node)
    5629             :       {
    5630       29739 :          return node && (details::expression_node<T>::e_vecelem == node->type());
    5631             :       }
    5632             : 
    5633             :       template <typename T>
    5634       21677 :       inline bool is_vector_celem_node(const expression_node<T>* node)
    5635             :       {
    5636       21677 :          return node && (details::expression_node<T>::e_veccelem == node->type());
    5637             :       }
    5638             : 
    5639             :       template <typename T>
    5640       28104 :       inline bool is_vector_elem_rtc_node(const expression_node<T>* node)
    5641             :       {
    5642       28104 :          return node && (details::expression_node<T>::e_vecelemrtc == node->type());
    5643             :       }
    5644             : 
    5645             :       template <typename T>
    5646       28028 :       inline bool is_vector_celem_rtc_node(const expression_node<T>* node)
    5647             :       {
    5648       28028 :          return node && (details::expression_node<T>::e_veccelemrtc == node->type());
    5649             :       }
    5650             : 
    5651             :       template <typename T>
    5652       28328 :       inline bool is_rebasevector_elem_node(const expression_node<T>* node)
    5653             :       {
    5654       28328 :          return node && (details::expression_node<T>::e_rbvecelem == node->type());
    5655             :       }
    5656             : 
    5657             :       template <typename T>
    5658       26828 :       inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node)
    5659             :       {
    5660       26828 :          return node && (details::expression_node<T>::e_rbvecelemrtc == node->type());
    5661             :       }
    5662             : 
    5663             :       template <typename T>
    5664        8972 :       inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node)
    5665             :       {
    5666        8972 :          return node && (details::expression_node<T>::e_rbveccelemrtc == node->type());
    5667             :       }
    5668             : 
    5669             :       template <typename T>
    5670       27728 :       inline bool is_rebasevector_celem_node(const expression_node<T>* node)
    5671             :       {
    5672       27728 :          return node && (details::expression_node<T>::e_rbveccelem == node->type());
    5673             :       }
    5674             : 
    5675             :       template <typename T>
    5676      344382 :       inline bool is_vector_node(const expression_node<T>* node)
    5677             :       {
    5678      344382 :          return node && (details::expression_node<T>::e_vector == node->type());
    5679             :       }
    5680             : 
    5681             :       template <typename T>
    5682    13397019 :       inline bool is_ivector_node(const expression_node<T>* node)
    5683             :       {
    5684    13397019 :          if (node)
    5685             :          {
    5686    13395577 :             switch (node->type())
    5687             :             {
    5688       89328 :                case details::expression_node<T>::e_vector      :
    5689             :                case details::expression_node<T>::e_vecvalass   :
    5690             :                case details::expression_node<T>::e_vecvecass   :
    5691             :                case details::expression_node<T>::e_vecopvalass :
    5692             :                case details::expression_node<T>::e_vecopvecass :
    5693             :                case details::expression_node<T>::e_vecvecswap  :
    5694             :                case details::expression_node<T>::e_vecvecarith :
    5695             :                case details::expression_node<T>::e_vecvalarith :
    5696             :                case details::expression_node<T>::e_valvecarith :
    5697             :                case details::expression_node<T>::e_vecunaryop  :
    5698       89328 :                case details::expression_node<T>::e_vecondition : return true;
    5699    13306249 :                default                                         : return false;
    5700             :             }
    5701             :          }
    5702             :          else
    5703        1442 :             return false;
    5704             :       }
    5705             : 
    5706             :       template <typename T>
    5707    19052734 :       inline bool is_constant_node(const expression_node<T>* node)
    5708             :       {
    5709    38105468 :          return node &&
    5710             :          (
    5711    19052734 :            details::expression_node<T>::e_constant    == node->type() ||
    5712    13225327 :            details::expression_node<T>::e_stringconst == node->type()
    5713    19052734 :          );
    5714             :       }
    5715             : 
    5716             :       template <typename T>
    5717    11049570 :       inline bool is_null_node(const expression_node<T>* node)
    5718             :       {
    5719    11049570 :          return node && (details::expression_node<T>::e_null == node->type());
    5720             :       }
    5721             : 
    5722             :       template <typename T>
    5723     6141941 :       inline bool is_break_node(const expression_node<T>* node)
    5724             :       {
    5725     6141941 :          return node && (details::expression_node<T>::e_break == node->type());
    5726             :       }
    5727             : 
    5728             :       template <typename T>
    5729     6141621 :       inline bool is_continue_node(const expression_node<T>* node)
    5730             :       {
    5731     6141621 :          return node && (details::expression_node<T>::e_continue == node->type());
    5732             :       }
    5733             : 
    5734             :       template <typename T>
    5735             :       inline bool is_swap_node(const expression_node<T>* node)
    5736             :       {
    5737             :          return node && (details::expression_node<T>::e_swap == node->type());
    5738             :       }
    5739             : 
    5740             :       template <typename T>
    5741             :       inline bool is_function(const expression_node<T>* node)
    5742             :       {
    5743             :          return node && (details::expression_node<T>::e_function == node->type());
    5744             :       }
    5745             : 
    5746             :       template <typename T>
    5747     5733352 :       inline bool is_return_node(const expression_node<T>* node)
    5748             :       {
    5749     5733352 :          return node && (details::expression_node<T>::e_return == node->type());
    5750             :       }
    5751             : 
    5752             :       template <typename T> class unary_node;
    5753             : 
    5754             :       template <typename T>
    5755             :       inline bool is_negate_node(const expression_node<T>* node)
    5756             :       {
    5757             :          if (node && is_unary_node(node))
    5758             :          {
    5759             :             return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
    5760             :          }
    5761             :          else
    5762             :             return false;
    5763             :       }
    5764             : 
    5765             :       template <typename T>
    5766     3939206 :       inline bool branch_deletable(const expression_node<T>* node)
    5767             :       {
    5768     3939206 :          return (0 != node)             &&
    5769     7784835 :                 !is_variable_node(node) &&
    5770     7784835 :                 !is_string_node  (node) ;
    5771             :       }
    5772             : 
    5773             :       template <std::size_t N, typename T>
    5774      716730 :       inline bool all_nodes_valid(expression_node<T>* const (&b)[N])
    5775             :       {
    5776     2217259 :          for (std::size_t i = 0; i < N; ++i)
    5777             :          {
    5778     1500529 :             if (0 == b[i]) return false;
    5779             :          }
    5780             : 
    5781      716730 :          return true;
    5782             :       }
    5783             : 
    5784             :       template <typename T,
    5785             :                 typename Allocator,
    5786             :                 template <typename, typename> class Sequence>
    5787       45000 :       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
    5788             :       {
    5789      168143 :          for (std::size_t i = 0; i < b.size(); ++i)
    5790             :          {
    5791      123143 :             if (0 == b[i]) return false;
    5792             :          }
    5793             : 
    5794       45000 :          return true;
    5795             :       }
    5796             : 
    5797             :       template <std::size_t N, typename T>
    5798        2710 :       inline bool all_nodes_variables(expression_node<T>* const (&b)[N])
    5799             :       {
    5800       12350 :          for (std::size_t i = 0; i < N; ++i)
    5801             :          {
    5802        9640 :             if (0 == b[i])
    5803           0 :                return false;
    5804        9640 :             else if (!is_variable_node(b[i]))
    5805           0 :                return false;
    5806             :          }
    5807             : 
    5808        2710 :          return true;
    5809             :       }
    5810             : 
    5811             :       template <typename T,
    5812             :                 typename Allocator,
    5813             :                 template <typename, typename> class Sequence>
    5814       38375 :       inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b)
    5815             :       {
    5816       45425 :          for (std::size_t i = 0; i < b.size(); ++i)
    5817             :          {
    5818       43117 :             if (0 == b[i])
    5819           0 :                return false;
    5820       43117 :             else if (!is_variable_node(b[i]))
    5821       36067 :                return false;
    5822             :          }
    5823             : 
    5824        2308 :          return true;
    5825             :       }
    5826             : 
    5827             :       template <typename Node>
    5828             :       class node_collection_destructor
    5829             :       {
    5830             :       public:
    5831             : 
    5832             :          typedef node_collector_interface<Node> nci_t;
    5833             : 
    5834             :          typedef typename nci_t::node_ptr_t     node_ptr_t;
    5835             :          typedef typename nci_t::node_pp_t      node_pp_t;
    5836             :          typedef typename nci_t::noderef_list_t noderef_list_t;
    5837             : 
    5838     2822561 :          static void delete_nodes(node_ptr_t& root)
    5839             :          {
    5840     2822561 :             std::vector<node_pp_t> node_delete_list;
    5841     2822561 :             node_delete_list.reserve(1000);
    5842             : 
    5843     2822561 :             collect_nodes(root, node_delete_list);
    5844             : 
    5845     8601980 :             for (std::size_t i = 0; i < node_delete_list.size(); ++i)
    5846             :             {
    5847     5779419 :                node_ptr_t& node = *node_delete_list[i];
    5848             :                exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node)));
    5849     5779419 :                delete node;
    5850     5779419 :                node = reinterpret_cast<node_ptr_t>(0);
    5851             :             }
    5852     2822561 :          }
    5853             : 
    5854             :       private:
    5855             : 
    5856     2822561 :          static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list)
    5857             :          {
    5858     2822561 :             std::deque<node_ptr_t> node_list;
    5859     2822561 :             node_list.push_back(root);
    5860     2822561 :             node_delete_list.push_back(&root);
    5861             : 
    5862     2822561 :             noderef_list_t child_node_delete_list;
    5863     2822561 :             child_node_delete_list.reserve(1000);
    5864             : 
    5865     8601980 :             while (!node_list.empty())
    5866             :             {
    5867     5779419 :                node_list.front()->collect_nodes(child_node_delete_list);
    5868             : 
    5869     5779419 :                if (!child_node_delete_list.empty())
    5870             :                {
    5871     4796721 :                   for (std::size_t i = 0; i < child_node_delete_list.size(); ++i)
    5872             :                   {
    5873     2956858 :                      node_pp_t& node = child_node_delete_list[i];
    5874             : 
    5875     2956858 :                      if (0 == (*node))
    5876             :                      {
    5877             :                         exprtk_debug(("ncd::collect_nodes() - null node encountered.\n"));
    5878             :                      }
    5879             : 
    5880     2956858 :                      node_list.push_back(*node);
    5881             :                   }
    5882             : 
    5883     3679726 :                   node_delete_list.insert(
    5884     1839863 :                      node_delete_list.end(),
    5885             :                      child_node_delete_list.begin(), child_node_delete_list.end());
    5886             : 
    5887     1839863 :                   child_node_delete_list.clear();
    5888             :                }
    5889             : 
    5890     5779419 :                node_list.pop_front();
    5891             :             }
    5892             : 
    5893     2822561 :             std::reverse(node_delete_list.begin(), node_delete_list.end());
    5894     2822561 :          }
    5895             :       };
    5896             : 
    5897             :       template <typename NodeAllocator, typename T, std::size_t N>
    5898        8646 :       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
    5899             :       {
    5900       25993 :          for (std::size_t i = 0; i < N; ++i)
    5901             :          {
    5902       17347 :             free_node(node_allocator,b[i]);
    5903             :          }
    5904        8646 :       }
    5905             : 
    5906             :       template <typename NodeAllocator,
    5907             :                 typename T,
    5908             :                 typename Allocator,
    5909             :                 template <typename, typename> class Sequence>
    5910           0 :       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
    5911             :       {
    5912           0 :          for (std::size_t i = 0; i < b.size(); ++i)
    5913             :          {
    5914           0 :             free_node(node_allocator,b[i]);
    5915             :          }
    5916             : 
    5917           0 :          b.clear();
    5918           0 :       }
    5919             : 
    5920             :       template <typename NodeAllocator, typename T>
    5921     2452576 :       inline void free_node(NodeAllocator&, expression_node<T>*& node)
    5922             :       {
    5923     2452576 :          if ((0 == node) || is_variable_node(node) || is_string_node(node))
    5924             :          {
    5925      321182 :             return;
    5926             :          }
    5927             : 
    5928             :          node_collection_destructor<expression_node<T> >
    5929     2131394 :             ::delete_nodes(node);
    5930             :       }
    5931             : 
    5932             :       template <typename T>
    5933      691167 :       inline void destroy_node(expression_node<T>*& node)
    5934             :       {
    5935      691167 :          if (0 != node)
    5936             :          {
    5937             :             node_collection_destructor<expression_node<T> >
    5938      691167 :                ::delete_nodes(node);
    5939             :          }
    5940      691167 :       }
    5941             : 
    5942             :       template <typename Node>
    5943             :       struct node_depth_base
    5944             :       {
    5945             :          typedef Node* node_ptr_t;
    5946             :          typedef std::pair<node_ptr_t,bool> nb_pair_t;
    5947             : 
    5948     6406822 :          node_depth_base()
    5949     6406822 :          : depth_set(false)
    5950     6406822 :          , depth(0)
    5951     6406822 :          {}
    5952             : 
    5953     6406822 :          virtual ~node_depth_base()
    5954     6406822 :          {}
    5955             : 
    5956     9680844 :          virtual std::size_t node_depth() const { return 1; }
    5957             : 
    5958      159621 :          std::size_t compute_node_depth(const Node* const& node) const
    5959             :          {
    5960      159621 :             if (!depth_set)
    5961             :             {
    5962       57390 :                depth = 1 + (node ? node->node_depth() : 0);
    5963       57390 :                depth_set = true;
    5964             :             }
    5965             : 
    5966      159621 :             return depth;
    5967             :          }
    5968             : 
    5969     2147446 :          std::size_t compute_node_depth(const nb_pair_t& branch) const
    5970             :          {
    5971     2147446 :             if (!depth_set)
    5972             :             {
    5973      799666 :                depth = 1 + (branch.first ? branch.first->node_depth() : 0);
    5974      799666 :                depth_set = true;
    5975             :             }
    5976             : 
    5977     2147446 :             return depth;
    5978             :          }
    5979             : 
    5980             :          template <std::size_t N>
    5981     2795907 :          std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const
    5982             :          {
    5983     2795907 :             if (!depth_set)
    5984             :             {
    5985      993717 :                depth = 0;
    5986             : 
    5987     3064051 :                for (std::size_t i = 0; i < N; ++i)
    5988             :                {
    5989     2070334 :                   if (branch[i].first)
    5990             :                   {
    5991     1870285 :                      depth = std::max(depth,branch[i].first->node_depth());
    5992             :                   }
    5993             :                }
    5994             : 
    5995      993717 :                depth += 1;
    5996      993717 :                depth_set = true;
    5997             :             }
    5998             : 
    5999     2795907 :             return depth;
    6000             :          }
    6001             : 
    6002             :          template <typename BranchType>
    6003        5674 :          std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const
    6004             :          {
    6005        5674 :             return std::max(compute_node_depth(n0), compute_node_depth(n1));
    6006             :          }
    6007             : 
    6008             :          template <typename BranchType>
    6009        3605 :          std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const
    6010             :          {
    6011        3605 :             return std::max(compute_node_depth(n0),
    6012        7210 :                    std::max(compute_node_depth(n1), compute_node_depth(n2)));
    6013             :          }
    6014             : 
    6015             :          template <typename BranchType>
    6016        2663 :          std::size_t max_node_depth(const BranchType& n0, const BranchType& n1,
    6017             :                                     const BranchType& n2, const BranchType& n3) const
    6018             :          {
    6019        2663 :             return std::max(
    6020        2663 :                      std::max(compute_node_depth(n0), compute_node_depth(n1)),
    6021        5326 :                      std::max(compute_node_depth(n2), compute_node_depth(n3)));
    6022             :          }
    6023             : 
    6024             :          template <typename BranchType>
    6025       12762 :          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
    6026             :          {
    6027       12762 :             if (!depth_set)
    6028             :             {
    6029        5674 :                depth = 1 + max_node_depth(n0, n1);
    6030        5674 :                depth_set = true;
    6031             :             }
    6032             : 
    6033       12762 :             return depth;
    6034             :          }
    6035             : 
    6036             :          template <typename BranchType>
    6037        8893 :          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
    6038             :                                         const BranchType& n2) const
    6039             :          {
    6040        8893 :             if (!depth_set)
    6041             :             {
    6042        3605 :                depth = 1 + max_node_depth(n0, n1, n2);
    6043        3605 :                depth_set = true;
    6044             :             }
    6045             : 
    6046        8893 :             return depth;
    6047             :          }
    6048             : 
    6049             :          template <typename BranchType>
    6050        6644 :          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
    6051             :                                         const BranchType& n2, const BranchType& n3) const
    6052             :          {
    6053        6644 :             if (!depth_set)
    6054             :             {
    6055        2663 :                depth = 1 + max_node_depth(n0, n1, n2, n3);
    6056        2663 :                depth_set = true;
    6057             :             }
    6058             : 
    6059        6644 :             return depth;
    6060             :          }
    6061             : 
    6062             :          template <typename Allocator,
    6063             :                    template <typename, typename> class Sequence>
    6064       53233 :          std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const
    6065             :          {
    6066       53233 :             if (!depth_set)
    6067             :             {
    6068       68463 :                for (std::size_t i = 0; i < branch_list.size(); ++i)
    6069             :                {
    6070       48862 :                   if (branch_list[i])
    6071             :                   {
    6072       48862 :                      depth = std::max(depth, compute_node_depth(branch_list[i]));
    6073             :                   }
    6074             :                }
    6075       19601 :                depth_set = true;
    6076             :             }
    6077             : 
    6078       53233 :             return depth;
    6079             :          }
    6080             : 
    6081             :          template <typename Allocator,
    6082             :                    template <typename, typename> class Sequence>
    6083       55024 :          std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const
    6084             :          {
    6085       55024 :             if (!depth_set)
    6086             :             {
    6087      151437 :                for (std::size_t i = 0; i < branch_list.size(); ++i)
    6088             :                {
    6089      110759 :                   if (branch_list[i].first)
    6090             :                   {
    6091      110759 :                      depth = std::max(depth, compute_node_depth(branch_list[i].first));
    6092             :                   }
    6093             :                }
    6094             : 
    6095       40678 :                depth_set = true;
    6096             :             }
    6097             : 
    6098       55024 :             return depth;
    6099             :          }
    6100             : 
    6101             :          mutable bool depth_set;
    6102             :          mutable std::size_t depth;
    6103             : 
    6104             :          template <typename NodeSequence>
    6105     3055122 :          void collect(node_ptr_t const& node,
    6106             :                       const bool deletable,
    6107             :                       NodeSequence& delete_node_list) const
    6108             :          {
    6109     3055122 :             if ((0 != node) && deletable)
    6110             :             {
    6111     2956789 :                delete_node_list.push_back(const_cast<node_ptr_t*>(&node));
    6112             :             }
    6113     3055122 :          }
    6114             : 
    6115             :          template <typename NodeSequence>
    6116      820624 :          void collect(const nb_pair_t& branch,
    6117             :                       NodeSequence& delete_node_list) const
    6118             :          {
    6119      820624 :             collect(branch.first, branch.second, delete_node_list);
    6120      820624 :          }
    6121             : 
    6122             :          template <typename NodeSequence>
    6123             :          void collect(Node*& node,
    6124             :                       NodeSequence& delete_node_list) const
    6125             :          {
    6126             :             collect(node, branch_deletable(node), delete_node_list);
    6127             :          }
    6128             : 
    6129             :          template <std::size_t N, typename NodeSequence>
    6130      993717 :          void collect(const nb_pair_t(&branch)[N],
    6131             :                       NodeSequence& delete_node_list) const
    6132             :          {
    6133     3064051 :             for (std::size_t i = 0; i < N; ++i)
    6134             :             {
    6135     2070334 :                collect(branch[i].first, branch[i].second, delete_node_list);
    6136             :             }
    6137      993717 :          }
    6138             : 
    6139             :          template <typename Allocator,
    6140             :                    template <typename, typename> class Sequence,
    6141             :                    typename NodeSequence>
    6142       40678 :          void collect(const Sequence<nb_pair_t, Allocator>& branch,
    6143             :                       NodeSequence& delete_node_list) const
    6144             :          {
    6145      156097 :             for (std::size_t i = 0; i < branch.size(); ++i)
    6146             :             {
    6147      115419 :                collect(branch[i].first, branch[i].second, delete_node_list);
    6148             :             }
    6149       40678 :          }
    6150             : 
    6151             :          template <typename Allocator,
    6152             :                    template <typename, typename> class Sequence,
    6153             :                    typename NodeSequence>
    6154       19552 :          void collect(const Sequence<node_ptr_t, Allocator>& branch_list,
    6155             :                       NodeSequence& delete_node_list) const
    6156             :          {
    6157       68297 :             for (std::size_t i = 0; i < branch_list.size(); ++i)
    6158             :             {
    6159       48745 :                collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list);
    6160             :             }
    6161       19552 :          }
    6162             : 
    6163             :          template <typename Boolean,
    6164             :                    typename AllocatorT,
    6165             :                    typename AllocatorB,
    6166             :                    template <typename, typename> class Sequence,
    6167             :                    typename NodeSequence>
    6168             :          void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list,
    6169             :                       const Sequence<Boolean, AllocatorB>& branch_deletable_list,
    6170             :                       NodeSequence& delete_node_list) const
    6171             :          {
    6172             :             for (std::size_t i = 0; i < branch_list.size(); ++i)
    6173             :             {
    6174             :                collect(branch_list[i], branch_deletable_list[i], delete_node_list);
    6175             :             }
    6176             :          }
    6177             :       };
    6178             : 
    6179             :       template <typename Type>
    6180             :       class vector_holder
    6181             :       {
    6182             :       private:
    6183             : 
    6184             :          typedef Type value_type;
    6185             :          typedef value_type* value_ptr;
    6186             :          typedef const value_ptr const_value_ptr;
    6187             :          typedef vector_holder<Type> vector_holder_t;
    6188             : 
    6189             :          class vector_holder_base
    6190             :          {
    6191             :          public:
    6192             : 
    6193           0 :             virtual ~vector_holder_base()
    6194           0 :             {}
    6195             : 
    6196       74281 :             inline value_ptr operator[](const std::size_t& index) const
    6197             :             {
    6198       74281 :                return value_at(index);
    6199             :             }
    6200             : 
    6201      176735 :             inline std::size_t size() const
    6202             :             {
    6203      176735 :                return vector_size();
    6204             :             }
    6205             : 
    6206      108927 :             inline std::size_t base_size() const
    6207             :             {
    6208      108927 :                return vector_base_size();
    6209             :             }
    6210             : 
    6211        9341 :             inline value_ptr data() const
    6212             :             {
    6213        9341 :                return value_at(0);
    6214             :             }
    6215             : 
    6216      134633 :             virtual inline bool rebaseable() const
    6217             :             {
    6218      134633 :                return false;
    6219             :             }
    6220             : 
    6221           0 :             virtual void set_ref(value_ptr*)
    6222           0 :             {}
    6223             : 
    6224         478 :             virtual void remove_ref(value_ptr*)
    6225         478 :             {}
    6226             : 
    6227           0 :             virtual vector_view<Type>* rebaseable_instance()
    6228             :             {
    6229           0 :                return reinterpret_cast<vector_view<Type>*>(0);
    6230             :             }
    6231             : 
    6232             :          protected:
    6233             : 
    6234             :             virtual value_ptr value_at(const std::size_t&) const = 0;
    6235             :             virtual std::size_t vector_size()              const = 0;
    6236             :             virtual std::size_t vector_base_size()         const = 0;
    6237             :          };
    6238             : 
    6239             :          class array_vector_impl exprtk_final : public vector_holder_base
    6240             :          {
    6241             :          public:
    6242             : 
    6243       36371 :             array_vector_impl(const Type* vec, const std::size_t& vec_size)
    6244       36371 :             : vec_(vec)
    6245       36371 :             , size_(vec_size)
    6246       36371 :             {}
    6247             : 
    6248             :          protected:
    6249             : 
    6250       75804 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6251             :             {
    6252       75804 :                assert(index < size_);
    6253       75804 :                return const_cast<const_value_ptr>(vec_ + index);
    6254             :             }
    6255             : 
    6256      265553 :             std::size_t vector_size() const exprtk_override
    6257             :             {
    6258      265553 :                return size_;
    6259             :             }
    6260             : 
    6261      105511 :             std::size_t vector_base_size() const exprtk_override
    6262             :             {
    6263      105511 :                return vector_size();
    6264             :             }
    6265             : 
    6266             :          private:
    6267             : 
    6268             :             array_vector_impl(const array_vector_impl&) exprtk_delete;
    6269             :             array_vector_impl& operator=(const array_vector_impl&) exprtk_delete;
    6270             : 
    6271             :             const Type* vec_;
    6272             :             const std::size_t size_;
    6273             :          };
    6274             : 
    6275             :          template <typename Allocator,
    6276             :                    template <typename, typename> class Sequence>
    6277             :          class sequence_vector_impl exprtk_final : public vector_holder_base
    6278             :          {
    6279             :          public:
    6280             : 
    6281             :             typedef Sequence<Type,Allocator> sequence_t;
    6282             : 
    6283          84 :             explicit sequence_vector_impl(sequence_t& seq)
    6284          84 :             : sequence_(seq)
    6285          84 :             {}
    6286             : 
    6287             :          protected:
    6288             : 
    6289          10 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6290             :             {
    6291          10 :                assert(index < sequence_.size());
    6292          10 :                return (&sequence_[index]);
    6293             :             }
    6294             : 
    6295          60 :             std::size_t vector_size() const exprtk_override
    6296             :             {
    6297          60 :                return sequence_.size();
    6298             :             }
    6299             : 
    6300          20 :             std::size_t vector_base_size() const exprtk_override
    6301             :             {
    6302          20 :                return vector_size();
    6303             :             }
    6304             : 
    6305             :          private:
    6306             : 
    6307             :             sequence_vector_impl(const sequence_vector_impl&) exprtk_delete;
    6308             :             sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete;
    6309             : 
    6310             :             sequence_t& sequence_;
    6311             :          };
    6312             : 
    6313             :          class vector_view_impl exprtk_final : public vector_holder_base
    6314             :          {
    6315             :          public:
    6316             : 
    6317             :             typedef exprtk::vector_view<Type> vector_view_t;
    6318             : 
    6319        4195 :             vector_view_impl(vector_view_t& vec_view)
    6320        4195 :             : vec_view_(vec_view)
    6321             :             {
    6322        4195 :                assert(vec_view_.size() > 0);
    6323        4195 :             }
    6324             : 
    6325        3559 :             void set_ref(value_ptr* ref) exprtk_override
    6326             :             {
    6327        3559 :                vec_view_.set_ref(ref);
    6328        3559 :             }
    6329             : 
    6330        3559 :             void remove_ref(value_ptr* ref) exprtk_override
    6331             :             {
    6332        3559 :                vec_view_.remove_ref(ref);
    6333        3559 :             }
    6334             : 
    6335       10649 :             bool rebaseable() const exprtk_override
    6336             :             {
    6337       10649 :                return true;
    6338             :             }
    6339             : 
    6340         658 :             vector_view<Type>* rebaseable_instance() exprtk_override
    6341             :             {
    6342         658 :                return &vec_view_;
    6343             :             }
    6344             : 
    6345             :          protected:
    6346             : 
    6347        7555 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6348             :             {
    6349        7555 :                assert(index < vec_view_.size());
    6350        7555 :                return (&vec_view_[index]);
    6351             :             }
    6352             : 
    6353       15714 :             std::size_t vector_size() const exprtk_override
    6354             :             {
    6355       15714 :                return vec_view_.size();
    6356             :             }
    6357             : 
    6358        2662 :             std::size_t vector_base_size() const exprtk_override
    6359             :             {
    6360        2662 :                return vec_view_.base_size();
    6361             :             }
    6362             : 
    6363             :          private:
    6364             : 
    6365             :             vector_view_impl(const vector_view_impl&) exprtk_delete;
    6366             :             vector_view_impl& operator=(const vector_view_impl&) exprtk_delete;
    6367             : 
    6368             :             vector_view_t& vec_view_;
    6369             :          };
    6370             : 
    6371             :          class resizable_vector_impl exprtk_final : public vector_holder_base
    6372             :          {
    6373             :          public:
    6374             : 
    6375         478 :             resizable_vector_impl(vector_holder& vec_view_holder,
    6376             :                                   const Type* vec,
    6377             :                                   const std::size_t& vec_size)
    6378         478 :             : vec_(vec)
    6379         478 :             , size_(vec_size)
    6380         478 :             , vec_view_holder_(*vec_view_holder.rebaseable_instance())
    6381             :             {
    6382         478 :                assert(vec_view_holder.rebaseable_instance());
    6383         478 :                assert(size_ <= vector_base_size());
    6384         478 :             }
    6385             : 
    6386           0 :             virtual ~resizable_vector_impl()
    6387           0 :             {}
    6388             : 
    6389             :          protected:
    6390             : 
    6391         253 :             value_ptr value_at(const std::size_t& index) const exprtk_override
    6392             :             {
    6393         253 :                assert(index < vector_size());
    6394         253 :                return const_cast<const_value_ptr>(vec_ + index);
    6395             :             }
    6396             : 
    6397        1192 :             std::size_t vector_size() const exprtk_override
    6398             :             {
    6399        1192 :                return vec_view_holder_.size();
    6400             :             }
    6401             : 
    6402        1212 :             std::size_t vector_base_size() const exprtk_override
    6403             :             {
    6404        1212 :                return vec_view_holder_.base_size();
    6405             :             }
    6406             : 
    6407         903 :             bool rebaseable() const exprtk_override
    6408             :             {
    6409         903 :                return true;
    6410             :             }
    6411             : 
    6412         520 :             virtual vector_view<Type>* rebaseable_instance() exprtk_override
    6413             :             {
    6414         520 :                return &vec_view_holder_;
    6415             :             }
    6416             : 
    6417             :          private:
    6418             : 
    6419             :             resizable_vector_impl(const resizable_vector_impl&) exprtk_delete;
    6420             :             resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete;
    6421             : 
    6422             :             const Type* vec_;
    6423             :             const std::size_t size_;
    6424             :             vector_view<Type>& vec_view_holder_;
    6425             :          };
    6426             : 
    6427             :       public:
    6428             : 
    6429             :          typedef typename details::vec_data_store<Type> vds_t;
    6430             : 
    6431       20920 :          vector_holder(Type* vec, const std::size_t& vec_size)
    6432       20920 :          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
    6433       20920 :          {}
    6434             : 
    6435       15451 :          explicit vector_holder(const vds_t& vds)
    6436       15451 :          : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
    6437       15451 :          {}
    6438             : 
    6439             :          template <typename Allocator>
    6440          84 :          explicit vector_holder(std::vector<Type,Allocator>& vec)
    6441          84 :          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
    6442          84 :          {}
    6443             : 
    6444        4195 :          explicit vector_holder(exprtk::vector_view<Type>& vec)
    6445        4195 :          : vector_holder_base_(new(buffer)vector_view_impl(vec))
    6446        4195 :          {}
    6447             : 
    6448         478 :          explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds)
    6449         478 :          : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size()))
    6450         478 :          {}
    6451             : 
    6452       74281 :          inline value_ptr operator[](const std::size_t& index) const
    6453             :          {
    6454       74281 :             return (*vector_holder_base_)[index];
    6455             :          }
    6456             : 
    6457      176735 :          inline std::size_t size() const
    6458             :          {
    6459      176735 :             return vector_holder_base_->size();
    6460             :          }
    6461             : 
    6462      108927 :          inline std::size_t base_size() const
    6463             :          {
    6464      108927 :             return vector_holder_base_->base_size();
    6465             :          }
    6466             : 
    6467        9341 :          inline value_ptr data() const
    6468             :          {
    6469        9341 :             return vector_holder_base_->data();
    6470             :          }
    6471             : 
    6472       41607 :          void set_ref(value_ptr* ref)
    6473             :          {
    6474       41607 :             if (rebaseable())
    6475             :             {
    6476        3559 :                vector_holder_base_->set_ref(ref);
    6477             :             }
    6478       41607 :          }
    6479             : 
    6480       57536 :          void remove_ref(value_ptr* ref)
    6481             :          {
    6482       57536 :             if (rebaseable())
    6483             :             {
    6484        4037 :                vector_holder_base_->remove_ref(ref);
    6485             :             }
    6486       57536 :          }
    6487             : 
    6488      146185 :          bool rebaseable() const
    6489             :          {
    6490      146185 :             return vector_holder_base_->rebaseable();
    6491             :          }
    6492             : 
    6493        1178 :          vector_view<Type>* rebaseable_instance()
    6494             :          {
    6495        1178 :             return vector_holder_base_->rebaseable_instance();
    6496             :          }
    6497             : 
    6498             :       private:
    6499             : 
    6500             :          vector_holder(const vector_holder<Type>&) exprtk_delete;
    6501             :          vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete;
    6502             : 
    6503             :          mutable vector_holder_base* vector_holder_base_;
    6504             :          uchar_t buffer[64];
    6505             :       };
    6506             : 
    6507             :       template <typename T>
    6508             :       class null_node exprtk_final : public expression_node<T>
    6509             :       {
    6510             :       public:
    6511             : 
    6512         285 :          inline T value() const exprtk_override
    6513             :          {
    6514         285 :             return std::numeric_limits<T>::quiet_NaN();
    6515             :          }
    6516             : 
    6517      674795 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6518             :          {
    6519      674795 :             return expression_node<T>::e_null;
    6520             :          }
    6521             :       };
    6522             : 
    6523             :       template <typename T, std::size_t N>
    6524     9333370 :       inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N],
    6525             :                                         expression_node<T>* b,
    6526             :                                         const std::size_t& index)
    6527             :       {
    6528     9333370 :          if (b && (index < N))
    6529             :          {
    6530     1870285 :             branch[index] = std::make_pair(b,branch_deletable(b));
    6531             :          }
    6532     9333370 :       }
    6533             : 
    6534             :       template <typename T>
    6535      931383 :       inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b)
    6536             :       {
    6537      931383 :          if (b)
    6538             :          {
    6539      931182 :             branch = std::make_pair(b,branch_deletable(b));
    6540             :          }
    6541      931383 :       }
    6542             : 
    6543             :       template <std::size_t N, typename T>
    6544      933337 :       inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
    6545             :                                 expression_node<T>* b0,
    6546             :                                 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
    6547             :                                 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
    6548             :                                 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
    6549             :                                 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
    6550             :                                 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
    6551             :                                 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
    6552             :                                 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
    6553             :                                 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
    6554             :                                 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
    6555             :       {
    6556      933337 :          construct_branch_pair(branch, b0, 0);
    6557      933337 :          construct_branch_pair(branch, b1, 1);
    6558      933337 :          construct_branch_pair(branch, b2, 2);
    6559      933337 :          construct_branch_pair(branch, b3, 3);
    6560      933337 :          construct_branch_pair(branch, b4, 4);
    6561      933337 :          construct_branch_pair(branch, b5, 5);
    6562      933337 :          construct_branch_pair(branch, b6, 6);
    6563      933337 :          construct_branch_pair(branch, b7, 7);
    6564      933337 :          construct_branch_pair(branch, b8, 8);
    6565      933337 :          construct_branch_pair(branch, b9, 9);
    6566      933337 :       }
    6567             : 
    6568             :       template <typename T>
    6569             :       class null_eq_node exprtk_final : public expression_node<T>
    6570             :       {
    6571             :       public:
    6572             : 
    6573             :          typedef expression_node<T>* expression_ptr;
    6574             :          typedef std::pair<expression_ptr,bool> branch_t;
    6575             : 
    6576         195 :          explicit null_eq_node(expression_ptr branch, const bool equality = true)
    6577         195 :          : equality_(equality)
    6578             :          {
    6579         195 :             construct_branch_pair(branch_, branch);
    6580         195 :             assert(valid());
    6581         195 :          }
    6582             : 
    6583         195 :          inline T value() const exprtk_override
    6584             :          {
    6585         195 :             const T v = branch_.first->value();
    6586         195 :             const bool result = details::numeric::is_nan(v);
    6587             : 
    6588         195 :             if (result)
    6589         195 :                return equality_ ? T(1) : T(0);
    6590             :             else
    6591           0 :                return equality_ ? T(0) : T(1);
    6592             :          }
    6593             : 
    6594        1170 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6595             :          {
    6596        1170 :             return expression_node<T>::e_nulleq;
    6597             :          }
    6598             : 
    6599           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6600             :          {
    6601           0 :             return branch_.first;
    6602             :          }
    6603             : 
    6604         225 :          inline bool valid() const exprtk_override
    6605             :          {
    6606         225 :             return branch_.first;
    6607             :          }
    6608             : 
    6609         195 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6610             :          {
    6611         195 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    6612         195 :          }
    6613             : 
    6614         405 :          std::size_t node_depth() const exprtk_override
    6615             :          {
    6616         405 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
    6617             :          }
    6618             : 
    6619             :       private:
    6620             : 
    6621             :          bool equality_;
    6622             :          branch_t branch_;
    6623             :       };
    6624             : 
    6625             :       template <typename T>
    6626             :       class literal_node exprtk_final : public expression_node<T>
    6627             :       {
    6628             :       public:
    6629             : 
    6630     2088529 :          explicit literal_node(const T& v)
    6631     2088529 :          : value_(v)
    6632     2088529 :          {}
    6633             : 
    6634   139167839 :          inline T value() const exprtk_override
    6635             :          {
    6636   139167839 :             return value_;
    6637             :          }
    6638             : 
    6639    30616818 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6640             :          {
    6641    30616818 :             return expression_node<T>::e_constant;
    6642             :          }
    6643             : 
    6644           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6645             :          {
    6646           0 :             return reinterpret_cast<expression_node<T>*>(0);
    6647             :          }
    6648             : 
    6649             :       private:
    6650             : 
    6651             :          literal_node(const literal_node<T>&) exprtk_delete;
    6652             :          literal_node<T>& operator=(const literal_node<T>&) exprtk_delete;
    6653             : 
    6654             :          const T value_;
    6655             :       };
    6656             : 
    6657             :       template <typename T>
    6658             :       struct range_pack;
    6659             : 
    6660             :       template <typename T>
    6661             :       struct range_data_type;
    6662             : 
    6663             :       template <typename T>
    6664             :       class range_interface
    6665             :       {
    6666             :       public:
    6667             : 
    6668             :          typedef range_pack<T> range_t;
    6669             : 
    6670      243537 :          virtual ~range_interface()
    6671      243537 :          {}
    6672             : 
    6673             :          virtual range_t& range_ref() = 0;
    6674             : 
    6675             :          virtual const range_t& range_ref() const = 0;
    6676             :       };
    6677             : 
    6678             :       #ifndef exprtk_disable_string_capabilities
    6679             :       template <typename T>
    6680             :       class string_base_node
    6681             :       {
    6682             :       public:
    6683             : 
    6684             :          typedef range_data_type<T> range_data_type_t;
    6685             : 
    6686      243537 :          virtual ~string_base_node()
    6687      243537 :          {}
    6688             : 
    6689             :          virtual std::string str () const = 0;
    6690             : 
    6691             :          virtual char_cptr   base() const = 0;
    6692             : 
    6693             :          virtual std::size_t size() const = 0;
    6694             :       };
    6695             : 
    6696             :       template <typename T>
    6697             :       class string_literal_node exprtk_final
    6698             :                                 : public expression_node <T>
    6699             :                                 , public string_base_node<T>
    6700             :                                 , public range_interface <T>
    6701             :       {
    6702             :       public:
    6703             : 
    6704             :          typedef range_pack<T> range_t;
    6705             : 
    6706       54292 :          explicit string_literal_node(const std::string& v)
    6707       54292 :          : value_(v)
    6708             :          {
    6709       54292 :             rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0);
    6710       54292 :             rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size());
    6711       54292 :             rp_.cache.first  = rp_.n0_c.second;
    6712       54292 :             rp_.cache.second = rp_.n1_c.second;
    6713       54292 :          }
    6714             : 
    6715       24166 :          inline T value() const exprtk_override
    6716             :          {
    6717       24166 :             return std::numeric_limits<T>::quiet_NaN();
    6718             :          }
    6719             : 
    6720      898660 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6721             :          {
    6722      898660 :             return expression_node<T>::e_stringconst;
    6723             :          }
    6724             : 
    6725           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6726             :          {
    6727           0 :             return reinterpret_cast<expression_node<T>*>(0);
    6728             :          }
    6729             : 
    6730       31779 :          std::string str() const exprtk_override
    6731             :          {
    6732       31779 :             return value_;
    6733             :          }
    6734             : 
    6735       21371 :          char_cptr base() const exprtk_override
    6736             :          {
    6737       21371 :             return value_.data();
    6738             :          }
    6739             : 
    6740       24221 :          std::size_t size() const exprtk_override
    6741             :          {
    6742       24221 :             return value_.size();
    6743             :          }
    6744             : 
    6745       20125 :          range_t& range_ref() exprtk_override
    6746             :          {
    6747       20125 :             return rp_;
    6748             :          }
    6749             : 
    6750           0 :          const range_t& range_ref() const exprtk_override
    6751             :          {
    6752           0 :             return rp_;
    6753             :          }
    6754             : 
    6755             :       private:
    6756             : 
    6757             :          string_literal_node(const string_literal_node<T>&) exprtk_delete;
    6758             :          string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete;
    6759             : 
    6760             :          const std::string value_;
    6761             :          range_t rp_;
    6762             :       };
    6763             :       #endif
    6764             : 
    6765             :       template <typename T>
    6766             :       class unary_node : public expression_node<T>
    6767             :       {
    6768             :       public:
    6769             : 
    6770             :          typedef expression_node<T>* expression_ptr;
    6771             :          typedef std::pair<expression_ptr,bool> branch_t;
    6772             : 
    6773       98845 :          unary_node(const operator_type& opr, expression_ptr branch)
    6774       98845 :          : operation_(opr)
    6775             :          {
    6776       98845 :             construct_branch_pair(branch_,branch);
    6777       98845 :             assert(valid());
    6778       98845 :          }
    6779             : 
    6780       97415 :          inline T value() const exprtk_override
    6781             :          {
    6782             :             return numeric::process<T>
    6783       97415 :                      (operation_,branch_.first->value());
    6784             :          }
    6785             : 
    6786      194830 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6787             :          {
    6788      194830 :             return expression_node<T>::e_unary;
    6789             :          }
    6790             : 
    6791             :          inline operator_type operation()
    6792             :          {
    6793             :             return operation_;
    6794             :          }
    6795             : 
    6796        5689 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
    6797             :          {
    6798        5689 :             return branch_.first;
    6799             :          }
    6800             : 
    6801      107864 :          inline bool valid() const exprtk_override
    6802             :          {
    6803      107864 :             return branch_.first && branch_.first->valid();
    6804             :          }
    6805             : 
    6806             :          inline void release()
    6807             :          {
    6808             :             branch_.second = false;
    6809             :          }
    6810             : 
    6811       98845 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6812             :          {
    6813       98845 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    6814       98845 :          }
    6815             : 
    6816      198358 :          std::size_t node_depth() const exprtk_final
    6817             :          {
    6818      198358 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
    6819             :          }
    6820             : 
    6821             :       private:
    6822             : 
    6823             :          operator_type operation_;
    6824             :          branch_t branch_;
    6825             :       };
    6826             : 
    6827             :       template <typename T>
    6828             :       class binary_node : public expression_node<T>
    6829             :       {
    6830             :       public:
    6831             : 
    6832             :          typedef expression_node<T>* expression_ptr;
    6833             :          typedef std::pair<expression_ptr,bool> branch_t;
    6834             : 
    6835      524684 :          binary_node(const operator_type& opr,
    6836             :                      expression_ptr branch0,
    6837             :                      expression_ptr branch1)
    6838      524684 :          : operation_(opr)
    6839             :          {
    6840      524684 :             init_branches<2>(branch_, branch0, branch1);
    6841      524684 :             assert(valid());
    6842      524684 :          }
    6843             : 
    6844      441216 :          inline T value() const exprtk_override
    6845             :          {
    6846             :             return numeric::process<T>
    6847     1764864 :                    (
    6848      441216 :                       operation_,
    6849      441216 :                       branch_[0].first->value(),
    6850      441216 :                       branch_[1].first->value()
    6851      441216 :                    );
    6852             :          }
    6853             : 
    6854     2046724 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6855             :          {
    6856     2046724 :             return expression_node<T>::e_binary;
    6857             :          }
    6858             : 
    6859             :          inline operator_type operation()
    6860             :          {
    6861             :             return operation_;
    6862             :          }
    6863             : 
    6864   208709125 :          inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
    6865             :          {
    6866   208709125 :             assert(index < 2);
    6867   208709125 :             return branch_[index].first;
    6868             :          }
    6869             : 
    6870      984061 :          inline bool valid() const exprtk_override
    6871             :          {
    6872             :             return
    6873      984061 :                branch_[0].first && branch_[0].first->valid() &&
    6874     1968122 :                branch_[1].first && branch_[1].first->valid() ;
    6875             :          }
    6876             : 
    6877      524684 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6878             :          {
    6879      524684 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
    6880      524684 :          }
    6881             : 
    6882     1401879 :          std::size_t node_depth() const exprtk_final
    6883             :          {
    6884     1401879 :             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
    6885             :          }
    6886             : 
    6887             :       private:
    6888             : 
    6889             :          operator_type operation_;
    6890             :          branch_t branch_[2];
    6891             :       };
    6892             : 
    6893             :       template <typename T, typename Operation>
    6894             :       class binary_ext_node exprtk_final : public expression_node<T>
    6895             :       {
    6896             :       public:
    6897             : 
    6898             :          typedef expression_node<T>* expression_ptr;
    6899             :          typedef std::pair<expression_ptr,bool> branch_t;
    6900             : 
    6901      405857 :          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
    6902      405857 :          {
    6903      405857 :             init_branches<2>(branch_, branch0, branch1);
    6904      405857 :             assert(valid());
    6905      405857 :          }
    6906             : 
    6907    63294408 :          inline T value() const exprtk_override
    6908             :          {
    6909    63294408 :             const T arg0 = branch_[0].first->value();
    6910    63294408 :             const T arg1 = branch_[1].first->value();
    6911   126588816 :             return Operation::process(arg0,arg1);
    6912             :          }
    6913             : 
    6914    11816857 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6915             :          {
    6916    11816857 :             return expression_node<T>::e_binary_ext;
    6917             :          }
    6918             : 
    6919             :          inline operator_type operation()
    6920             :          {
    6921             :             return Operation::operation();
    6922             :          }
    6923             : 
    6924           0 :          inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
    6925             :          {
    6926           0 :             assert(index < 2);
    6927           0 :             return branch_[index].first;
    6928             :          }
    6929             : 
    6930     2720300 :          inline bool valid() const exprtk_override
    6931             :          {
    6932             :             return
    6933     2720300 :                branch_[0].first && branch_[0].first->valid() &&
    6934     5440600 :                branch_[1].first && branch_[1].first->valid() ;
    6935             :          }
    6936             : 
    6937      405857 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    6938             :          {
    6939      405857 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
    6940      405857 :          }
    6941             : 
    6942     1210848 :          std::size_t node_depth() const exprtk_override
    6943             :          {
    6944     1210848 :             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
    6945             :          }
    6946             : 
    6947             :       protected:
    6948             : 
    6949             :          branch_t branch_[2];
    6950             :       };
    6951             : 
    6952             :       template <typename T>
    6953             :       class trinary_node : public expression_node<T>
    6954             :       {
    6955             :       public:
    6956             : 
    6957             :          typedef expression_node<T>* expression_ptr;
    6958             :          typedef std::pair<expression_ptr,bool> branch_t;
    6959             : 
    6960        1981 :          trinary_node(const operator_type& opr,
    6961             :                       expression_ptr branch0,
    6962             :                       expression_ptr branch1,
    6963             :                       expression_ptr branch2)
    6964        1981 :          : operation_(opr)
    6965             :          {
    6966        1981 :             init_branches<3>(branch_, branch0, branch1, branch2);
    6967        1981 :             assert(valid());
    6968        1981 :          }
    6969             : 
    6970    40000116 :          inline T value() const exprtk_override
    6971             :          {
    6972    40000116 :             const T arg0 = branch_[0].first->value();
    6973    40000116 :             const T arg1 = branch_[1].first->value();
    6974    40000116 :             const T arg2 = branch_[2].first->value();
    6975             : 
    6976    40000116 :             switch (operation_)
    6977             :             {
    6978          30 :                case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
    6979             : 
    6980    40000086 :                case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
    6981             : 
    6982           0 :                case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
    6983           0 :                                    return arg1;
    6984             :                                 else
    6985           0 :                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
    6986             : 
    6987           0 :                default        : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
    6988           0 :                                 return std::numeric_limits<T>::quiet_NaN();
    6989             :             }
    6990             :          }
    6991             : 
    6992        1705 :          inline typename expression_node<T>::node_type type() const exprtk_override
    6993             :          {
    6994        1705 :             return expression_node<T>::e_trinary;
    6995             :          }
    6996             : 
    6997        1992 :          inline bool valid() const exprtk_override
    6998             :          {
    6999             :             return
    7000        1992 :                branch_[0].first && branch_[0].first->valid() &&
    7001        1992 :                branch_[1].first && branch_[1].first->valid() &&
    7002        3984 :                branch_[2].first && branch_[2].first->valid() ;
    7003             :          }
    7004             : 
    7005        1981 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7006             :          {
    7007        1981 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
    7008        1981 :          }
    7009             : 
    7010        5473 :          std::size_t node_depth() const exprtk_override exprtk_final
    7011             :          {
    7012        5473 :             return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
    7013             :          }
    7014             : 
    7015             :       protected:
    7016             : 
    7017             :          operator_type operation_;
    7018             :          branch_t branch_[3];
    7019             :       };
    7020             : 
    7021             :       template <typename T>
    7022             :       class quaternary_node : public expression_node<T>
    7023             :       {
    7024             :       public:
    7025             : 
    7026             :          typedef expression_node<T>* expression_ptr;
    7027             :          typedef std::pair<expression_ptr,bool> branch_t;
    7028             : 
    7029         815 :          quaternary_node(const operator_type& opr,
    7030             :                          expression_ptr branch0,
    7031             :                          expression_ptr branch1,
    7032             :                          expression_ptr branch2,
    7033             :                          expression_ptr branch3)
    7034         815 :          : operation_(opr)
    7035             :          {
    7036         815 :             init_branches<4>(branch_, branch0, branch1, branch2, branch3);
    7037         815 :          }
    7038             : 
    7039           0 :          inline T value() const exprtk_override
    7040             :          {
    7041           0 :             return std::numeric_limits<T>::quiet_NaN();
    7042             :          }
    7043             : 
    7044        1630 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7045             :          {
    7046        1630 :             return expression_node<T>::e_quaternary;
    7047             :          }
    7048             : 
    7049         815 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7050             :          {
    7051         815 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
    7052         815 :          }
    7053             : 
    7054        1630 :          std::size_t node_depth() const exprtk_override exprtk_final
    7055             :          {
    7056        1630 :             return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
    7057             :          }
    7058             : 
    7059           0 :          inline bool valid() const exprtk_override
    7060             :          {
    7061             :             return
    7062           0 :                branch_[0].first && branch_[0].first->valid() &&
    7063           0 :                branch_[1].first && branch_[1].first->valid() &&
    7064           0 :                branch_[2].first && branch_[2].first->valid() &&
    7065           0 :                branch_[3].first && branch_[3].first->valid() ;
    7066             :          }
    7067             : 
    7068             :       protected:
    7069             : 
    7070             :          operator_type operation_;
    7071             :          branch_t branch_[4];
    7072             :       };
    7073             : 
    7074             :       template <typename T>
    7075             :       class conditional_node exprtk_final : public expression_node<T>
    7076             :       {
    7077             :       public:
    7078             : 
    7079             :          typedef expression_node<T>* expression_ptr;
    7080             :          typedef std::pair<expression_ptr,bool> branch_t;
    7081             : 
    7082        2837 :          conditional_node(expression_ptr condition,
    7083             :                           expression_ptr consequent,
    7084             :                           expression_ptr alternative)
    7085        2837 :          {
    7086        2837 :             construct_branch_pair(condition_  , condition  );
    7087        2837 :             construct_branch_pair(consequent_ , consequent );
    7088        2837 :             construct_branch_pair(alternative_, alternative);
    7089        2837 :             assert(valid());
    7090        2837 :          }
    7091             : 
    7092    57799351 :          inline T value() const exprtk_override
    7093             :          {
    7094    57799351 :             if (is_true(condition_))
    7095    21746054 :                return consequent_.first->value();
    7096             :             else
    7097    36053297 :                return alternative_.first->value();
    7098             :          }
    7099             : 
    7100       53982 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7101             :          {
    7102       53982 :             return expression_node<T>::e_conditional;
    7103             :          }
    7104             : 
    7105        9622 :          inline bool valid() const exprtk_override
    7106             :          {
    7107             :             return
    7108        9622 :                condition_  .first && condition_  .first->valid() &&
    7109        9622 :                consequent_ .first && consequent_ .first->valid() &&
    7110       19244 :                alternative_.first && alternative_.first->valid() ;
    7111             :          }
    7112             : 
    7113        2837 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7114             :          {
    7115        2837 :             expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
    7116        2837 :             expression_node<T>::ndb_t::collect(consequent_  , node_delete_list);
    7117        2837 :             expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
    7118        2837 :          }
    7119             : 
    7120        6949 :          std::size_t node_depth() const exprtk_override
    7121             :          {
    7122             :             return expression_node<T>::ndb_t::compute_node_depth
    7123        6949 :                (condition_, consequent_, alternative_);
    7124             :          }
    7125             : 
    7126             :       private:
    7127             : 
    7128             :          branch_t condition_;
    7129             :          branch_t consequent_;
    7130             :          branch_t alternative_;
    7131             :       };
    7132             : 
    7133             :       template <typename T>
    7134             :       class cons_conditional_node exprtk_final : public expression_node<T>
    7135             :       {
    7136             :       public:
    7137             : 
    7138             :          // Consequent only conditional statement node
    7139             :          typedef expression_node<T>* expression_ptr;
    7140             :          typedef std::pair<expression_ptr,bool> branch_t;
    7141             : 
    7142        1021 :          cons_conditional_node(expression_ptr condition,
    7143             :                                expression_ptr consequent)
    7144        1021 :          {
    7145        1021 :             construct_branch_pair(condition_ , condition );
    7146        1021 :             construct_branch_pair(consequent_, consequent);
    7147        1021 :             assert(valid());
    7148        1021 :          }
    7149             : 
    7150    10005970 :          inline T value() const exprtk_override
    7151             :          {
    7152    10005970 :             if (is_true(condition_))
    7153      666017 :                return consequent_.first->value();
    7154             :             else
    7155     9339953 :                return std::numeric_limits<T>::quiet_NaN();
    7156             :          }
    7157             : 
    7158       14449 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7159             :          {
    7160       14449 :             return expression_node<T>::e_conditional;
    7161             :          }
    7162             : 
    7163        4678 :          inline bool valid() const exprtk_override
    7164             :          {
    7165             :             return
    7166        4678 :                condition_ .first && condition_ .first->valid() &&
    7167        9356 :                consequent_.first && consequent_.first->valid() ;
    7168             :          }
    7169             : 
    7170        1021 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7171             :          {
    7172        1021 :             expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
    7173        1021 :             expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
    7174        1021 :          }
    7175             : 
    7176        2241 :          std::size_t node_depth() const exprtk_override
    7177             :          {
    7178             :             return expression_node<T>::ndb_t::
    7179        2241 :                compute_node_depth(condition_, consequent_);
    7180             :          }
    7181             : 
    7182             :       private:
    7183             : 
    7184             :          branch_t condition_;
    7185             :          branch_t consequent_;
    7186             :       };
    7187             : 
    7188             :       #ifndef exprtk_disable_break_continue
    7189             :       template <typename T>
    7190             :       class break_exception
    7191             :       {
    7192             :       public:
    7193             : 
    7194      372198 :          explicit break_exception(const T& v)
    7195      372198 :          : value(v)
    7196      372198 :          {}
    7197             : 
    7198             :          T value;
    7199             :       };
    7200             : 
    7201             :       class continue_exception {};
    7202             : 
    7203             :       template <typename T>
    7204             :       class break_node exprtk_final : public expression_node<T>
    7205             :       {
    7206             :       public:
    7207             : 
    7208             :          typedef expression_node<T>* expression_ptr;
    7209             :          typedef std::pair<expression_ptr,bool> branch_t;
    7210             : 
    7211         483 :          explicit break_node(expression_ptr ret = expression_ptr(0))
    7212         483 :          {
    7213         483 :             construct_branch_pair(return_, ret);
    7214         483 :          }
    7215             : 
    7216      372198 :          inline T value() const exprtk_override
    7217             :          {
    7218      372198 :             const T result = return_.first ?
    7219        1738 :                              return_.first->value() :
    7220      370460 :                              std::numeric_limits<T>::quiet_NaN();
    7221             : 
    7222      372198 :             throw break_exception<T>(result);
    7223             : 
    7224             :             #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    7225             :             return std::numeric_limits<T>::quiet_NaN();
    7226             :             #endif
    7227             :          }
    7228             : 
    7229        3418 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7230             :          {
    7231        3418 :             return expression_node<T>::e_break;
    7232             :          }
    7233             : 
    7234         483 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7235             :          {
    7236         483 :             expression_node<T>::ndb_t::collect(return_, node_delete_list);
    7237         483 :          }
    7238             : 
    7239        1528 :          std::size_t node_depth() const exprtk_override
    7240             :          {
    7241        1528 :             return expression_node<T>::ndb_t::compute_node_depth(return_);
    7242             :          }
    7243             : 
    7244             :       private:
    7245             : 
    7246             :          branch_t return_;
    7247             :       };
    7248             : 
    7249             :       template <typename T>
    7250             :       class continue_node exprtk_final : public expression_node<T>
    7251             :       {
    7252             :       public:
    7253             : 
    7254        1480 :          inline T value() const exprtk_override
    7255             :          {
    7256        1480 :             throw continue_exception();
    7257             :             #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
    7258             :             return std::numeric_limits<T>::quiet_NaN();
    7259             :             #endif
    7260             :          }
    7261             : 
    7262        2560 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7263             :          {
    7264        2560 :             return expression_node<T>::e_break;
    7265             :          }
    7266             :       };
    7267             :       #endif
    7268             : 
    7269             :       struct loop_runtime_checker
    7270             :       {
    7271           0 :          loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check,
    7272             :                               loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid)
    7273           0 :          : iteration_count_(0)
    7274           0 :          , loop_runtime_check_(loop_runtime_check)
    7275           0 :          , max_loop_iterations_(loop_runtime_check_->max_loop_iterations)
    7276           0 :          , loop_type_(lp_typ)
    7277             :          {
    7278           0 :             assert(loop_runtime_check_);
    7279           0 :          }
    7280             : 
    7281           0 :          inline void reset(const _uint64_t initial_value = 0) const
    7282             :          {
    7283           0 :             iteration_count_ = initial_value;
    7284           0 :          }
    7285             : 
    7286           0 :          inline bool check() const
    7287             :          {
    7288           0 :             if (
    7289           0 :                  (0 == loop_runtime_check_) ||
    7290           0 :                  ((++iteration_count_ <= max_loop_iterations_) && loop_runtime_check_->check())
    7291             :                )
    7292             :             {
    7293           0 :                return true;
    7294             :             }
    7295             : 
    7296             :             loop_runtime_check::violation_context ctxt;
    7297           0 :             ctxt.loop      = loop_type_;
    7298           0 :             ctxt.violation = loop_runtime_check::e_iteration_count;
    7299             : 
    7300           0 :             loop_runtime_check_->handle_runtime_violation(ctxt);
    7301             : 
    7302           0 :             return false;
    7303             :          }
    7304             : 
    7305             :          mutable _uint64_t iteration_count_;
    7306             :          mutable loop_runtime_check_ptr loop_runtime_check_;
    7307             :          const details::_uint64_t& max_loop_iterations_;
    7308             :          loop_runtime_check::loop_types loop_type_;
    7309             :       };
    7310             : 
    7311             :       template <typename T>
    7312             :       class while_loop_node : public expression_node<T>
    7313             :       {
    7314             :       public:
    7315             : 
    7316             :          typedef expression_node<T>* expression_ptr;
    7317             :          typedef std::pair<expression_ptr,bool> branch_t;
    7318             : 
    7319          22 :          while_loop_node(expression_ptr condition,
    7320             :                          expression_ptr loop_body)
    7321          22 :          {
    7322          22 :             construct_branch_pair(condition_, condition);
    7323          22 :             construct_branch_pair(loop_body_, loop_body);
    7324          22 :             assert(valid());
    7325          22 :          }
    7326             : 
    7327         176 :          inline T value() const exprtk_override
    7328             :          {
    7329         176 :             T result = T(0);
    7330             : 
    7331       26728 :             while (is_true(condition_))
    7332             :             {
    7333       26552 :                result = loop_body_.first->value();
    7334             :             }
    7335             : 
    7336         176 :             return result;
    7337             :          }
    7338             : 
    7339         231 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7340             :          {
    7341         231 :             return expression_node<T>::e_while;
    7342             :          }
    7343             : 
    7344          75 :          inline bool valid() const exprtk_override exprtk_final
    7345             :          {
    7346             :             return
    7347          75 :                condition_.first && condition_.first->valid() &&
    7348         150 :                loop_body_.first && loop_body_.first->valid() ;
    7349             :          }
    7350             : 
    7351          22 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7352             :          {
    7353          22 :             expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
    7354          22 :             expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
    7355          22 :          }
    7356             : 
    7357          45 :          std::size_t node_depth() const exprtk_override
    7358             :          {
    7359          45 :             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
    7360             :          }
    7361             : 
    7362             :       protected:
    7363             : 
    7364             :          branch_t condition_;
    7365             :          branch_t loop_body_;
    7366             :       };
    7367             : 
    7368             :       template <typename T>
    7369             :       class while_loop_rtc_node exprtk_final
    7370             :                                 : public while_loop_node<T>
    7371             :                                 , public loop_runtime_checker
    7372             :       {
    7373             :       public:
    7374             : 
    7375             :          typedef while_loop_node<T>  parent_t;
    7376             :          typedef expression_node<T>* expression_ptr;
    7377             : 
    7378           0 :          while_loop_rtc_node(expression_ptr condition,
    7379             :                              expression_ptr loop_body,
    7380             :                              loop_runtime_check_ptr loop_rt_chk)
    7381             :          : parent_t(condition, loop_body)
    7382           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
    7383             :          {
    7384           0 :             assert(parent_t::valid());
    7385           0 :          }
    7386             : 
    7387           0 :          inline T value() const exprtk_override
    7388             :          {
    7389             : 
    7390           0 :             T result = T(0);
    7391             : 
    7392           0 :             loop_runtime_checker::reset();
    7393             : 
    7394           0 :             while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7395             :             {
    7396           0 :                result = parent_t::loop_body_.first->value();
    7397             :             }
    7398             : 
    7399           0 :             return result;
    7400             :          }
    7401             :       };
    7402             : 
    7403             :       template <typename T>
    7404             :       class repeat_until_loop_node : public expression_node<T>
    7405             :       {
    7406             :       public:
    7407             : 
    7408             :          typedef expression_node<T>* expression_ptr;
    7409             :          typedef std::pair<expression_ptr,bool> branch_t;
    7410             : 
    7411           2 :          repeat_until_loop_node(expression_ptr condition,
    7412             :                                 expression_ptr loop_body)
    7413           2 :          {
    7414           2 :             construct_branch_pair(condition_, condition);
    7415           2 :             construct_branch_pair(loop_body_, loop_body);
    7416           2 :             assert(valid());
    7417           2 :          }
    7418             : 
    7419          30 :          inline T value() const exprtk_override
    7420             :          {
    7421          30 :             T result = T(0);
    7422             : 
    7423             :             do
    7424             :             {
    7425         465 :                result = loop_body_.first->value();
    7426             :             }
    7427         465 :             while (is_false(condition_.first));
    7428             : 
    7429          30 :             return result;
    7430             :          }
    7431             : 
    7432           9 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7433             :          {
    7434           9 :             return expression_node<T>::e_repeat;
    7435             :          }
    7436             : 
    7437           7 :          inline bool valid() const exprtk_override exprtk_final
    7438             :          {
    7439             :             return
    7440           7 :                condition_.first && condition_.first->valid() &&
    7441          14 :                loop_body_.first && loop_body_.first->valid() ;
    7442             :          }
    7443             : 
    7444           2 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7445             :          {
    7446           2 :             expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
    7447           2 :             expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
    7448           2 :          }
    7449             : 
    7450           4 :          std::size_t node_depth() const exprtk_override
    7451             :          {
    7452           4 :             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
    7453             :          }
    7454             : 
    7455             :       protected:
    7456             : 
    7457             :          branch_t condition_;
    7458             :          branch_t loop_body_;
    7459             :       };
    7460             : 
    7461             :       template <typename T>
    7462             :       class repeat_until_loop_rtc_node exprtk_final
    7463             :                                        : public repeat_until_loop_node<T>
    7464             :                                        , public loop_runtime_checker
    7465             :       {
    7466             :       public:
    7467             : 
    7468             :          typedef repeat_until_loop_node<T> parent_t;
    7469             :          typedef expression_node<T>*       expression_ptr;
    7470             : 
    7471           0 :          repeat_until_loop_rtc_node(expression_ptr condition,
    7472             :                                     expression_ptr loop_body,
    7473             :                                     loop_runtime_check_ptr loop_rt_chk)
    7474             :          : parent_t(condition, loop_body)
    7475           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
    7476             :          {
    7477           0 :             assert(parent_t::valid());
    7478           0 :          }
    7479             : 
    7480           0 :          inline T value() const exprtk_override
    7481             :          {
    7482           0 :             T result = T(0);
    7483             : 
    7484           0 :             loop_runtime_checker::reset(1);
    7485             : 
    7486             :             do
    7487             :             {
    7488           0 :                result = parent_t::loop_body_.first->value();
    7489             :             }
    7490           0 :             while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
    7491             : 
    7492           0 :             return result;
    7493             :          }
    7494             :       };
    7495             : 
    7496             :       template <typename T>
    7497             :       class for_loop_node : public expression_node<T>
    7498             :       {
    7499             :       public:
    7500             : 
    7501             :          typedef expression_node<T>* expression_ptr;
    7502             :          typedef std::pair<expression_ptr,bool> branch_t;
    7503             : 
    7504        2663 :          for_loop_node(expression_ptr initialiser,
    7505             :                        expression_ptr condition,
    7506             :                        expression_ptr incrementor,
    7507             :                        expression_ptr loop_body)
    7508        2663 :          {
    7509        2663 :             construct_branch_pair(initialiser_, initialiser);
    7510        2663 :             construct_branch_pair(condition_  , condition  );
    7511        2663 :             construct_branch_pair(incrementor_, incrementor);
    7512        2663 :             construct_branch_pair(loop_body_  , loop_body  );
    7513        2663 :             assert(valid());
    7514        2663 :          }
    7515             : 
    7516        6716 :          inline T value() const exprtk_override
    7517             :          {
    7518        6716 :             T result = T(0);
    7519             : 
    7520        6716 :             if (initialiser_.first)
    7521        6716 :                initialiser_.first->value();
    7522             : 
    7523        6716 :             if (incrementor_.first)
    7524             :             {
    7525    93358480 :                while (is_true(condition_))
    7526             :                {
    7527    93351891 :                   result = loop_body_.first->value();
    7528    93351884 :                   incrementor_.first->value();
    7529             :                }
    7530             :             }
    7531             :             else
    7532             :             {
    7533        1020 :                while (is_true(condition_))
    7534             :                {
    7535         900 :                   result = loop_body_.first->value();
    7536             :                }
    7537             :             }
    7538             : 
    7539        6709 :             return result;
    7540             :          }
    7541             : 
    7542       38421 :          inline typename expression_node<T>::node_type type() const exprtk_override
    7543             :          {
    7544       38421 :             return expression_node<T>::e_for;
    7545             :          }
    7546             : 
    7547        8845 :          inline bool valid() const exprtk_override exprtk_final
    7548             :          {
    7549        8845 :             return condition_.first && loop_body_.first;
    7550             :          }
    7551             : 
    7552        2663 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7553             :          {
    7554        2663 :             expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list);
    7555        2663 :             expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
    7556        2663 :             expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list);
    7557        2663 :             expression_node<T>::ndb_t::collect(loop_body_   , node_delete_list);
    7558        2663 :          }
    7559             : 
    7560        6644 :          std::size_t node_depth() const exprtk_override
    7561             :          {
    7562             :             return expression_node<T>::ndb_t::compute_node_depth
    7563        6644 :                (initialiser_, condition_, incrementor_, loop_body_);
    7564             :          }
    7565             : 
    7566             :       protected:
    7567             : 
    7568             :          branch_t initialiser_;
    7569             :          branch_t condition_  ;
    7570             :          branch_t incrementor_;
    7571             :          branch_t loop_body_  ;
    7572             :       };
    7573             : 
    7574             :       template <typename T>
    7575             :       class for_loop_rtc_node exprtk_final
    7576             :                               : public for_loop_node<T>
    7577             :                               , public loop_runtime_checker
    7578             :       {
    7579             :       public:
    7580             : 
    7581             :          typedef for_loop_node<T>    parent_t;
    7582             :          typedef expression_node<T>* expression_ptr;
    7583             : 
    7584           0 :          for_loop_rtc_node(expression_ptr initialiser,
    7585             :                            expression_ptr condition,
    7586             :                            expression_ptr incrementor,
    7587             :                            expression_ptr loop_body,
    7588             :                            loop_runtime_check_ptr loop_rt_chk)
    7589             :          : parent_t(initialiser, condition, incrementor, loop_body)
    7590           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
    7591             :          {
    7592           0 :             assert(parent_t::valid());
    7593           0 :          }
    7594             : 
    7595           0 :          inline T value() const exprtk_override
    7596             :          {
    7597           0 :             T result = T(0);
    7598             : 
    7599           0 :             loop_runtime_checker::reset();
    7600             : 
    7601           0 :             if (parent_t::initialiser_.first)
    7602           0 :                parent_t::initialiser_.first->value();
    7603             : 
    7604           0 :             if (parent_t::incrementor_.first)
    7605             :             {
    7606           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7607             :                {
    7608           0 :                   result = parent_t::loop_body_.first->value();
    7609           0 :                   parent_t::incrementor_.first->value();
    7610             :                }
    7611             :             }
    7612             :             else
    7613             :             {
    7614           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7615             :                {
    7616           0 :                   result = parent_t::loop_body_.first->value();
    7617             :                }
    7618             :             }
    7619             : 
    7620           0 :             return result;
    7621             :          }
    7622             :       };
    7623             : 
    7624             :       #ifndef exprtk_disable_break_continue
    7625             :       template <typename T>
    7626             :       class while_loop_bc_node : public while_loop_node<T>
    7627             :       {
    7628             :       public:
    7629             : 
    7630             :          typedef while_loop_node<T>  parent_t;
    7631             :          typedef expression_node<T>* expression_ptr;
    7632             : 
    7633          10 :          while_loop_bc_node(expression_ptr condition,
    7634             :                             expression_ptr loop_body)
    7635          10 :          : parent_t(condition, loop_body)
    7636             :          {
    7637          10 :             assert(parent_t::valid());
    7638          10 :          }
    7639             : 
    7640         100 :          inline T value() const exprtk_override
    7641             :          {
    7642         100 :             T result = T(0);
    7643             : 
    7644         650 :             while (is_true(parent_t::condition_))
    7645             :             {
    7646             :                try
    7647             :                {
    7648         650 :                   result = parent_t::loop_body_.first->value();
    7649             :                }
    7650         100 :                catch(const break_exception<T>& e)
    7651             :                {
    7652         100 :                   return e.value;
    7653             :                }
    7654           0 :                catch(const continue_exception&)
    7655             :                {}
    7656             :             }
    7657             : 
    7658           0 :             return result;
    7659             :          }
    7660             :       };
    7661             : 
    7662             :       template <typename T>
    7663             :       class while_loop_bc_rtc_node exprtk_final
    7664             :                                    : public while_loop_bc_node<T>
    7665             :                                    , public loop_runtime_checker
    7666             :       {
    7667             :       public:
    7668             : 
    7669             :          typedef while_loop_bc_node<T> parent_t;
    7670             :          typedef expression_node<T>*   expression_ptr;
    7671             : 
    7672           0 :          while_loop_bc_rtc_node(expression_ptr condition,
    7673             :                                 expression_ptr loop_body,
    7674             :                                 loop_runtime_check_ptr loop_rt_chk)
    7675             :          : parent_t(condition, loop_body)
    7676           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
    7677             :          {
    7678           0 :             assert(parent_t::valid());
    7679           0 :          }
    7680             : 
    7681           0 :          inline T value() const exprtk_override
    7682             :          {
    7683           0 :             T result = T(0);
    7684             : 
    7685           0 :             loop_runtime_checker::reset();
    7686             : 
    7687           0 :             while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7688             :             {
    7689             :                try
    7690             :                {
    7691           0 :                   result = parent_t::loop_body_.first->value();
    7692             :                }
    7693           0 :                catch(const break_exception<T>& e)
    7694             :                {
    7695           0 :                   return e.value;
    7696             :                }
    7697           0 :                catch(const continue_exception&)
    7698             :                {}
    7699             :             }
    7700             : 
    7701           0 :             return result;
    7702             :          }
    7703             :       };
    7704             : 
    7705             :       template <typename T>
    7706             :       class repeat_until_loop_bc_node : public repeat_until_loop_node<T>
    7707             :       {
    7708             :       public:
    7709             : 
    7710             :          typedef repeat_until_loop_node<T> parent_t;
    7711             :          typedef expression_node<T>*       expression_ptr;
    7712             : 
    7713           1 :          repeat_until_loop_bc_node(expression_ptr condition,
    7714             :                                    expression_ptr loop_body)
    7715           1 :          : parent_t(condition, loop_body)
    7716             :          {
    7717           1 :             assert(parent_t::valid());
    7718           1 :          }
    7719             : 
    7720          98 :          inline T value() const exprtk_override
    7721             :          {
    7722          98 :             T result = T(0);
    7723             : 
    7724             :             do
    7725             :             {
    7726             :                try
    7727             :                {
    7728         548 :                   result = parent_t::loop_body_.first->value();
    7729             :                }
    7730          98 :                catch(const break_exception<T>& e)
    7731             :                {
    7732          98 :                   return e.value;
    7733             :                }
    7734           0 :                catch(const continue_exception&)
    7735             :                {}
    7736             :             }
    7737         450 :             while (is_false(parent_t::condition_.first));
    7738             : 
    7739           0 :             return result;
    7740             :          }
    7741             :       };
    7742             : 
    7743             :       template <typename T>
    7744             :       class repeat_until_loop_bc_rtc_node exprtk_final
    7745             :                                           : public repeat_until_loop_bc_node<T>
    7746             :                                           , public loop_runtime_checker
    7747             :       {
    7748             :       public:
    7749             : 
    7750             :          typedef repeat_until_loop_bc_node<T> parent_t;
    7751             :          typedef expression_node<T>*          expression_ptr;
    7752             : 
    7753           0 :          repeat_until_loop_bc_rtc_node(expression_ptr condition,
    7754             :                                        expression_ptr loop_body,
    7755             :                                        loop_runtime_check_ptr loop_rt_chk)
    7756             :          : parent_t(condition, loop_body)
    7757           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
    7758             :          {
    7759           0 :             assert(parent_t::valid());
    7760           0 :          }
    7761             : 
    7762           0 :          inline T value() const exprtk_override
    7763             :          {
    7764           0 :             T result = T(0);
    7765             : 
    7766           0 :             loop_runtime_checker::reset();
    7767             : 
    7768             :             do
    7769             :             {
    7770             :                try
    7771             :                {
    7772           0 :                   result = parent_t::loop_body_.first->value();
    7773             :                }
    7774           0 :                catch(const break_exception<T>& e)
    7775             :                {
    7776           0 :                   return e.value;
    7777             :                }
    7778           0 :                catch(const continue_exception&)
    7779             :                {}
    7780             :             }
    7781           0 :             while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
    7782             : 
    7783           0 :             return result;
    7784             :          }
    7785             :       };
    7786             : 
    7787             :       template <typename T>
    7788             :       class for_loop_bc_node : public for_loop_node<T>
    7789             :       {
    7790             :       public:
    7791             : 
    7792             :          typedef for_loop_node<T>    parent_t;
    7793             :          typedef expression_node<T>* expression_ptr;
    7794             : 
    7795         612 :          for_loop_bc_node(expression_ptr initialiser,
    7796             :                           expression_ptr condition,
    7797             :                           expression_ptr incrementor,
    7798             :                           expression_ptr loop_body)
    7799         612 :          : parent_t(initialiser, condition, incrementor, loop_body)
    7800             :          {
    7801         612 :             assert(parent_t::valid());
    7802         612 :          }
    7803             : 
    7804      486072 :          inline T value() const exprtk_override
    7805             :          {
    7806      486072 :             T result = T(0);
    7807             : 
    7808      486072 :             if (parent_t::initialiser_.first)
    7809      486072 :                parent_t::initialiser_.first->value();
    7810             : 
    7811      486072 :             if (parent_t::incrementor_.first)
    7812             :             {
    7813     5131214 :                while (is_true(parent_t::condition_))
    7814             :                {
    7815             :                   try
    7816             :                   {
    7817     5017142 :                      result = parent_t::loop_body_.first->value();
    7818             :                   }
    7819      373480 :                   catch(const break_exception<T>& e)
    7820             :                   {
    7821      372000 :                      return e.value;
    7822             :                   }
    7823        1480 :                   catch(const continue_exception&)
    7824             :                   {}
    7825             : 
    7826     4645142 :                   parent_t::incrementor_.first->value();
    7827             :                }
    7828             :             }
    7829             :             else
    7830             :             {
    7831           0 :                while (is_true(parent_t::condition_))
    7832             :                {
    7833             :                   try
    7834             :                   {
    7835           0 :                      result = parent_t::loop_body_.first->value();
    7836             :                   }
    7837           0 :                   catch(const break_exception<T>& e)
    7838             :                   {
    7839           0 :                      return e.value;
    7840             :                   }
    7841           0 :                   catch(const continue_exception&)
    7842             :                   {}
    7843             :                }
    7844             :             }
    7845             : 
    7846      114072 :             return result;
    7847             :          }
    7848             :       };
    7849             : 
    7850             :       template <typename T>
    7851             :       class for_loop_bc_rtc_node exprtk_final
    7852             :                                  : public for_loop_bc_node<T>
    7853             :                                  , public loop_runtime_checker
    7854             :       {
    7855             :       public:
    7856             : 
    7857             :          typedef for_loop_bc_node<T> parent_t;
    7858             :          typedef expression_node<T>* expression_ptr;
    7859             : 
    7860           0 :          for_loop_bc_rtc_node(expression_ptr initialiser,
    7861             :                               expression_ptr condition,
    7862             :                               expression_ptr incrementor,
    7863             :                               expression_ptr loop_body,
    7864             :                               loop_runtime_check_ptr loop_rt_chk)
    7865             :          : parent_t(initialiser, condition, incrementor, loop_body)
    7866           0 :          , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
    7867             :          {
    7868           0 :             assert(parent_t::valid());
    7869           0 :          }
    7870             : 
    7871           0 :          inline T value() const exprtk_override
    7872             :          {
    7873           0 :             T result = T(0);
    7874             : 
    7875           0 :             loop_runtime_checker::reset();
    7876             : 
    7877           0 :             if (parent_t::initialiser_.first)
    7878           0 :                parent_t::initialiser_.first->value();
    7879             : 
    7880           0 :             if (parent_t::incrementor_.first)
    7881             :             {
    7882           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7883             :                {
    7884             :                   try
    7885             :                   {
    7886           0 :                      result = parent_t::loop_body_.first->value();
    7887             :                   }
    7888           0 :                   catch(const break_exception<T>& e)
    7889             :                   {
    7890           0 :                      return e.value;
    7891             :                   }
    7892           0 :                   catch(const continue_exception&)
    7893             :                   {}
    7894             : 
    7895           0 :                   parent_t::incrementor_.first->value();
    7896             :                }
    7897             :             }
    7898             :             else
    7899             :             {
    7900           0 :                while (is_true(parent_t::condition_) && loop_runtime_checker::check())
    7901             :                {
    7902             :                   try
    7903             :                   {
    7904           0 :                      result = parent_t::loop_body_.first->value();
    7905             :                   }
    7906           0 :                   catch(const break_exception<T>& e)
    7907             :                   {
    7908           0 :                      return e.value;
    7909             :                   }
    7910           0 :                   catch(const continue_exception&)
    7911             :                   {}
    7912             :                }
    7913             :             }
    7914             : 
    7915           0 :             return result;
    7916             :          }
    7917             :       };
    7918             :       #endif
    7919             : 
    7920             :       template <typename T>
    7921             :       class switch_node : public expression_node<T>
    7922             :       {
    7923             :       public:
    7924             : 
    7925             :          typedef expression_node<T>* expression_ptr;
    7926             :          typedef std::pair<expression_ptr,bool> branch_t;
    7927             : 
    7928             :          template <typename Allocator,
    7929             :                    template <typename, typename> class Sequence>
    7930        1005 :          explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
    7931        1005 :          {
    7932        1005 :             if (1 != (arg_list.size() & 1))
    7933           0 :                return;
    7934             : 
    7935        1005 :             arg_list_.resize(arg_list.size());
    7936             : 
    7937        4560 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
    7938             :             {
    7939        3555 :                if (arg_list[i] && arg_list[i]->valid())
    7940             :                {
    7941        3555 :                   construct_branch_pair(arg_list_[i], arg_list[i]);
    7942             :                }
    7943             :                else
    7944             :                {
    7945           0 :                   arg_list_.clear();
    7946           0 :                   return;
    7947             :                }
    7948             :             }
    7949             : 
    7950        1005 :             assert(valid());
    7951           0 :          }
    7952             : 
    7953           0 :          inline T value() const exprtk_override
    7954             :          {
    7955           0 :             const std::size_t upper_bound = (arg_list_.size() - 1);
    7956             : 
    7957           0 :             for (std::size_t i = 0; i < upper_bound; i += 2)
    7958             :             {
    7959           0 :                expression_ptr condition  = arg_list_[i    ].first;
    7960           0 :                expression_ptr consequent = arg_list_[i + 1].first;
    7961             : 
    7962           0 :                if (is_true(condition))
    7963             :                {
    7964           0 :                   return consequent->value();
    7965             :                }
    7966             :             }
    7967             : 
    7968           0 :             return arg_list_[upper_bound].first->value();
    7969             :          }
    7970             : 
    7971        4802 :          inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
    7972             :          {
    7973        4802 :             return expression_node<T>::e_switch;
    7974             :          }
    7975             : 
    7976        1282 :          inline bool valid() const exprtk_override
    7977             :          {
    7978        1282 :             return !arg_list_.empty();
    7979             :          }
    7980             : 
    7981        1005 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    7982             :          {
    7983        1005 :             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
    7984        1005 :          }
    7985             : 
    7986        2020 :          std::size_t node_depth() const exprtk_override exprtk_final
    7987             :          {
    7988        2020 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
    7989             :          }
    7990             : 
    7991             :       protected:
    7992             : 
    7993             :          std::vector<branch_t> arg_list_;
    7994             :       };
    7995             : 
    7996             :       template <typename T, typename Switch_N>
    7997             :       class switch_n_node exprtk_final : public switch_node<T>
    7998             :       {
    7999             :       public:
    8000             : 
    8001             :          typedef expression_node<T>* expression_ptr;
    8002             : 
    8003             :          template <typename Allocator,
    8004             :                    template <typename, typename> class Sequence>
    8005        1005 :          explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
    8006        1005 :          : switch_node<T>(arg_list)
    8007        1005 :          {}
    8008             : 
    8009    11459417 :          inline T value() const exprtk_override
    8010             :          {
    8011    11459417 :             return Switch_N::process(switch_node<T>::arg_list_);
    8012             :          }
    8013             :       };
    8014             : 
    8015             :       template <typename T>
    8016             :       class multi_switch_node exprtk_final : public expression_node<T>
    8017             :       {
    8018             :       public:
    8019             : 
    8020             :          typedef expression_node<T>* expression_ptr;
    8021             :          typedef std::pair<expression_ptr,bool> branch_t;
    8022             : 
    8023             :          template <typename Allocator,
    8024             :                    template <typename, typename> class Sequence>
    8025         180 :          explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
    8026         180 :          {
    8027         180 :             if (0 != (arg_list.size() & 1))
    8028           0 :                return;
    8029             : 
    8030         180 :             arg_list_.resize(arg_list.size());
    8031             : 
    8032         900 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
    8033             :             {
    8034         720 :                if (arg_list[i] && arg_list[i]->valid())
    8035             :                {
    8036         720 :                   construct_branch_pair(arg_list_[i], arg_list[i]);
    8037             :                }
    8038             :                else
    8039             :                {
    8040           0 :                   arg_list_.clear();
    8041           0 :                   return;
    8042             :                }
    8043             :             }
    8044             : 
    8045         180 :             assert(valid());
    8046           0 :          }
    8047             : 
    8048         180 :          inline T value() const exprtk_override
    8049             :          {
    8050         180 :             const std::size_t upper_bound = (arg_list_.size() - 1);
    8051             : 
    8052         180 :             T result = T(0);
    8053             : 
    8054         540 :             for (std::size_t i = 0; i < upper_bound; i += 2)
    8055             :             {
    8056         360 :                expression_ptr condition  = arg_list_[i    ].first;
    8057         360 :                expression_ptr consequent = arg_list_[i + 1].first;
    8058             : 
    8059         360 :                if (is_true(condition))
    8060             :                {
    8061         120 :                   result = consequent->value();
    8062             :                }
    8063             :             }
    8064             : 
    8065         180 :             return result;
    8066             :          }
    8067             : 
    8068         900 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8069             :          {
    8070         900 :             return expression_node<T>::e_mswitch;
    8071             :          }
    8072             : 
    8073         180 :          inline bool valid() const exprtk_override
    8074             :          {
    8075         180 :             return !arg_list_.empty() && (0 == (arg_list_.size() % 2));
    8076             :          }
    8077             : 
    8078         180 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8079             :          {
    8080         180 :             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
    8081         180 :          }
    8082             : 
    8083         360 :          std::size_t node_depth() const exprtk_override exprtk_final
    8084             :          {
    8085         360 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
    8086             :          }
    8087             : 
    8088             :       private:
    8089             : 
    8090             :          std::vector<branch_t> arg_list_;
    8091             :       };
    8092             : 
    8093             :       template <typename T>
    8094             :       class ivariable
    8095             :       {
    8096             :       public:
    8097             : 
    8098      486296 :          virtual ~ivariable()
    8099      486296 :          {}
    8100             : 
    8101             :          virtual T& ref() = 0;
    8102             :          virtual const T& ref() const = 0;
    8103             :       };
    8104             : 
    8105             :       template <typename T>
    8106             :       class variable_node exprtk_final
    8107             :                           : public expression_node<T>
    8108             :                           , public ivariable      <T>
    8109             :       {
    8110             :       public:
    8111             : 
    8112             :          static T null_value;
    8113             : 
    8114             :          explicit variable_node()
    8115             :          : value_(&null_value)
    8116             :          {}
    8117             : 
    8118      479678 :          explicit variable_node(T& v)
    8119      479678 :          : value_(&v)
    8120      479678 :          {}
    8121             : 
    8122             :          inline bool operator <(const variable_node<T>& v) const
    8123             :          {
    8124             :             return this < (&v);
    8125             :          }
    8126             : 
    8127   127757228 :          inline T value() const exprtk_override
    8128             :          {
    8129   127757228 :             return (*value_);
    8130             :          }
    8131             : 
    8132   199196244 :          inline T& ref() exprtk_override
    8133             :          {
    8134   199196244 :             return (*value_);
    8135             :          }
    8136             : 
    8137         960 :          inline const T& ref() const exprtk_override
    8138             :          {
    8139         960 :             return (*value_);
    8140             :          }
    8141             : 
    8142    28660836 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8143             :          {
    8144    28660836 :             return expression_node<T>::e_variable;
    8145             :          }
    8146             : 
    8147             :       private:
    8148             : 
    8149             :          T* value_;
    8150             :       };
    8151             : 
    8152             :       template <typename T>
    8153             :       T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
    8154             : 
    8155             :       template <typename T>
    8156             :       struct range_pack
    8157             :       {
    8158             :          typedef expression_node<T>*           expression_node_ptr;
    8159             :          typedef std::pair<std::size_t,std::size_t> cached_range_t;
    8160             : 
    8161      228368 :          range_pack()
    8162      228368 :          : n0_e (std::make_pair(false,expression_node_ptr(0)))
    8163      228368 :          , n1_e (std::make_pair(false,expression_node_ptr(0)))
    8164      228368 :          , n0_c (std::make_pair(false,0))
    8165      228368 :          , n1_c (std::make_pair(false,0))
    8166      228368 :          , cache(std::make_pair(0,0))
    8167      228368 :          {}
    8168             : 
    8169       77292 :          void clear()
    8170             :          {
    8171       77292 :             n0_e  = std::make_pair(false,expression_node_ptr(0));
    8172       77292 :             n1_e  = std::make_pair(false,expression_node_ptr(0));
    8173       77292 :             n0_c  = std::make_pair(false,0);
    8174       77292 :             n1_c  = std::make_pair(false,0);
    8175       77292 :             cache = std::make_pair(0,0);
    8176       77292 :          }
    8177             : 
    8178       45496 :          void free()
    8179             :          {
    8180       45496 :             if (n0_e.first && n0_e.second)
    8181             :             {
    8182        5206 :                n0_e.first = false;
    8183             : 
    8184        5206 :                if (
    8185        6509 :                     !is_variable_node(n0_e.second) &&
    8186        1303 :                     !is_string_node  (n0_e.second)
    8187             :                   )
    8188             :                {
    8189        1303 :                   destroy_node(n0_e.second);
    8190             :                }
    8191             :             }
    8192             : 
    8193       45496 :             if (n1_e.first && n1_e.second)
    8194             :             {
    8195        6856 :                n1_e.first = false;
    8196             : 
    8197        6856 :                if (
    8198       11709 :                     !is_variable_node(n1_e.second) &&
    8199        4853 :                     !is_string_node  (n1_e.second)
    8200             :                   )
    8201             :                {
    8202        4853 :                   destroy_node(n1_e.second);
    8203             :                }
    8204             :             }
    8205       45496 :          }
    8206             : 
    8207       32050 :          bool const_range() const
    8208             :          {
    8209       53992 :            return ( n0_c.first &&  n1_c.first) &&
    8210       53992 :                   (!n0_e.first && !n1_e.first);
    8211             :          }
    8212             : 
    8213             :          bool var_range() const
    8214             :          {
    8215             :            return ( n0_e.first &&  n1_e.first) &&
    8216             :                   (!n0_c.first && !n1_c.first);
    8217             :          }
    8218             : 
    8219       99038 :          bool operator() (std::size_t& r0, std::size_t& r1,
    8220             :                           const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
    8221             :          {
    8222       99038 :             if (n0_c.first)
    8223       93838 :                r0 = n0_c.second;
    8224        5200 :             else if (n0_e.first)
    8225             :             {
    8226        5200 :                r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value()));
    8227             :             }
    8228             :             else
    8229           0 :                return false;
    8230             : 
    8231       99038 :             if (n1_c.first)
    8232       92188 :                r1 = n1_c.second;
    8233        6850 :             else if (n1_e.first)
    8234             :             {
    8235        6850 :                r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value()));
    8236             :             }
    8237             :             else
    8238           0 :                return false;
    8239             : 
    8240       99038 :             if (
    8241      176388 :                  (std::numeric_limits<std::size_t>::max() != size) &&
    8242       77350 :                  (std::numeric_limits<std::size_t>::max() == r1  )
    8243             :                )
    8244             :             {
    8245        9650 :                r1 = size;
    8246             :             }
    8247             : 
    8248       99038 :             cache.first  = r0;
    8249       99038 :             cache.second = r1;
    8250             : 
    8251             :             #ifndef exprtk_enable_range_runtime_checks
    8252       99038 :             return (r0 <= r1);
    8253             :             #else
    8254             :             return range_runtime_check(r0, r1, size);
    8255             :             #endif
    8256             :          }
    8257             : 
    8258           0 :          inline std::size_t const_size() const
    8259             :          {
    8260           0 :             return (n1_c.second - n0_c.second);
    8261             :          }
    8262             : 
    8263        3250 :          inline std::size_t cache_size() const
    8264             :          {
    8265        3250 :             return (cache.second - cache.first);
    8266             :          }
    8267             : 
    8268             :          std::pair<bool,expression_node_ptr> n0_e;
    8269             :          std::pair<bool,expression_node_ptr> n1_e;
    8270             :          std::pair<bool,std::size_t        > n0_c;
    8271             :          std::pair<bool,std::size_t        > n1_c;
    8272             :          mutable cached_range_t             cache;
    8273             : 
    8274             :          #ifdef exprtk_enable_range_runtime_checks
    8275             :          bool range_runtime_check(const std::size_t r0,
    8276             :                                   const std::size_t r1,
    8277             :                                   const std::size_t size) const
    8278             :          {
    8279             :             if (r0 > size)
    8280             :             {
    8281             :                throw std::runtime_error("range error: (r0 < 0) || (r0 > size)");
    8282             :                #ifndef _MSC_VER
    8283             :                return false;
    8284             :                #endif
    8285             :             }
    8286             : 
    8287             :             if (r1 > size)
    8288             :             {
    8289             :                throw std::runtime_error("range error: (r1 < 0) || (r1 > size)");
    8290             :                #ifndef _MSC_VER
    8291             :                return false;
    8292             :                #endif
    8293             :             }
    8294             : 
    8295             :             return (r0 <= r1);
    8296             :          }
    8297             :          #endif
    8298             :       };
    8299             : 
    8300             :       template <typename T>
    8301             :       class string_base_node;
    8302             : 
    8303             :       template <typename T>
    8304             :       struct range_data_type
    8305             :       {
    8306             :          typedef range_pack<T> range_t;
    8307             :          typedef string_base_node<T>* strbase_ptr_t;
    8308             : 
    8309        2049 :          range_data_type()
    8310        2049 :          : range(0)
    8311        2049 :          , data (0)
    8312        2049 :          , size (0)
    8313        2049 :          , type_size(0)
    8314        2049 :          , str_node (0)
    8315        2049 :          {}
    8316             : 
    8317             :          range_t*      range;
    8318             :          void*         data;
    8319             :          std::size_t   size;
    8320             :          std::size_t   type_size;
    8321             :          strbase_ptr_t str_node;
    8322             :       };
    8323             : 
    8324             :       template <typename T> class vector_node;
    8325             : 
    8326             :       template <typename T>
    8327             :       class vector_interface
    8328             :       {
    8329             :       public:
    8330             : 
    8331             :          typedef vector_node<T>*   vector_node_ptr;
    8332             :          typedef vec_data_store<T> vds_t;
    8333             : 
    8334       78580 :          virtual ~vector_interface()
    8335       78580 :          {}
    8336             : 
    8337             :          virtual std::size_t size     () const = 0;
    8338             : 
    8339             :          virtual std::size_t base_size() const = 0;
    8340             : 
    8341             :          virtual vector_node_ptr vec  () const = 0;
    8342             : 
    8343             :          virtual vector_node_ptr vec  ()       = 0;
    8344             : 
    8345             :          virtual       vds_t& vds     ()       = 0;
    8346             : 
    8347             :          virtual const vds_t& vds     () const = 0;
    8348             : 
    8349         657 :          virtual bool side_effect     () const { return false; }
    8350             :       };
    8351             : 
    8352             :       template <typename T>
    8353             :       class vector_node exprtk_final
    8354             :                         : public expression_node <T>
    8355             :                         , public vector_interface<T>
    8356             :       {
    8357             :       public:
    8358             : 
    8359             :          typedef expression_node<T>* expression_ptr;
    8360             :          typedef vector_holder<T>    vector_holder_t;
    8361             :          typedef vector_node<T>*     vector_node_ptr;
    8362             :          typedef vec_data_store<T>   vds_t;
    8363             : 
    8364       41607 :          explicit vector_node(vector_holder_t* vh)
    8365       41607 :          : vector_holder_(vh)
    8366       41607 :          , vds_((*vector_holder_).size(),(*vector_holder_)[0])
    8367             :          {
    8368       41607 :             vector_holder_->set_ref(&vds_.ref());
    8369       41607 :          }
    8370             : 
    8371       15929 :          vector_node(const vds_t& vds, vector_holder_t* vh)
    8372       15929 :          : vector_holder_(vh)
    8373       15929 :          , vds_(vds)
    8374       15929 :          {}
    8375             : 
    8376      115072 :         ~vector_node()
    8377             :          {
    8378       57536 :             assert(valid());
    8379       57536 :             vector_holder_->remove_ref(&vds_.ref());
    8380      172608 :          }
    8381             : 
    8382    32893529 :          inline T value() const exprtk_override
    8383             :          {
    8384    32893529 :             return vds().data()[0];
    8385             :          }
    8386             : 
    8387           0 :          vector_node_ptr vec() const exprtk_override
    8388             :          {
    8389           0 :             return const_cast<vector_node_ptr>(this);
    8390             :          }
    8391             : 
    8392        3992 :          vector_node_ptr vec() exprtk_override
    8393             :          {
    8394        3992 :             return this;
    8395             :          }
    8396             : 
    8397      380834 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8398             :          {
    8399      380834 :             return expression_node<T>::e_vector;
    8400             :          }
    8401             : 
    8402      160519 :          inline bool valid() const exprtk_override
    8403             :          {
    8404      160519 :             return vector_holder_;
    8405             :          }
    8406             : 
    8407       22211 :          std::size_t size() const exprtk_override
    8408             :          {
    8409       22211 :             return vec_holder().size();
    8410             :          }
    8411             : 
    8412        2772 :          std::size_t base_size() const exprtk_override
    8413             :          {
    8414        2772 :             return vec_holder().base_size();
    8415             :          }
    8416             : 
    8417       47305 :          vds_t& vds() exprtk_override
    8418             :          {
    8419       47305 :             return vds_;
    8420             :          }
    8421             : 
    8422    32893529 :          const vds_t& vds() const exprtk_override
    8423             :          {
    8424    32893529 :             return vds_;
    8425             :          }
    8426             : 
    8427      203931 :          inline vector_holder_t& vec_holder()
    8428             :          {
    8429      203931 :             return (*vector_holder_);
    8430             :          }
    8431             : 
    8432       24983 :          inline vector_holder_t& vec_holder() const
    8433             :          {
    8434       24983 :             return (*vector_holder_);
    8435             :          }
    8436             : 
    8437             :       private:
    8438             : 
    8439             :          vector_holder_t* vector_holder_;
    8440             :          vds_t                      vds_;
    8441             :       };
    8442             : 
    8443             :       template <typename T>
    8444             :       class vector_size_node exprtk_final
    8445             :                         : public expression_node <T>
    8446             :       {
    8447             :       public:
    8448             : 
    8449             :          typedef expression_node<T>* expression_ptr;
    8450             :          typedef vector_holder<T>    vector_holder_t;
    8451             : 
    8452         188 :          explicit vector_size_node(vector_holder_t* vh)
    8453         188 :          : vector_holder_(vh)
    8454         188 :          {}
    8455             : 
    8456         376 :         ~vector_size_node()
    8457             :          {
    8458         188 :             assert(valid());
    8459         564 :          }
    8460             : 
    8461        1022 :          inline T value() const exprtk_override
    8462             :          {
    8463        1022 :             assert(vector_holder_);
    8464        1022 :             return static_cast<T>(vector_holder_->size());
    8465             :          }
    8466             : 
    8467        6781 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8468             :          {
    8469        6781 :             return expression_node<T>::e_vecsize;
    8470             :          }
    8471             : 
    8472         807 :          inline bool valid() const exprtk_override
    8473             :          {
    8474         807 :             return vector_holder_ && vector_holder_->size();
    8475             :          }
    8476             : 
    8477           0 :          inline vector_holder_t* vec_holder()
    8478             :          {
    8479           0 :             return vector_holder_;
    8480             :          }
    8481             : 
    8482             :       private:
    8483             : 
    8484             :          vector_holder_t* vector_holder_;
    8485             :       };
    8486             : 
    8487             :       template <typename T>
    8488             :       class vector_elem_node exprtk_final
    8489             :                              : public expression_node<T>
    8490             :                              , public ivariable      <T>
    8491             :       {
    8492             :       public:
    8493             : 
    8494             :          typedef expression_node<T>*            expression_ptr;
    8495             :          typedef vector_holder<T>               vector_holder_t;
    8496             :          typedef vector_holder_t*               vector_holder_ptr;
    8497             :          typedef std::pair<expression_ptr,bool> branch_t;
    8498             : 
    8499        3521 :          vector_elem_node(expression_ptr vec_node,
    8500             :                           expression_ptr index,
    8501             :                           vector_holder_ptr vec_holder)
    8502        3521 :          : vector_holder_(vec_holder)
    8503        3521 :          , vector_base_((*vec_holder)[0])
    8504             :          {
    8505        3521 :             construct_branch_pair(vector_node_, vec_node);
    8506        3521 :             construct_branch_pair(index_      , index   );
    8507        3521 :             assert(valid());
    8508        3521 :          }
    8509             : 
    8510    10007733 :          inline T value() const exprtk_override
    8511             :          {
    8512    10007733 :             return *access_vector();
    8513             :          }
    8514             : 
    8515    22853974 :          inline T& ref() exprtk_override
    8516             :          {
    8517    22853974 :             return *access_vector();
    8518             :          }
    8519             : 
    8520           0 :          inline const T& ref() const exprtk_override
    8521             :          {
    8522           0 :             return *access_vector();
    8523             :          }
    8524             : 
    8525       71014 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8526             :          {
    8527       71014 :             return expression_node<T>::e_vecelem;
    8528             :          }
    8529             : 
    8530       17417 :          inline bool valid() const exprtk_override
    8531             :          {
    8532             :             return
    8533       34834 :                vector_holder_        &&
    8534       17417 :                index_.first          &&
    8535       17417 :                vector_node_.first    &&
    8536       52251 :                index_.first->valid() &&
    8537       34834 :                vector_node_.first->valid();
    8538             :          }
    8539             : 
    8540           0 :          inline vector_holder_t& vec_holder()
    8541             :          {
    8542           0 :             return (*vector_holder_);
    8543             :          }
    8544             : 
    8545        3521 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8546             :          {
    8547        3521 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8548        3521 :             expression_node<T>::ndb_t::collect(index_      , node_delete_list);
    8549        3521 :          }
    8550             : 
    8551        7846 :          std::size_t node_depth() const exprtk_override
    8552             :          {
    8553             :             return expression_node<T>::ndb_t::compute_node_depth
    8554        7846 :                (vector_node_, index_);
    8555             :          }
    8556             : 
    8557             :       private:
    8558             : 
    8559    32861707 :          inline T* access_vector() const
    8560             :          {
    8561    32861707 :             vector_node_.first->value();
    8562    32861707 :             return (vector_base_ + details::numeric::to_uint64(index_.first->value()));
    8563             :          }
    8564             : 
    8565             :          vector_holder_ptr vector_holder_;
    8566             :          T* vector_base_;
    8567             :          branch_t vector_node_;
    8568             :          branch_t index_;
    8569             :       };
    8570             : 
    8571             :       template <typename T>
    8572             :       class vector_celem_node exprtk_final
    8573             :                               : public expression_node<T>
    8574             :                               , public ivariable      <T>
    8575             :       {
    8576             :       public:
    8577             : 
    8578             :          typedef expression_node<T>*            expression_ptr;
    8579             :          typedef vector_holder<T>               vector_holder_t;
    8580             :          typedef vector_holder_t*               vector_holder_ptr;
    8581             :          typedef std::pair<expression_ptr,bool> branch_t;
    8582             : 
    8583          95 :          vector_celem_node(expression_ptr vec_node,
    8584             :                            const std::size_t index,
    8585             :                            vector_holder_ptr vec_holder)
    8586          95 :          : index_(index)
    8587          95 :          , vector_holder_(vec_holder)
    8588          95 :          , vector_base_((*vec_holder)[0])
    8589             :          {
    8590          95 :             construct_branch_pair(vector_node_, vec_node);
    8591          95 :             assert(valid());
    8592          95 :          }
    8593             : 
    8594          95 :          inline T value() const exprtk_override
    8595             :          {
    8596          95 :             return *access_vector();
    8597             :          }
    8598             : 
    8599           0 :          inline T& ref() exprtk_override
    8600             :          {
    8601           0 :             return *access_vector();
    8602             :          }
    8603             : 
    8604           0 :          inline const T& ref() const exprtk_override
    8605             :          {
    8606           0 :             return *access_vector();
    8607             :          }
    8608             : 
    8609        2945 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8610             :          {
    8611        2945 :             return expression_node<T>::e_veccelem;
    8612             :          }
    8613             : 
    8614         380 :          inline bool valid() const exprtk_override
    8615             :          {
    8616             :             return
    8617         760 :                vector_holder_     &&
    8618         760 :                vector_node_.first &&
    8619         760 :                vector_node_.first->valid();
    8620             :          }
    8621             : 
    8622             :          inline vector_holder_t& vec_holder()
    8623             :          {
    8624             :             return (*vector_holder_);
    8625             :          }
    8626             : 
    8627          95 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8628             :          {
    8629          95 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8630          95 :          }
    8631             : 
    8632         190 :          std::size_t node_depth() const exprtk_override
    8633             :          {
    8634         190 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    8635             :          }
    8636             : 
    8637             :       private:
    8638             : 
    8639          95 :          inline T* access_vector() const
    8640             :          {
    8641          95 :             vector_node_.first->value();
    8642          95 :             return (vector_base_ + index_);
    8643             :          }
    8644             : 
    8645             :          const std::size_t index_;
    8646             :          vector_holder_ptr vector_holder_;
    8647             :          T* vector_base_;
    8648             :          branch_t vector_node_;
    8649             :       };
    8650             : 
    8651             :       template <typename T>
    8652             :       class vector_elem_rtc_node exprtk_final
    8653             :                                  : public expression_node<T>
    8654             :                                  , public ivariable      <T>
    8655             :       {
    8656             :       public:
    8657             : 
    8658             :          typedef expression_node<T>*            expression_ptr;
    8659             :          typedef vector_holder<T>               vector_holder_t;
    8660             :          typedef vector_holder_t*               vector_holder_ptr;
    8661             :          typedef std::pair<expression_ptr,bool> branch_t;
    8662             : 
    8663          92 :          vector_elem_rtc_node(expression_ptr vec_node,
    8664             :                               expression_ptr index,
    8665             :                               vector_holder_ptr vec_holder,
    8666             :                               vector_access_runtime_check_ptr vec_rt_chk)
    8667          92 :          : vector_holder_(vec_holder)
    8668           0 :          , vector_base_((*vec_holder)[0])
    8669          92 :          , vec_rt_chk_(vec_rt_chk)
    8670          92 :          , max_vector_index_(vector_holder_->size() - 1)
    8671             :          {
    8672          92 :             construct_branch_pair(vector_node_, vec_node);
    8673          92 :             construct_branch_pair(index_      , index   );
    8674          92 :             assert(valid());
    8675          92 :          }
    8676             : 
    8677         243 :          inline T value() const exprtk_override
    8678             :          {
    8679         243 :             return *access_vector();
    8680             :          }
    8681             : 
    8682         335 :          inline T& ref() exprtk_override
    8683             :          {
    8684         335 :             return *access_vector();
    8685             :          }
    8686             : 
    8687           0 :          inline const T& ref() const exprtk_override
    8688             :          {
    8689           0 :             return *access_vector();
    8690             :          }
    8691             : 
    8692        1416 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8693             :          {
    8694        1416 :             return expression_node<T>::e_vecelemrtc;
    8695             :          }
    8696             : 
    8697         446 :          inline bool valid() const exprtk_override
    8698             :          {
    8699             :             return
    8700         892 :                vector_holder_        &&
    8701         446 :                index_.first          &&
    8702         446 :                vector_node_.first    &&
    8703        1338 :                index_.first->valid() &&
    8704         892 :                vector_node_.first->valid();
    8705             :          }
    8706             : 
    8707             :          inline vector_holder_t& vec_holder()
    8708             :          {
    8709             :             return (*vector_holder_);
    8710             :          }
    8711             : 
    8712          92 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8713             :          {
    8714          92 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8715          92 :             expression_node<T>::ndb_t::collect(index_,       node_delete_list);
    8716          92 :          }
    8717             : 
    8718         226 :          std::size_t node_depth() const exprtk_override
    8719             :          {
    8720             :             return expression_node<T>::ndb_t::compute_node_depth
    8721         226 :                (vector_node_, index_);
    8722             :          }
    8723             : 
    8724             :       private:
    8725             : 
    8726         578 :          inline T* access_vector() const
    8727             :          {
    8728         578 :             const _uint64_t index = details::numeric::to_uint64(index_.first->value());
    8729         578 :             vector_node_.first->value();
    8730             : 
    8731         578 :             if (index <= max_vector_index_)
    8732             :             {
    8733         156 :                return (vector_holder_->data() + index);
    8734             :             }
    8735             : 
    8736         422 :             assert(vec_rt_chk_);
    8737             : 
    8738             :             vector_access_runtime_check::violation_context context;
    8739         422 :             context.base_ptr   = reinterpret_cast<void*>(vector_base_);
    8740         422 :             context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
    8741         422 :             context.access_ptr = reinterpret_cast<void*>(vector_base_ + index);
    8742         422 :             context.type_size  = sizeof(T);
    8743             : 
    8744         422 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    8745             :                reinterpret_cast<T*>(context.access_ptr) :
    8746         422 :                vector_base_ ;
    8747             :          }
    8748             : 
    8749             :          vector_holder_ptr vector_holder_;
    8750             :          T*                vector_base_;
    8751             :          branch_t          vector_node_;
    8752             :          branch_t          index_;
    8753             :          vector_access_runtime_check_ptr vec_rt_chk_;
    8754             :          const std::size_t max_vector_index_;
    8755             :       };
    8756             : 
    8757             :       template <typename T>
    8758             :       class vector_celem_rtc_node exprtk_final
    8759             :                                  : public expression_node<T>
    8760             :                                  , public ivariable      <T>
    8761             :       {
    8762             :       public:
    8763             : 
    8764             :          typedef expression_node<T>*            expression_ptr;
    8765             :          typedef vector_holder<T>               vector_holder_t;
    8766             :          typedef vector_holder_t*               vector_holder_ptr;
    8767             :          typedef std::pair<expression_ptr,bool> branch_t;
    8768             : 
    8769           0 :          vector_celem_rtc_node(expression_ptr vec_node,
    8770             :                                const std::size_t index,
    8771             :                                vector_holder_ptr vec_holder,
    8772             :                                vector_access_runtime_check_ptr vec_rt_chk)
    8773           0 :          : index_(index)
    8774           0 :          , max_vector_index_(vec_holder->size() - 1)
    8775           0 :          , vector_holder_(vec_holder)
    8776           0 :          , vector_base_((*vec_holder)[0])
    8777           0 :          , vec_rt_chk_(vec_rt_chk)
    8778             :          {
    8779           0 :             construct_branch_pair(vector_node_, vec_node);
    8780           0 :             assert(valid());
    8781           0 :          }
    8782             : 
    8783           0 :          inline T value() const exprtk_override
    8784             :          {
    8785           0 :             return *access_vector();
    8786             :          }
    8787             : 
    8788           0 :          inline T& ref() exprtk_override
    8789             :          {
    8790           0 :             return *access_vector();
    8791             :          }
    8792             : 
    8793           0 :          inline const T& ref() const exprtk_override
    8794             :          {
    8795           0 :             return *access_vector();
    8796             :          }
    8797             : 
    8798           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8799             :          {
    8800           0 :             return expression_node<T>::e_veccelemrtc;
    8801             :          }
    8802             : 
    8803           0 :          inline bool valid() const exprtk_override
    8804             :          {
    8805             :             return
    8806           0 :                vector_holder_     &&
    8807           0 :                vector_node_.first &&
    8808           0 :                vector_node_.first->valid();
    8809             :          }
    8810             : 
    8811             :          inline vector_holder_t& vec_holder()
    8812             :          {
    8813             :             return (*vector_holder_);
    8814             :          }
    8815             : 
    8816           0 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8817             :          {
    8818           0 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8819           0 :          }
    8820             : 
    8821           0 :          std::size_t node_depth() const exprtk_override
    8822             :          {
    8823           0 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    8824             :          }
    8825             : 
    8826             :       private:
    8827             : 
    8828           0 :          inline T* access_vector() const
    8829             :          {
    8830           0 :             vector_node_.first->value();
    8831             : 
    8832           0 :             if (index_ <= max_vector_index_)
    8833             :             {
    8834           0 :                return (vector_holder_->data() + index_);
    8835             :             }
    8836             : 
    8837           0 :             assert(vec_rt_chk_);
    8838             : 
    8839             :             vector_access_runtime_check::violation_context context;
    8840           0 :             context.base_ptr   = reinterpret_cast<void*>(vector_base_);
    8841           0 :             context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
    8842           0 :             context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
    8843           0 :             context.type_size  = sizeof(T);
    8844             : 
    8845           0 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    8846             :                reinterpret_cast<T*>(context.access_ptr) :
    8847           0 :                vector_base_ ;
    8848             :          }
    8849             : 
    8850             :          const std::size_t index_;
    8851             :          const std::size_t max_vector_index_;
    8852             :          vector_holder_ptr vector_holder_;
    8853             :          T*                vector_base_;
    8854             :          branch_t          vector_node_;
    8855             :          vector_access_runtime_check_ptr vec_rt_chk_;
    8856             :       };
    8857             : 
    8858             :       template <typename T>
    8859             :       class rebasevector_elem_node exprtk_final
    8860             :                                    : public expression_node<T>
    8861             :                                    , public ivariable      <T>
    8862             :       {
    8863             :       public:
    8864             : 
    8865             :          typedef expression_node<T>*            expression_ptr;
    8866             :          typedef vector_holder<T>               vector_holder_t;
    8867             :          typedef vector_holder_t*               vector_holder_ptr;
    8868             :          typedef vec_data_store<T>              vds_t;
    8869             :          typedef std::pair<expression_ptr,bool> branch_t;
    8870             : 
    8871        1014 :          rebasevector_elem_node(expression_ptr vec_node,
    8872             :                                 expression_ptr index,
    8873             :                                 vector_holder_ptr vec_holder)
    8874        1014 :          : vector_holder_(vec_holder)
    8875             :          {
    8876        1014 :             construct_branch_pair(vector_node_, vec_node);
    8877        1014 :             construct_branch_pair(index_      , index   );
    8878        1014 :             assert(valid());
    8879        1014 :          }
    8880             : 
    8881         863 :          inline T value() const exprtk_override
    8882             :          {
    8883         863 :             return *access_vector();
    8884             :          }
    8885             : 
    8886         600 :          inline T& ref() exprtk_override
    8887             :          {
    8888         600 :             return *access_vector();
    8889             :          }
    8890             : 
    8891           0 :          inline const T& ref() const exprtk_override
    8892             :          {
    8893           0 :             return *access_vector();
    8894             :          }
    8895             : 
    8896       24774 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8897             :          {
    8898       24774 :             return expression_node<T>::e_rbvecelem;
    8899             :          }
    8900             : 
    8901        4631 :          inline bool valid() const exprtk_override
    8902             :          {
    8903             :             return
    8904        9262 :                vector_holder_        &&
    8905        4631 :                index_.first          &&
    8906        4631 :                vector_node_.first    &&
    8907       13893 :                index_.first->valid() &&
    8908        9262 :                vector_node_.first->valid();
    8909             :          }
    8910             : 
    8911             :          inline vector_holder_t& vec_holder()
    8912             :          {
    8913             :             return (*vector_holder_);
    8914             :          }
    8915             : 
    8916        1014 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8917             :          {
    8918        1014 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    8919        1014 :             expression_node<T>::ndb_t::collect(index_,       node_delete_list);
    8920        1014 :          }
    8921             : 
    8922        2394 :          std::size_t node_depth() const exprtk_override
    8923             :          {
    8924             :             return expression_node<T>::ndb_t::compute_node_depth
    8925        2394 :                (vector_node_, index_);
    8926             :          }
    8927             : 
    8928             :       private:
    8929             : 
    8930        1463 :          inline T* access_vector() const
    8931             :          {
    8932        1463 :             vector_node_.first->value();
    8933        1463 :             return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value()));
    8934             :          }
    8935             : 
    8936             :          vector_holder_ptr vector_holder_;
    8937             :          branch_t          vector_node_;
    8938             :          branch_t          index_;
    8939             :       };
    8940             : 
    8941             :       template <typename T>
    8942             :       class rebasevector_celem_node exprtk_final
    8943             :                                     : public expression_node<T>
    8944             :                                     , public ivariable      <T>
    8945             :       {
    8946             :       public:
    8947             : 
    8948             :          typedef expression_node<T>* expression_ptr;
    8949             :          typedef vector_holder<T>    vector_holder_t;
    8950             :          typedef vector_holder_t*    vector_holder_ptr;
    8951             :          typedef std::pair<expression_ptr,bool> branch_t;
    8952             : 
    8953        1894 :          rebasevector_celem_node(expression_ptr vec_node,
    8954             :                                  const std::size_t index,
    8955             :                                  vector_holder_ptr vec_holder)
    8956        1894 :          : index_(index)
    8957        1894 :          , vector_holder_(vec_holder)
    8958             :          {
    8959        1894 :             construct_branch_pair(vector_node_, vec_node);
    8960        1894 :             assert(valid());
    8961        1894 :          }
    8962             : 
    8963        1909 :          inline T value() const exprtk_override
    8964             :          {
    8965        1909 :             vector_node_.first->value();
    8966        1909 :             return ref();;
    8967             :          }
    8968             : 
    8969         600 :          inline T& ref() exprtk_override
    8970             :          {
    8971         600 :             return *(vector_holder_->data() + index_);
    8972             :          }
    8973             : 
    8974        1909 :          inline const T& ref() const exprtk_override
    8975             :          {
    8976        1909 :             return *(vector_holder_->data() + index_);
    8977             :          }
    8978             : 
    8979       40054 :          inline typename expression_node<T>::node_type type() const exprtk_override
    8980             :          {
    8981       40054 :             return expression_node<T>::e_rbveccelem;
    8982             :          }
    8983             : 
    8984       10916 :          inline bool valid() const exprtk_override
    8985             :          {
    8986             :             return
    8987       21832 :                vector_holder_     &&
    8988       21832 :                vector_node_.first &&
    8989       21832 :                vector_node_.first->valid();
    8990             :          }
    8991             : 
    8992             :          inline vector_holder_t& vec_holder()
    8993             :          {
    8994             :             return (*vector_holder_);
    8995             :          }
    8996             : 
    8997        1894 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    8998             :          {
    8999        1894 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9000        1894 :          }
    9001             : 
    9002        4990 :          std::size_t node_depth() const exprtk_override
    9003             :          {
    9004        4990 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    9005             :          }
    9006             : 
    9007             :       private:
    9008             : 
    9009             :          const std::size_t index_;
    9010             :          vector_holder_ptr vector_holder_;
    9011             :          branch_t          vector_node_;
    9012             :       };
    9013             : 
    9014             :       template <typename T>
    9015             :       class rebasevector_elem_rtc_node exprtk_final
    9016             :                                        : public expression_node<T>
    9017             :                                        , public ivariable      <T>
    9018             :       {
    9019             :       public:
    9020             : 
    9021             :          typedef expression_node<T>*            expression_ptr;
    9022             :          typedef vector_holder<T>               vector_holder_t;
    9023             :          typedef vector_holder_t*               vector_holder_ptr;
    9024             :          typedef std::pair<expression_ptr,bool> branch_t;
    9025             : 
    9026           2 :          rebasevector_elem_rtc_node(expression_ptr vec_node,
    9027             :                                     expression_ptr index,
    9028             :                                     vector_holder_ptr vec_holder,
    9029             :                                     vector_access_runtime_check_ptr vec_rt_chk)
    9030           2 :          : vector_holder_(vec_holder)
    9031           2 :          , vec_rt_chk_(vec_rt_chk)
    9032             :          {
    9033           2 :             construct_branch_pair(vector_node_, vec_node);
    9034           2 :             construct_branch_pair(index_      , index   );
    9035           2 :             assert(valid());
    9036           2 :          }
    9037             : 
    9038          30 :          inline T value() const exprtk_override
    9039             :          {
    9040          30 :             return *access_vector();
    9041             :          }
    9042             : 
    9043           0 :          inline T& ref() exprtk_override
    9044             :          {
    9045           0 :             return *access_vector();
    9046             :          }
    9047             : 
    9048           0 :          inline const T& ref() const exprtk_override
    9049             :          {
    9050           0 :             return *access_vector();
    9051             :          }
    9052             : 
    9053          52 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9054             :          {
    9055          52 :             return expression_node<T>::e_rbvecelemrtc;
    9056             :          }
    9057             : 
    9058          12 :          inline bool valid() const exprtk_override
    9059             :          {
    9060             :             return
    9061          24 :                vector_holder_        &&
    9062          12 :                index_.first          &&
    9063          12 :                vector_node_.first    &&
    9064          36 :                index_.first->valid() &&
    9065          24 :                vector_node_.first->valid();
    9066             :          }
    9067             : 
    9068             :          inline vector_holder_t& vec_holder()
    9069             :          {
    9070             :             return (*vector_holder_);
    9071             :          }
    9072             : 
    9073           2 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9074             :          {
    9075           2 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9076           2 :             expression_node<T>::ndb_t::collect(index_      , node_delete_list);
    9077           2 :          }
    9078             : 
    9079           6 :          std::size_t node_depth() const exprtk_override
    9080             :          {
    9081             :             return expression_node<T>::ndb_t::compute_node_depth
    9082           6 :                (vector_node_, index_);
    9083             :          }
    9084             : 
    9085             :       private:
    9086             : 
    9087          30 :          inline T* access_vector() const
    9088             :          {
    9089          30 :             vector_node_.first->value();
    9090          30 :             const _uint64_t index = details::numeric::to_uint64(index_.first->value());
    9091             : 
    9092          30 :             if (index <= (vector_holder_->size() - 1))
    9093             :             {
    9094          15 :                return (vector_holder_->data() + index);
    9095             :             }
    9096             : 
    9097          15 :             assert(vec_rt_chk_);
    9098             : 
    9099             :             vector_access_runtime_check::violation_context context;
    9100          15 :             context.base_ptr   = reinterpret_cast<void*>(vector_holder_->data());
    9101          15 :             context.end_ptr    = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size());
    9102          15 :             context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index);
    9103          15 :             context.type_size  = sizeof(T);
    9104             : 
    9105          15 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    9106             :                    reinterpret_cast<T*>(context.access_ptr) :
    9107          15 :                    vector_holder_->data() ;
    9108             :          }
    9109             : 
    9110             :          vector_holder_ptr vector_holder_;
    9111             :          branch_t          vector_node_;
    9112             :          branch_t          index_;
    9113             :          vector_access_runtime_check_ptr vec_rt_chk_;
    9114             :       };
    9115             : 
    9116             :       template <typename T>
    9117             :       class rebasevector_celem_rtc_node exprtk_final
    9118             :                                     : public expression_node<T>
    9119             :                                     , public ivariable      <T>
    9120             :       {
    9121             :       public:
    9122             : 
    9123             :          typedef expression_node<T>*            expression_ptr;
    9124             :          typedef vector_holder<T>               vector_holder_t;
    9125             :          typedef vector_holder_t*               vector_holder_ptr;
    9126             :          typedef std::pair<expression_ptr,bool> branch_t;
    9127             : 
    9128           0 :          rebasevector_celem_rtc_node(expression_ptr vec_node,
    9129             :                                      const std::size_t index,
    9130             :                                      vector_holder_ptr vec_holder,
    9131             :                                      vector_access_runtime_check_ptr vec_rt_chk)
    9132           0 :          : index_(index)
    9133           0 :          , vector_holder_(vec_holder)
    9134           0 :          , vector_base_((*vec_holder)[0])
    9135           0 :          , vec_rt_chk_(vec_rt_chk)
    9136             :          {
    9137           0 :             construct_branch_pair(vector_node_, vec_node);
    9138           0 :             assert(valid());
    9139           0 :          }
    9140             : 
    9141           0 :          inline T value() const exprtk_override
    9142             :          {
    9143           0 :             return *access_vector();
    9144             :          }
    9145             : 
    9146           0 :          inline T& ref() exprtk_override
    9147             :          {
    9148           0 :             return *access_vector();
    9149             :          }
    9150             : 
    9151           0 :          inline const T& ref() const exprtk_override
    9152             :          {
    9153           0 :             return *access_vector();
    9154             :          }
    9155             : 
    9156           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9157             :          {
    9158           0 :             return expression_node<T>::e_rbveccelemrtc;
    9159             :          }
    9160             : 
    9161           0 :          inline bool valid() const exprtk_override
    9162             :          {
    9163             :             return
    9164           0 :                vector_holder_     &&
    9165           0 :                vector_node_.first &&
    9166           0 :                vector_node_.first->valid();
    9167             :          }
    9168             : 
    9169             :          inline vector_holder_t& vec_holder()
    9170             :          {
    9171             :             return (*vector_holder_);
    9172             :          }
    9173             : 
    9174           0 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9175             :          {
    9176           0 :             expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
    9177           0 :          }
    9178             : 
    9179           0 :          std::size_t node_depth() const exprtk_override
    9180             :          {
    9181           0 :             return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
    9182             :          }
    9183             : 
    9184             :       private:
    9185             : 
    9186           0 :          inline T* access_vector() const
    9187             :          {
    9188           0 :             vector_node_.first->value();
    9189             : 
    9190           0 :             if (index_ <= vector_holder_->size() - 1)
    9191             :             {
    9192           0 :                return (vector_holder_->data() + index_);
    9193             :             }
    9194             : 
    9195           0 :             assert(vec_rt_chk_);
    9196             : 
    9197             :             vector_access_runtime_check::violation_context context;
    9198           0 :             context.base_ptr   = reinterpret_cast<void*>(vector_base_);
    9199           0 :             context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
    9200           0 :             context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
    9201           0 :             context.type_size  = sizeof(T);
    9202             : 
    9203           0 :             return vec_rt_chk_->handle_runtime_violation(context) ?
    9204             :                reinterpret_cast<T*>(context.access_ptr) :
    9205           0 :                vector_base_ ;
    9206             :          }
    9207             : 
    9208             :          const std::size_t index_;
    9209             :          vector_holder_ptr vector_holder_;
    9210             :          T*                vector_base_;
    9211             :          branch_t          vector_node_;
    9212             :          vector_access_runtime_check_ptr vec_rt_chk_;
    9213             :       };
    9214             : 
    9215             :       template <typename T>
    9216             :       class vector_assignment_node exprtk_final : public expression_node<T>
    9217             :       {
    9218             :       public:
    9219             : 
    9220             :          typedef expression_node<T>* expression_ptr;
    9221             : 
    9222       19552 :          vector_assignment_node(T* vector_base,
    9223             :                                 const std::size_t& size,
    9224             :                                 const std::vector<expression_ptr>& initialiser_list,
    9225             :                                 const bool single_value_initialse)
    9226       19552 :          : vector_base_(vector_base)
    9227       19552 :          , initialiser_list_(initialiser_list)
    9228       19552 :          , size_(size)
    9229       19552 :          , single_value_initialse_(single_value_initialse)
    9230       19552 :          , zero_value_initialse_(false)
    9231       19552 :          , const_nonzero_literal_value_initialse_(false)
    9232       19552 :          , single_initialiser_value_(T(0))
    9233             :          {
    9234       19552 :             if (single_value_initialse_)
    9235             :             {
    9236        7501 :                if (initialiser_list_.empty())
    9237         838 :                   zero_value_initialse_ = true;
    9238        6663 :                else if (
    9239        6663 :                          (initialiser_list_.size() == 1) &&
    9240       13296 :                          details::is_constant_node(initialiser_list_[0]) &&
    9241        6633 :                          (T(0) == initialiser_list_[0]->value())
    9242             :                        )
    9243             :                {
    9244         824 :                   zero_value_initialse_ = true;
    9245             :                }
    9246             :                else
    9247             :                {
    9248        5839 :                   assert(initialiser_list_.size() == 1);
    9249             : 
    9250        5839 :                   if (details::is_constant_node(initialiser_list_[0]))
    9251             :                   {
    9252        5809 :                      const_nonzero_literal_value_initialse_ = true;
    9253        5809 :                      single_initialiser_value_ = initialiser_list_[0]->value();
    9254        5809 :                      assert(T(0) != single_initialiser_value_);
    9255             :                   }
    9256             :                }
    9257             :             }
    9258       19552 :          }
    9259             : 
    9260       20298 :          inline T value() const exprtk_override
    9261             :          {
    9262       20298 :             if (single_value_initialse_)
    9263             :             {
    9264        7493 :                if (zero_value_initialse_)
    9265             :                {
    9266        1646 :                   details::set_zero_value(vector_base_, size_);
    9267             :                }
    9268        5847 :                else if (const_nonzero_literal_value_initialse_)
    9269             :                {
    9270    98519881 :                   for (std::size_t i = 0; i < size_; ++i)
    9271             :                   {
    9272    98514064 :                      *(vector_base_ + i) = single_initialiser_value_;
    9273             :                   }
    9274             :                }
    9275             :                else
    9276             :                {
    9277         210 :                   for (std::size_t i = 0; i < size_; ++i)
    9278             :                   {
    9279         180 :                      *(vector_base_ + i) = initialiser_list_[0]->value();
    9280             :                   }
    9281             :                }
    9282             :             }
    9283             :             else
    9284             :             {
    9285       12805 :                const std::size_t initialiser_list_size = initialiser_list_.size();
    9286             : 
    9287       57217 :                for (std::size_t i = 0; i < initialiser_list_size; ++i)
    9288             :                {
    9289       44412 :                   *(vector_base_ + i) = initialiser_list_[i]->value();
    9290             :                }
    9291             : 
    9292       12805 :                if (initialiser_list_size < size_)
    9293             :                {
    9294         110 :                   details::set_zero_value(
    9295         110 :                      vector_base_ + initialiser_list_size,
    9296         110 :                      (size_ - initialiser_list_size));
    9297             :                }
    9298             :             }
    9299             : 
    9300       20298 :             return *(vector_base_);
    9301             :          }
    9302             : 
    9303      296195 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9304             :          {
    9305      296195 :             return expression_node<T>::e_vecdefass;
    9306             :          }
    9307             : 
    9308       24256 :          inline bool valid() const exprtk_override
    9309             :          {
    9310       24256 :             return vector_base_;
    9311             :          }
    9312             : 
    9313       19552 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9314             :          {
    9315       19552 :             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
    9316       19552 :          }
    9317             : 
    9318       53089 :          std::size_t node_depth() const exprtk_override
    9319             :          {
    9320       53089 :             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
    9321             :          }
    9322             : 
    9323             :       private:
    9324             : 
    9325             :          vector_assignment_node(const vector_assignment_node<T>&) exprtk_delete;
    9326             :          vector_assignment_node<T>& operator=(const vector_assignment_node<T>&) exprtk_delete;
    9327             : 
    9328             :          mutable T* vector_base_;
    9329             :          std::vector<expression_ptr> initialiser_list_;
    9330             :          const std::size_t size_;
    9331             :          const bool single_value_initialse_;
    9332             :          bool zero_value_initialse_;
    9333             :          bool const_nonzero_literal_value_initialse_;
    9334             :          T single_initialiser_value_;
    9335             :       };
    9336             : 
    9337             :       template <typename T>
    9338             :       class swap_node exprtk_final : public expression_node<T>
    9339             :       {
    9340             :       public:
    9341             : 
    9342             :          typedef expression_node<T>* expression_ptr;
    9343             :          typedef variable_node<T>*   variable_node_ptr;
    9344             : 
    9345         480 :          swap_node(variable_node_ptr var0, variable_node_ptr var1)
    9346         480 :          : var0_(var0)
    9347         480 :          , var1_(var1)
    9348         480 :          {}
    9349             : 
    9350         480 :          inline T value() const exprtk_override
    9351             :          {
    9352         480 :             std::swap(var0_->ref(),var1_->ref());
    9353         480 :             return var1_->ref();
    9354             :          }
    9355             : 
    9356        5760 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9357             :          {
    9358        5760 :             return expression_node<T>::e_swap;
    9359             :          }
    9360             : 
    9361             :       private:
    9362             : 
    9363             :          variable_node_ptr var0_;
    9364             :          variable_node_ptr var1_;
    9365             :       };
    9366             : 
    9367             :       template <typename T>
    9368             :       class swap_generic_node exprtk_final : public binary_node<T>
    9369             :       {
    9370             :       public:
    9371             : 
    9372             :          typedef expression_node<T>* expression_ptr;
    9373             :          typedef ivariable<T>*       ivariable_ptr;
    9374             : 
    9375         646 :          swap_generic_node(expression_ptr var0, expression_ptr var1)
    9376        1292 :          : binary_node<T>(details::e_swap, var0, var1)
    9377         646 :          , var0_(dynamic_cast<ivariable_ptr>(var0))
    9378        1292 :          , var1_(dynamic_cast<ivariable_ptr>(var1))
    9379         646 :          {}
    9380             : 
    9381         685 :          inline T value() const exprtk_override
    9382             :          {
    9383         685 :             std::swap(var0_->ref(),var1_->ref());
    9384         685 :             return var1_->ref();
    9385             :          }
    9386             : 
    9387        7544 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9388             :          {
    9389        7544 :             return expression_node<T>::e_swap;
    9390             :          }
    9391             : 
    9392             :       private:
    9393             : 
    9394             :          ivariable_ptr var0_;
    9395             :          ivariable_ptr var1_;
    9396             :       };
    9397             : 
    9398             :       template <typename T>
    9399             :       class swap_vecvec_node exprtk_final
    9400             :                              : public binary_node     <T>
    9401             :                              , public vector_interface<T>
    9402             :       {
    9403             :       public:
    9404             : 
    9405             :          typedef expression_node<T>* expression_ptr;
    9406             :          typedef vector_node    <T>* vector_node_ptr;
    9407             :          typedef vec_data_store <T>  vds_t;
    9408             : 
    9409             :          using binary_node<T>::branch;
    9410             : 
    9411         662 :          swap_vecvec_node(expression_ptr branch0,
    9412             :                           expression_ptr branch1)
    9413           0 :          : binary_node<T>(details::e_swap, branch0, branch1)
    9414         662 :          , vec0_node_ptr_(0)
    9415         662 :          , vec1_node_ptr_(0)
    9416         662 :          , initialised_  (false)
    9417             :          {
    9418         662 :             if (is_ivector_node(branch(0)))
    9419             :             {
    9420         662 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
    9421             : 
    9422         662 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
    9423             :                {
    9424         662 :                   vec0_node_ptr_ = vi->vec();
    9425         662 :                   vds()          = vi->vds();
    9426             :                }
    9427             :             }
    9428             : 
    9429         662 :             if (is_ivector_node(branch(1)))
    9430             :             {
    9431         662 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
    9432             : 
    9433         662 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
    9434             :                {
    9435         662 :                   vec1_node_ptr_ = vi->vec();
    9436             :                }
    9437             :             }
    9438             : 
    9439         662 :             if (vec0_node_ptr_ && vec1_node_ptr_)
    9440             :             {
    9441         662 :                initialised_ = size() <= base_size();
    9442             :             }
    9443             : 
    9444         662 :             assert(valid());
    9445         662 :          }
    9446             : 
    9447         662 :          inline T value() const exprtk_override
    9448             :          {
    9449         662 :             binary_node<T>::branch(0)->value();
    9450         662 :             binary_node<T>::branch(1)->value();
    9451             : 
    9452         662 :             T* vec0 = vec0_node_ptr_->vds().data();
    9453         662 :             T* vec1 = vec1_node_ptr_->vds().data();
    9454             : 
    9455         662 :             assert(size() <= base_size());
    9456         662 :             const std::size_t n = size();
    9457             : 
    9458        2186 :             for (std::size_t i = 0; i < n; ++i)
    9459             :             {
    9460        1524 :                std::swap(vec0[i],vec1[i]);
    9461             :             }
    9462             : 
    9463         662 :             return vec1_node_ptr_->value();
    9464             :          }
    9465             : 
    9466           0 :          vector_node_ptr vec() const exprtk_override
    9467             :          {
    9468           0 :             return vec0_node_ptr_;
    9469             :          }
    9470             : 
    9471           0 :          vector_node_ptr vec() exprtk_override
    9472             :          {
    9473           0 :             return vec0_node_ptr_;
    9474             :          }
    9475             : 
    9476        7282 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9477             :          {
    9478        7282 :             return expression_node<T>::e_vecvecswap;
    9479             :          }
    9480             : 
    9481        1986 :          inline bool valid() const exprtk_override
    9482             :          {
    9483        1986 :             return initialised_ && binary_node<T>::valid();
    9484             :          }
    9485             : 
    9486        1986 :          std::size_t size() const exprtk_override
    9487             :          {
    9488        1986 :             return std::min(
    9489        1986 :                vec0_node_ptr_->vec_holder().size(),
    9490        3972 :                vec1_node_ptr_->vec_holder().size());
    9491             :          }
    9492             : 
    9493        1324 :          std::size_t base_size() const exprtk_override
    9494             :          {
    9495        1324 :             return std::min(
    9496        1324 :                vec0_node_ptr_->vec_holder().base_size(),
    9497        2648 :                vec1_node_ptr_->vec_holder().base_size());
    9498             :          }
    9499             : 
    9500         662 :          vds_t& vds() exprtk_override
    9501             :          {
    9502         662 :             return vds_;
    9503             :          }
    9504             : 
    9505           0 :          const vds_t& vds() const exprtk_override
    9506             :          {
    9507           0 :             return vds_;
    9508             :          }
    9509             : 
    9510             :       private:
    9511             : 
    9512             :          vector_node<T>* vec0_node_ptr_;
    9513             :          vector_node<T>* vec1_node_ptr_;
    9514             :          bool            initialised_;
    9515             :          vds_t           vds_;
    9516             :       };
    9517             : 
    9518             :       #ifndef exprtk_disable_string_capabilities
    9519             :       template <typename T>
    9520             :       class stringvar_node exprtk_final
    9521             :                            : public expression_node <T>
    9522             :                            , public string_base_node<T>
    9523             :                            , public range_interface <T>
    9524             :       {
    9525             :       public:
    9526             : 
    9527             :          typedef typename range_interface<T>::range_t range_t;
    9528             : 
    9529             :          static std::string null_value;
    9530             : 
    9531             :          explicit stringvar_node()
    9532             :          : value_(&null_value)
    9533             :          {}
    9534             : 
    9535      131795 :          explicit stringvar_node(std::string& v)
    9536      131795 :          : value_(&v)
    9537             :          {
    9538      131795 :             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
    9539      131795 :             rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size());
    9540      131795 :             rp_.cache.first  = rp_.n0_c.second;
    9541      131795 :             rp_.cache.second = rp_.n1_c.second;
    9542      131795 :          }
    9543             : 
    9544             :          inline bool operator <(const stringvar_node<T>& v) const
    9545             :          {
    9546             :             return this < (&v);
    9547             :          }
    9548             : 
    9549       29457 :          inline T value() const exprtk_override
    9550             :          {
    9551       29457 :             rp_.n1_c.second  = (*value_).size();
    9552       29457 :             rp_.cache.second = rp_.n1_c.second;
    9553             : 
    9554       29457 :             return std::numeric_limits<T>::quiet_NaN();
    9555             :          }
    9556             : 
    9557        1740 :          std::string str() const exprtk_override
    9558             :          {
    9559        1740 :             return ref();
    9560             :          }
    9561             : 
    9562       25250 :          char_cptr base() const exprtk_override
    9563             :          {
    9564       25250 :             return &(*value_)[0];
    9565             :          }
    9566             : 
    9567       10853 :          std::size_t size() const exprtk_override
    9568             :          {
    9569       10853 :             return ref().size();
    9570             :          }
    9571             : 
    9572       72804 :          std::string& ref()
    9573             :          {
    9574       72804 :             return (*value_);
    9575             :          }
    9576             : 
    9577       12593 :          const std::string& ref() const
    9578             :          {
    9579       12593 :             return (*value_);
    9580             :          }
    9581             : 
    9582       10629 :          range_t& range_ref() exprtk_override
    9583             :          {
    9584       10629 :             return rp_;
    9585             :          }
    9586             : 
    9587           0 :          const range_t& range_ref() const exprtk_override
    9588             :          {
    9589           0 :             return rp_;
    9590             :          }
    9591             : 
    9592      975278 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9593             :          {
    9594      975278 :             return expression_node<T>::e_stringvar;
    9595             :          }
    9596             : 
    9597             :          void rebase(std::string& s)
    9598             :          {
    9599             :             value_ = &s;
    9600             :             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
    9601             :             rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1);
    9602             :             rp_.cache.first  = rp_.n0_c.second;
    9603             :             rp_.cache.second = rp_.n1_c.second;
    9604             :          }
    9605             : 
    9606             :       private:
    9607             : 
    9608             :          std::string* value_;
    9609             :          mutable range_t rp_;
    9610             :       };
    9611             : 
    9612             :       template <typename T>
    9613             :       std::string stringvar_node<T>::null_value = std::string("");
    9614             : 
    9615             :       template <typename T>
    9616             :       class string_range_node exprtk_final
    9617             :                               : public expression_node <T>
    9618             :                               , public string_base_node<T>
    9619             :                               , public range_interface <T>
    9620             :       {
    9621             :       public:
    9622             : 
    9623             :          typedef typename range_interface<T>::range_t range_t;
    9624             : 
    9625             :          static std::string null_value;
    9626             : 
    9627       22141 :          explicit string_range_node(std::string& v, const range_t& rp)
    9628       22141 :          : value_(&v)
    9629       22141 :          , rp_(rp)
    9630       22141 :          {}
    9631             : 
    9632       44282 :          virtual ~string_range_node()
    9633             :          {
    9634       22141 :             rp_.free();
    9635       44282 :          }
    9636             : 
    9637             :          inline bool operator <(const string_range_node<T>& v) const
    9638             :          {
    9639             :             return this < (&v);
    9640             :          }
    9641             : 
    9642       13429 :          inline T value() const exprtk_override
    9643             :          {
    9644       13429 :             return std::numeric_limits<T>::quiet_NaN();
    9645             :          }
    9646             : 
    9647           0 :          inline std::string str() const exprtk_override
    9648             :          {
    9649           0 :             return (*value_);
    9650             :          }
    9651             : 
    9652       21168 :          char_cptr base() const exprtk_override
    9653             :          {
    9654       21168 :             return &(*value_)[0];
    9655             :          }
    9656             : 
    9657       13456 :          std::size_t size() const exprtk_override
    9658             :          {
    9659       13456 :             return ref().size();
    9660             :          }
    9661             : 
    9662        8700 :          inline range_t range() const
    9663             :          {
    9664        8700 :             return rp_;
    9665             :          }
    9666             : 
    9667        8700 :          inline virtual std::string& ref()
    9668             :          {
    9669        8700 :             return (*value_);
    9670             :          }
    9671             : 
    9672       13456 :          inline virtual const std::string& ref() const
    9673             :          {
    9674       13456 :             return (*value_);
    9675             :          }
    9676             : 
    9677       22156 :          inline range_t& range_ref() exprtk_override
    9678             :          {
    9679       22156 :             return rp_;
    9680             :          }
    9681             : 
    9682           0 :          inline const range_t& range_ref() const exprtk_override
    9683             :          {
    9684           0 :             return rp_;
    9685             :          }
    9686             : 
    9687      434686 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9688             :          {
    9689      434686 :             return expression_node<T>::e_stringvarrng;
    9690             :          }
    9691             : 
    9692             :       private:
    9693             : 
    9694             :          std::string* value_;
    9695             :          range_t      rp_;
    9696             :       };
    9697             : 
    9698             :       template <typename T>
    9699             :       std::string string_range_node<T>::null_value = std::string("");
    9700             : 
    9701             :       template <typename T>
    9702             :       class const_string_range_node exprtk_final
    9703             :                                     : public expression_node <T>
    9704             :                                     , public string_base_node<T>
    9705             :                                     , public range_interface <T>
    9706             :       {
    9707             :       public:
    9708             : 
    9709             :          typedef typename range_interface<T>::range_t range_t;
    9710             : 
    9711        5553 :          explicit const_string_range_node(const std::string& v, const range_t& rp)
    9712        5553 :          : value_(v)
    9713        5553 :          , rp_(rp)
    9714        5553 :          {}
    9715             : 
    9716       11106 :         ~const_string_range_node()
    9717             :          {
    9718        5553 :             rp_.free();
    9719       11106 :          }
    9720             : 
    9721         551 :          inline T value() const exprtk_override
    9722             :          {
    9723         551 :             return std::numeric_limits<T>::quiet_NaN();
    9724             :          }
    9725             : 
    9726        5000 :          std::string str() const exprtk_override
    9727             :          {
    9728        5000 :             return value_;
    9729             :          }
    9730             : 
    9731         551 :          char_cptr base() const exprtk_override
    9732             :          {
    9733         551 :             return value_.data();
    9734             :          }
    9735             : 
    9736         551 :          std::size_t size() const exprtk_override
    9737             :          {
    9738         551 :             return value_.size();
    9739             :          }
    9740             : 
    9741        5000 :          range_t range() const
    9742             :          {
    9743        5000 :             return rp_;
    9744             :          }
    9745             : 
    9746        5551 :          range_t& range_ref() exprtk_override
    9747             :          {
    9748        5551 :             return rp_;
    9749             :          }
    9750             : 
    9751           0 :          const range_t& range_ref() const exprtk_override
    9752             :          {
    9753           0 :             return rp_;
    9754             :          }
    9755             : 
    9756      110965 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9757             :          {
    9758      110965 :             return expression_node<T>::e_cstringvarrng;
    9759             :          }
    9760             : 
    9761             :       private:
    9762             : 
    9763             :          const_string_range_node(const const_string_range_node<T>&) exprtk_delete;
    9764             :          const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete;
    9765             : 
    9766             :          const std::string value_;
    9767             :          range_t rp_;
    9768             :       };
    9769             : 
    9770             :       template <typename T>
    9771             :       class generic_string_range_node exprtk_final
    9772             :                                       : public expression_node <T>
    9773             :                                       , public string_base_node<T>
    9774             :                                       , public range_interface <T>
    9775             :       {
    9776             :       public:
    9777             : 
    9778             :          typedef expression_node <T>* expression_ptr;
    9779             :          typedef stringvar_node  <T>* strvar_node_ptr;
    9780             :          typedef string_base_node<T>* str_base_ptr;
    9781             :          typedef typename range_interface<T>::range_t range_t;
    9782             :          typedef range_t*             range_ptr;
    9783             :          typedef range_interface<T>   irange_t;
    9784             :          typedef irange_t*            irange_ptr;
    9785             :          typedef std::pair<expression_ptr,bool>  branch_t;
    9786             : 
    9787        4102 :          generic_string_range_node(expression_ptr str_branch, const range_t& brange)
    9788        4102 :          : initialised_(false)
    9789        4102 :          , str_base_ptr_ (0)
    9790        4102 :          , str_range_ptr_(0)
    9791        4102 :          , base_range_(brange)
    9792             :          {
    9793        4102 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
    9794        4102 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
    9795        4102 :             range_.cache.first  = range_.n0_c.second;
    9796        4102 :             range_.cache.second = range_.n1_c.second;
    9797             : 
    9798        4102 :             construct_branch_pair(branch_, str_branch);
    9799             : 
    9800        4102 :             if (is_generally_string_node(branch_.first))
    9801             :             {
    9802        4102 :                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
    9803             : 
    9804        4102 :                if (0 == str_base_ptr_)
    9805           0 :                   return;
    9806             : 
    9807        4102 :                str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
    9808             : 
    9809        4102 :                if (0 == str_range_ptr_)
    9810           0 :                   return;
    9811             :             }
    9812             : 
    9813        4102 :             initialised_ = (str_base_ptr_ && str_range_ptr_);
    9814        4102 :             assert(valid());
    9815           0 :          }
    9816             : 
    9817        8204 :         ~generic_string_range_node()
    9818             :          {
    9819        4102 :             base_range_.free();
    9820        8204 :          }
    9821             : 
    9822        4100 :          inline T value() const exprtk_override
    9823             :          {
    9824        4100 :             branch_.first->value();
    9825             : 
    9826        4100 :             std::size_t str_r0 = 0;
    9827        4100 :             std::size_t str_r1 = 0;
    9828             : 
    9829        4100 :             std::size_t r0 = 0;
    9830        4100 :             std::size_t r1 = 0;
    9831             : 
    9832        4100 :             const range_t& range = str_range_ptr_->range_ref();
    9833             : 
    9834        4100 :             const std::size_t base_str_size = str_base_ptr_->size();
    9835             : 
    9836        4100 :             if (
    9837        8200 :                   range      (str_r0, str_r1, base_str_size         ) &&
    9838        8200 :                   base_range_(r0    , r1    , base_str_size - str_r0)
    9839             :                )
    9840             :             {
    9841        4100 :                const std::size_t size = r1 - r0;
    9842             : 
    9843        4100 :                range_.n1_c.second  = size;
    9844        4100 :                range_.cache.second = range_.n1_c.second;
    9845             : 
    9846        4100 :                value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
    9847             :             }
    9848             : 
    9849        8200 :             return std::numeric_limits<T>::quiet_NaN();
    9850             :          }
    9851             : 
    9852        1300 :          std::string str() const exprtk_override
    9853             :          {
    9854        1300 :             return value_;
    9855             :          }
    9856             : 
    9857        2250 :          char_cptr base() const exprtk_override
    9858             :          {
    9859        2250 :             return &value_[0];
    9860             :          }
    9861             : 
    9862        4100 :          std::size_t size() const exprtk_override
    9863             :          {
    9864        4100 :             return value_.size();
    9865             :          }
    9866             : 
    9867        3550 :          range_t& range_ref() exprtk_override
    9868             :          {
    9869        3550 :             return range_;
    9870             :          }
    9871             : 
    9872           0 :          const range_t& range_ref() const exprtk_override
    9873             :          {
    9874           0 :             return range_;
    9875             :          }
    9876             : 
    9877       35556 :          inline typename expression_node<T>::node_type type() const exprtk_override
    9878             :          {
    9879       35556 :             return expression_node<T>::e_strgenrange;
    9880             :          }
    9881             : 
    9882        9504 :          inline bool valid() const exprtk_override
    9883             :          {
    9884        9504 :             return initialised_ && branch_.first;
    9885             :          }
    9886             : 
    9887        4102 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
    9888             :          {
    9889        4102 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
    9890        4102 :          }
    9891             : 
    9892        8202 :          std::size_t node_depth() const exprtk_override
    9893             :          {
    9894        8202 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
    9895             :          }
    9896             : 
    9897             :       private:
    9898             : 
    9899             :          bool                initialised_;
    9900             :          branch_t            branch_;
    9901             :          str_base_ptr        str_base_ptr_;
    9902             :          irange_ptr          str_range_ptr_;
    9903             :          mutable range_t     base_range_;
    9904             :          mutable range_t     range_;
    9905             :          mutable std::string value_;
    9906             :       };
    9907             : 
    9908             :       template <typename T>
    9909             :       class string_concat_node exprtk_final
    9910             :                                : public binary_node     <T>
    9911             :                                , public string_base_node<T>
    9912             :                                , public range_interface <T>
    9913             :       {
    9914             :       public:
    9915             : 
    9916             :          typedef typename range_interface<T>::range_t range_t;
    9917             :          typedef range_interface<T>   irange_t;
    9918             :          typedef irange_t*            irange_ptr;
    9919             :          typedef range_t*             range_ptr;
    9920             :          typedef expression_node <T>* expression_ptr;
    9921             :          typedef string_base_node<T>* str_base_ptr;
    9922             : 
    9923             :          using binary_node<T>::branch;
    9924             : 
    9925        5166 :          string_concat_node(const operator_type& opr,
    9926             :                             expression_ptr branch0,
    9927             :                             expression_ptr branch1)
    9928             :          : binary_node<T>(opr, branch0, branch1)
    9929        5166 :          , initialised_(false)
    9930        5166 :          , str0_base_ptr_ (0)
    9931        5166 :          , str1_base_ptr_ (0)
    9932        5166 :          , str0_range_ptr_(0)
    9933        5166 :          , str1_range_ptr_(0)
    9934             :          {
    9935        5166 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
    9936        5166 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
    9937             : 
    9938        5166 :             range_.cache.first  = range_.n0_c.second;
    9939        5166 :             range_.cache.second = range_.n1_c.second;
    9940             : 
    9941        5166 :             if (is_generally_string_node(branch(0)))
    9942             :             {
    9943        5166 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
    9944             : 
    9945        5166 :                if (0 == str0_base_ptr_)
    9946           0 :                   return;
    9947             : 
    9948        5166 :                str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
    9949             : 
    9950        5166 :                if (0 == str0_range_ptr_)
    9951           0 :                   return;
    9952             :             }
    9953             : 
    9954        5166 :             if (is_generally_string_node(branch(1)))
    9955             :             {
    9956        5166 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
    9957             : 
    9958        5166 :                if (0 == str1_base_ptr_)
    9959           0 :                   return;
    9960             : 
    9961        5166 :                str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1));
    9962             : 
    9963        5166 :                if (0 == str1_range_ptr_)
    9964           0 :                   return;
    9965             :             }
    9966             : 
    9967       15498 :             initialised_ = str0_base_ptr_  &&
    9968        5166 :                            str1_base_ptr_  &&
    9969       15498 :                            str0_range_ptr_ &&
    9970        5166 :                            str1_range_ptr_ ;
    9971             : 
    9972        5166 :             assert(valid());
    9973           0 :          }
    9974             : 
    9975        6114 :          inline T value() const exprtk_override
    9976             :          {
    9977        6114 :             branch(0)->value();
    9978        6114 :             branch(1)->value();
    9979             : 
    9980        6114 :             std::size_t str0_r0 = 0;
    9981        6114 :             std::size_t str0_r1 = 0;
    9982             : 
    9983        6114 :             std::size_t str1_r0 = 0;
    9984        6114 :             std::size_t str1_r1 = 0;
    9985             : 
    9986        6114 :             const range_t& range0 = str0_range_ptr_->range_ref();
    9987        6114 :             const range_t& range1 = str1_range_ptr_->range_ref();
    9988             : 
    9989        6114 :             if (
    9990       12228 :                   range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
    9991       12228 :                   range1(str1_r0, str1_r1, str1_base_ptr_->size())
    9992             :                )
    9993             :             {
    9994        6114 :                const std::size_t size0 = (str0_r1 - str0_r0);
    9995        6114 :                const std::size_t size1 = (str1_r1 - str1_r0);
    9996             : 
    9997        6114 :                value_.assign(str0_base_ptr_->base() + str0_r0, size0);
    9998        6114 :                value_.append(str1_base_ptr_->base() + str1_r0, size1);
    9999             : 
   10000        6114 :                range_.n1_c.second  = value_.size();
   10001        6114 :                range_.cache.second = range_.n1_c.second;
   10002             :             }
   10003             : 
   10004       12228 :             return std::numeric_limits<T>::quiet_NaN();
   10005             :          }
   10006             : 
   10007        2696 :          std::string str() const exprtk_override
   10008             :          {
   10009        2696 :             return value_;
   10010             :          }
   10011             : 
   10012        3484 :          char_cptr base() const exprtk_override
   10013             :          {
   10014        3484 :             return &value_[0];
   10015             :          }
   10016             : 
   10017        6180 :          std::size_t size() const exprtk_override
   10018             :          {
   10019        6180 :             return value_.size();
   10020             :          }
   10021             : 
   10022        5181 :          range_t& range_ref() exprtk_override
   10023             :          {
   10024        5181 :             return range_;
   10025             :          }
   10026             : 
   10027           0 :          const range_t& range_ref() const exprtk_override
   10028             :          {
   10029           0 :             return range_;
   10030             :          }
   10031             : 
   10032       76153 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10033             :          {
   10034       76153 :             return expression_node<T>::e_strconcat;
   10035             :          }
   10036             : 
   10037       17060 :          inline bool valid() const exprtk_override
   10038             :          {
   10039       17060 :             return initialised_ && binary_node<T>::valid();
   10040             :          }
   10041             : 
   10042             :       private:
   10043             : 
   10044             :          bool                initialised_;
   10045             :          str_base_ptr        str0_base_ptr_;
   10046             :          str_base_ptr        str1_base_ptr_;
   10047             :          irange_ptr          str0_range_ptr_;
   10048             :          irange_ptr          str1_range_ptr_;
   10049             :          mutable range_t     range_;
   10050             :          mutable std::string value_;
   10051             :       };
   10052             : 
   10053             :       template <typename T>
   10054             :       class swap_string_node exprtk_final
   10055             :                              : public binary_node     <T>
   10056             :                              , public string_base_node<T>
   10057             :                              , public range_interface <T>
   10058             :       {
   10059             :       public:
   10060             : 
   10061             :          typedef typename range_interface<T>::range_t range_t;
   10062             :          typedef range_t*             range_ptr;
   10063             :          typedef range_interface<T>   irange_t;
   10064             :          typedef irange_t*            irange_ptr;
   10065             :          typedef expression_node <T>* expression_ptr;
   10066             :          typedef stringvar_node  <T>* strvar_node_ptr;
   10067             :          typedef string_base_node<T>* str_base_ptr;
   10068             : 
   10069             :          using binary_node<T>::branch;
   10070             : 
   10071           0 :          swap_string_node(expression_ptr branch0, expression_ptr branch1)
   10072           0 :          : binary_node<T>(details::e_swap, branch0, branch1)
   10073           0 :          , initialised_(false)
   10074           0 :          , str0_node_ptr_(0)
   10075           0 :          , str1_node_ptr_(0)
   10076             :          {
   10077           0 :             if (is_string_node(branch(0)))
   10078             :             {
   10079           0 :                str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
   10080             :             }
   10081             : 
   10082           0 :             if (is_string_node(branch(1)))
   10083             :             {
   10084           0 :                str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1));
   10085             :             }
   10086             : 
   10087           0 :             initialised_ = (str0_node_ptr_ && str1_node_ptr_);
   10088           0 :             assert(valid());
   10089           0 :          }
   10090             : 
   10091           0 :          inline T value() const exprtk_override
   10092             :          {
   10093           0 :             branch(0)->value();
   10094           0 :             branch(1)->value();
   10095             : 
   10096           0 :             std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
   10097             : 
   10098           0 :             return std::numeric_limits<T>::quiet_NaN();
   10099             :          }
   10100             : 
   10101           0 :          std::string str() const exprtk_override
   10102             :          {
   10103           0 :             return str0_node_ptr_->str();
   10104             :          }
   10105             : 
   10106           0 :          char_cptr base() const exprtk_override
   10107             :          {
   10108           0 :            return str0_node_ptr_->base();
   10109             :          }
   10110             : 
   10111           0 :          std::size_t size() const exprtk_override
   10112             :          {
   10113           0 :             return str0_node_ptr_->size();
   10114             :          }
   10115             : 
   10116           0 :          range_t& range_ref() exprtk_override
   10117             :          {
   10118           0 :             return str0_node_ptr_->range_ref();
   10119             :          }
   10120             : 
   10121           0 :          const range_t& range_ref() const exprtk_override
   10122             :          {
   10123           0 :             return str0_node_ptr_->range_ref();
   10124             :          }
   10125             : 
   10126           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10127             :          {
   10128           0 :             return expression_node<T>::e_strswap;
   10129             :          }
   10130             : 
   10131           0 :          inline bool valid() const exprtk_override
   10132             :          {
   10133           0 :             return initialised_ && binary_node<T>::valid();
   10134             :          }
   10135             : 
   10136             :       private:
   10137             : 
   10138             :          bool initialised_;
   10139             :          strvar_node_ptr str0_node_ptr_;
   10140             :          strvar_node_ptr str1_node_ptr_;
   10141             :       };
   10142             : 
   10143             :       template <typename T>
   10144             :       class swap_genstrings_node exprtk_final : public binary_node<T>
   10145             :       {
   10146             :       public:
   10147             : 
   10148             :          typedef typename range_interface<T>::range_t range_t;
   10149             :          typedef range_t*             range_ptr;
   10150             :          typedef range_interface<T>   irange_t;
   10151             :          typedef irange_t*            irange_ptr;
   10152             :          typedef expression_node <T>* expression_ptr;
   10153             :          typedef string_base_node<T>* str_base_ptr;
   10154             : 
   10155             :          using binary_node<T>::branch;
   10156             : 
   10157        1500 :          swap_genstrings_node(expression_ptr branch0,
   10158             :                               expression_ptr branch1)
   10159           0 :          : binary_node<T>(details::e_default, branch0, branch1)
   10160        1500 :          , str0_base_ptr_ (0)
   10161        1500 :          , str1_base_ptr_ (0)
   10162        1500 :          , str0_range_ptr_(0)
   10163        1500 :          , str1_range_ptr_(0)
   10164        1500 :          , initialised_(false)
   10165             :          {
   10166        1500 :             if (is_generally_string_node(branch(0)))
   10167             :             {
   10168        1500 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   10169             : 
   10170        1500 :                if (0 == str0_base_ptr_)
   10171           0 :                   return;
   10172             : 
   10173        1500 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
   10174             : 
   10175        1500 :                if (0 == range)
   10176           0 :                   return;
   10177             : 
   10178        1500 :                str0_range_ptr_ = &(range->range_ref());
   10179             :             }
   10180             : 
   10181        1500 :             if (is_generally_string_node(branch(1)))
   10182             :             {
   10183        1500 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   10184             : 
   10185        1500 :                if (0 == str1_base_ptr_)
   10186           0 :                   return;
   10187             : 
   10188        1500 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   10189             : 
   10190        1500 :                if (0 == range)
   10191           0 :                   return;
   10192             : 
   10193        1500 :                str1_range_ptr_ = &(range->range_ref());
   10194             :             }
   10195             : 
   10196        4500 :             initialised_ = str0_base_ptr_  &&
   10197        1500 :                            str1_base_ptr_  &&
   10198        4500 :                            str0_range_ptr_ &&
   10199        1500 :                            str1_range_ptr_ ;
   10200             : 
   10201        1500 :             assert(valid());
   10202           0 :          }
   10203             : 
   10204        1500 :          inline T value() const exprtk_override
   10205             :          {
   10206        1500 :             branch(0)->value();
   10207        1500 :             branch(1)->value();
   10208             : 
   10209        1500 :             std::size_t str0_r0 = 0;
   10210        1500 :             std::size_t str0_r1 = 0;
   10211             : 
   10212        1500 :             std::size_t str1_r0 = 0;
   10213        1500 :             std::size_t str1_r1 = 0;
   10214             : 
   10215        1500 :             const range_t& range0 = (*str0_range_ptr_);
   10216        1500 :             const range_t& range1 = (*str1_range_ptr_);
   10217             : 
   10218        1500 :             if (
   10219        3000 :                   range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
   10220        3000 :                   range1(str1_r0, str1_r1, str1_base_ptr_->size())
   10221             :                )
   10222             :             {
   10223        1500 :                const std::size_t size0    = range0.cache_size();
   10224        1500 :                const std::size_t size1    = range1.cache_size();
   10225        1500 :                const std::size_t max_size = std::min(size0,size1);
   10226             : 
   10227        1500 :                char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
   10228        1500 :                char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
   10229             : 
   10230        1500 :                loop_unroll::details lud(max_size);
   10231        1500 :                char_cptr upper_bound = s0 + lud.upper_bound;
   10232             : 
   10233        1500 :                while (s0 < upper_bound)
   10234             :                {
   10235             :                   #define exprtk_loop(N)   \
   10236             :                   std::swap(s0[N], s1[N]); \
   10237             : 
   10238           0 :                   exprtk_loop( 0) exprtk_loop( 1)
   10239           0 :                   exprtk_loop( 2) exprtk_loop( 3)
   10240             :                   #ifndef exprtk_disable_superscalar_unroll
   10241           0 :                   exprtk_loop( 4) exprtk_loop( 5)
   10242           0 :                   exprtk_loop( 6) exprtk_loop( 7)
   10243           0 :                   exprtk_loop( 8) exprtk_loop( 9)
   10244           0 :                   exprtk_loop(10) exprtk_loop(11)
   10245           0 :                   exprtk_loop(12) exprtk_loop(13)
   10246           0 :                   exprtk_loop(14) exprtk_loop(15)
   10247             :                   #endif
   10248             : 
   10249           0 :                   s0 += lud.batch_size;
   10250           0 :                   s1 += lud.batch_size;
   10251             :                }
   10252             : 
   10253        1500 :                int i = 0;
   10254             : 
   10255        1500 :                switch (lud.remainder)
   10256             :                {
   10257             :                   #define case_stmt(N)                       \
   10258             :                   case N : { std::swap(s0[i], s1[i]); ++i; } \
   10259             :                   exprtk_fallthrough                         \
   10260             : 
   10261             :                   #ifndef exprtk_disable_superscalar_unroll
   10262           0 :                   case_stmt(15) case_stmt(14)
   10263           0 :                   case_stmt(13) case_stmt(12)
   10264           0 :                   case_stmt(11) case_stmt(10)
   10265           0 :                   case_stmt( 9) case_stmt( 8)
   10266           0 :                   case_stmt( 7) case_stmt( 6)
   10267         600 :                   case_stmt( 5) case_stmt( 4)
   10268             :                   #endif
   10269        1200 :                   case_stmt( 3) case_stmt( 2)
   10270        1500 :                   case_stmt( 1)
   10271        1500 :                   default: break;
   10272             :                }
   10273             : 
   10274             :                #undef exprtk_loop
   10275             :                #undef case_stmt
   10276             :             }
   10277             : 
   10278        3000 :             return std::numeric_limits<T>::quiet_NaN();
   10279             :          }
   10280             : 
   10281       18000 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10282             :          {
   10283       18000 :             return expression_node<T>::e_strswap;
   10284             :          }
   10285             : 
   10286        4500 :          inline bool valid() const exprtk_override
   10287             :          {
   10288        4500 :             return initialised_ && binary_node<T>::valid();
   10289             :          }
   10290             : 
   10291             :       private:
   10292             : 
   10293             :          swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete;
   10294             :          swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete;
   10295             : 
   10296             :          str_base_ptr str0_base_ptr_;
   10297             :          str_base_ptr str1_base_ptr_;
   10298             :          range_ptr    str0_range_ptr_;
   10299             :          range_ptr    str1_range_ptr_;
   10300             :          bool         initialised_;
   10301             :       };
   10302             : 
   10303             :       template <typename T>
   10304             :       class stringvar_size_node exprtk_final : public expression_node<T>
   10305             :       {
   10306             :       public:
   10307             : 
   10308             :          static const std::string null_value;
   10309             : 
   10310             :          explicit stringvar_size_node()
   10311             :          : value_(&null_value)
   10312             :          {}
   10313             : 
   10314        3600 :          explicit stringvar_size_node(std::string& v)
   10315        3600 :          : value_(&v)
   10316        3600 :          {}
   10317             : 
   10318        3600 :          inline T value() const exprtk_override
   10319             :          {
   10320        3600 :             return T((*value_).size());
   10321             :          }
   10322             : 
   10323       75750 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10324             :          {
   10325       75750 :             return expression_node<T>::e_stringvarsize;
   10326             :          }
   10327             : 
   10328             :       private:
   10329             : 
   10330             :          const std::string* value_;
   10331             :       };
   10332             : 
   10333             :       template <typename T>
   10334             :       const std::string stringvar_size_node<T>::null_value = std::string("");
   10335             : 
   10336             :       template <typename T>
   10337             :       class string_size_node exprtk_final : public expression_node<T>
   10338             :       {
   10339             :       public:
   10340             : 
   10341             :          typedef expression_node <T>* expression_ptr;
   10342             :          typedef string_base_node<T>* str_base_ptr;
   10343             :          typedef std::pair<expression_ptr,bool>  branch_t;
   10344             : 
   10345         750 :          explicit string_size_node(expression_ptr branch)
   10346         750 :          : str_base_ptr_(0)
   10347             :          {
   10348         750 :             construct_branch_pair(branch_, branch);
   10349             : 
   10350         750 :             if (is_generally_string_node(branch_.first))
   10351             :             {
   10352         750 :                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
   10353             :             }
   10354             : 
   10355         750 :             assert(valid());
   10356         750 :          }
   10357             : 
   10358         750 :          inline T value() const exprtk_override
   10359             :          {
   10360         750 :             branch_.first->value();
   10361         750 :             return T(str_base_ptr_->size());
   10362             :          }
   10363             : 
   10364       23250 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10365             :          {
   10366       23250 :             return expression_node<T>::e_stringsize;
   10367             :          }
   10368             : 
   10369        1500 :          inline bool valid() const exprtk_override
   10370             :          {
   10371        1500 :             return str_base_ptr_;
   10372             :          }
   10373             : 
   10374         750 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   10375             :          {
   10376         750 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   10377         750 :          }
   10378             : 
   10379        1500 :          std::size_t node_depth() const exprtk_override
   10380             :          {
   10381        1500 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   10382             :          }
   10383             : 
   10384             :       private:
   10385             : 
   10386             :          branch_t     branch_;
   10387             :          str_base_ptr str_base_ptr_;
   10388             :       };
   10389             : 
   10390             :       struct asn_assignment
   10391             :       {
   10392       12735 :          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
   10393       12735 :          { s.assign(data,size); }
   10394             :       };
   10395             : 
   10396             :       struct asn_addassignment
   10397             :       {
   10398        6700 :          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
   10399        6700 :          { s.append(data,size); }
   10400             :       };
   10401             : 
   10402             :       template <typename T, typename AssignmentProcess = asn_assignment>
   10403             :       class assignment_string_node exprtk_final
   10404             :                                    : public binary_node     <T>
   10405             :                                    , public string_base_node<T>
   10406             :                                    , public range_interface <T>
   10407             :       {
   10408             :       public:
   10409             : 
   10410             :          typedef typename range_interface<T>::range_t range_t;
   10411             :          typedef range_t*             range_ptr;
   10412             :          typedef range_interface <T>  irange_t;
   10413             :          typedef irange_t*            irange_ptr;
   10414             :          typedef expression_node <T>* expression_ptr;
   10415             :          typedef stringvar_node  <T>* strvar_node_ptr;
   10416             :          typedef string_base_node<T>* str_base_ptr;
   10417             : 
   10418             :          using binary_node<T>::branch;
   10419             : 
   10420       14336 :          assignment_string_node(const operator_type& opr,
   10421             :                                 expression_ptr branch0,
   10422             :                                 expression_ptr branch1)
   10423             :          : binary_node<T>(opr, branch0, branch1)
   10424       14336 :          , initialised_(false)
   10425       14336 :          , str0_base_ptr_ (0)
   10426       14336 :          , str1_base_ptr_ (0)
   10427       14336 :          , str0_node_ptr_ (0)
   10428       14336 :          , str1_range_ptr_(0)
   10429             :          {
   10430       14336 :             if (is_string_node(branch(0)))
   10431             :             {
   10432       14336 :                str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
   10433       14336 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   10434             :             }
   10435             : 
   10436       14336 :             if (is_generally_string_node(branch(1)))
   10437             :             {
   10438       14336 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   10439             : 
   10440       14336 :                if (0 == str1_base_ptr_)
   10441           0 :                   return;
   10442             : 
   10443       14336 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   10444             : 
   10445       14336 :                if (0 == range)
   10446           0 :                   return;
   10447             : 
   10448       14336 :                str1_range_ptr_ = &(range->range_ref());
   10449             :             }
   10450             : 
   10451       43008 :             initialised_ = str0_base_ptr_  &&
   10452       14336 :                            str1_base_ptr_  &&
   10453       43008 :                            str0_node_ptr_  &&
   10454       14336 :                            str1_range_ptr_ ;
   10455             : 
   10456       14336 :             assert(valid());
   10457           0 :          }
   10458             : 
   10459       19435 :          inline T value() const exprtk_override
   10460             :          {
   10461       19435 :             branch(1)->value();
   10462             : 
   10463       19435 :             std::size_t r0 = 0;
   10464       19435 :             std::size_t r1 = 0;
   10465             : 
   10466       19435 :             const range_t& range = (*str1_range_ptr_);
   10467             : 
   10468       19435 :             if (range(r0, r1, str1_base_ptr_->size()))
   10469             :             {
   10470       19435 :                AssignmentProcess::execute(
   10471       19435 :                   str0_node_ptr_->ref(),
   10472       19435 :                   str1_base_ptr_->base() + r0, (r1 - r0));
   10473             : 
   10474       19435 :                branch(0)->value();
   10475             :             }
   10476             : 
   10477       38870 :             return std::numeric_limits<T>::quiet_NaN();
   10478             :          }
   10479             : 
   10480         300 :          std::string str() const exprtk_override
   10481             :          {
   10482         300 :             return str0_node_ptr_->str();
   10483             :          }
   10484             : 
   10485         201 :          char_cptr base() const exprtk_override
   10486             :          {
   10487         201 :            return str0_node_ptr_->base();
   10488             :          }
   10489             : 
   10490         701 :          std::size_t size() const exprtk_override
   10491             :          {
   10492         701 :             return str0_node_ptr_->size();
   10493             :          }
   10494             : 
   10495         501 :          range_t& range_ref() exprtk_override
   10496             :          {
   10497         501 :             return str0_node_ptr_->range_ref();
   10498             :          }
   10499             : 
   10500           0 :          const range_t& range_ref() const exprtk_override
   10501             :          {
   10502           0 :             return str0_node_ptr_->range_ref();
   10503             :          }
   10504             : 
   10505      170992 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10506             :          {
   10507      170992 :             return expression_node<T>::e_strass;
   10508             :          }
   10509             : 
   10510       43875 :          inline bool valid() const exprtk_override
   10511             :          {
   10512       43875 :             return initialised_ && binary_node<T>::valid();
   10513             :          }
   10514             : 
   10515             :       private:
   10516             : 
   10517             :          bool            initialised_;
   10518             :          str_base_ptr    str0_base_ptr_;
   10519             :          str_base_ptr    str1_base_ptr_;
   10520             :          strvar_node_ptr str0_node_ptr_;
   10521             :          range_ptr       str1_range_ptr_;
   10522             :       };
   10523             : 
   10524             :       template <typename T, typename AssignmentProcess = asn_assignment>
   10525             :       class assignment_string_range_node exprtk_final
   10526             :                                          : public binary_node     <T>
   10527             :                                          , public string_base_node<T>
   10528             :                                          , public range_interface <T>
   10529             :       {
   10530             :       public:
   10531             : 
   10532             :          typedef typename range_interface<T>::range_t range_t;
   10533             :          typedef range_t*              range_ptr;
   10534             :          typedef range_interface  <T>  irange_t;
   10535             :          typedef irange_t*             irange_ptr;
   10536             :          typedef expression_node  <T>* expression_ptr;
   10537             :          typedef stringvar_node   <T>* strvar_node_ptr;
   10538             :          typedef string_range_node<T>* str_rng_node_ptr;
   10539             :          typedef string_base_node <T>* str_base_ptr;
   10540             : 
   10541             :          using binary_node<T>::branch;
   10542             : 
   10543        4850 :          assignment_string_range_node(const operator_type& opr,
   10544             :                                       expression_ptr branch0,
   10545             :                                       expression_ptr branch1)
   10546             :          : binary_node<T>(opr, branch0, branch1)
   10547        4850 :          , initialised_(false)
   10548        4850 :          , str0_base_ptr_    (0)
   10549        4850 :          , str1_base_ptr_    (0)
   10550        4850 :          , str0_rng_node_ptr_(0)
   10551        4850 :          , str0_range_ptr_   (0)
   10552        4850 :          , str1_range_ptr_   (0)
   10553             :          {
   10554        4850 :             if (is_string_range_node(branch(0)))
   10555             :             {
   10556        4850 :                str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0));
   10557        4850 :                str0_base_ptr_     = dynamic_cast<str_base_ptr>(branch(0));
   10558        4850 :                irange_ptr range   = dynamic_cast<irange_ptr>(branch(0));
   10559             : 
   10560        4850 :                if (0 == range)
   10561           0 :                   return;
   10562             : 
   10563        4850 :                str0_range_ptr_ = &(range->range_ref());
   10564             :             }
   10565             : 
   10566        4850 :             if (is_generally_string_node(branch(1)))
   10567             :             {
   10568        4850 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   10569             : 
   10570        4850 :                if (0 == str1_base_ptr_)
   10571           0 :                   return;
   10572             : 
   10573        4850 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   10574             : 
   10575        4850 :                if (0 == range)
   10576           0 :                   return;
   10577             : 
   10578        4850 :                str1_range_ptr_ = &(range->range_ref());
   10579             :             }
   10580             : 
   10581       14550 :             initialised_ = str0_base_ptr_     &&
   10582        4850 :                            str1_base_ptr_     &&
   10583        4850 :                            str0_rng_node_ptr_ &&
   10584       14550 :                            str0_range_ptr_    &&
   10585        4850 :                            str1_range_ptr_    ;
   10586             : 
   10587        4850 :             assert(valid());
   10588           0 :          }
   10589             : 
   10590        4850 :          inline T value() const exprtk_override
   10591             :          {
   10592        4850 :             branch(0)->value();
   10593        4850 :             branch(1)->value();
   10594             : 
   10595        4850 :             std::size_t s0_r0 = 0;
   10596        4850 :             std::size_t s0_r1 = 0;
   10597             : 
   10598        4850 :             std::size_t s1_r0 = 0;
   10599        4850 :             std::size_t s1_r1 = 0;
   10600             : 
   10601        4850 :             const range_t& range0 = (*str0_range_ptr_);
   10602        4850 :             const range_t& range1 = (*str1_range_ptr_);
   10603             : 
   10604        4850 :             if (
   10605        9700 :                   range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
   10606        9700 :                   range1(s1_r0, s1_r1, str1_base_ptr_->size())
   10607             :                )
   10608             :             {
   10609        4850 :                const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0));
   10610             : 
   10611        9700 :                std::copy(
   10612        4850 :                   str1_base_ptr_->base() + s1_r0,
   10613        4850 :                   str1_base_ptr_->base() + s1_r0 + size,
   10614        4850 :                   const_cast<char_ptr>(base() + s0_r0));
   10615             :             }
   10616             : 
   10617        9700 :             return std::numeric_limits<T>::quiet_NaN();
   10618             :          }
   10619             : 
   10620           0 :          std::string str() const exprtk_override
   10621             :          {
   10622           0 :             return str0_base_ptr_->str();
   10623             :          }
   10624             : 
   10625        4850 :          char_cptr base() const exprtk_override
   10626             :          {
   10627        4850 :             return str0_base_ptr_->base();
   10628             :          }
   10629             : 
   10630           0 :          std::size_t size() const exprtk_override
   10631             :          {
   10632           0 :             return str0_base_ptr_->size();
   10633             :          }
   10634             : 
   10635           0 :          range_t& range_ref() exprtk_override
   10636             :          {
   10637           0 :             return str0_rng_node_ptr_->range_ref();
   10638             :          }
   10639             : 
   10640           0 :          const range_t& range_ref() const exprtk_override
   10641             :          {
   10642           0 :             return str0_rng_node_ptr_->range_ref();
   10643             :          }
   10644             : 
   10645       78300 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10646             :          {
   10647       78300 :             return expression_node<T>::e_strass;
   10648             :          }
   10649             : 
   10650       14550 :          inline bool valid() const exprtk_override
   10651             :          {
   10652       14550 :             return initialised_ && binary_node<T>::valid();
   10653             :          }
   10654             : 
   10655             :       private:
   10656             : 
   10657             :          bool             initialised_;
   10658             :          str_base_ptr     str0_base_ptr_;
   10659             :          str_base_ptr     str1_base_ptr_;
   10660             :          str_rng_node_ptr str0_rng_node_ptr_;
   10661             :          range_ptr        str0_range_ptr_;
   10662             :          range_ptr        str1_range_ptr_;
   10663             :       };
   10664             : 
   10665             :       template <typename T>
   10666             :       class conditional_string_node exprtk_final
   10667             :                                     : public trinary_node    <T>
   10668             :                                     , public string_base_node<T>
   10669             :                                     , public range_interface <T>
   10670             :       {
   10671             :       public:
   10672             : 
   10673             :          typedef typename range_interface<T>::range_t range_t;
   10674             :          typedef range_t*             range_ptr;
   10675             :          typedef range_interface <T>  irange_t;
   10676             :          typedef irange_t*            irange_ptr;
   10677             :          typedef expression_node <T>* expression_ptr;
   10678             :          typedef string_base_node<T>* str_base_ptr;
   10679             : 
   10680        1145 :          conditional_string_node(expression_ptr condition,
   10681             :                                  expression_ptr consequent,
   10682             :                                  expression_ptr alternative)
   10683           0 :          : trinary_node<T>(details::e_default, consequent, alternative, condition)
   10684        1145 :          , initialised_(false)
   10685        1145 :          , str0_base_ptr_ (0)
   10686        1145 :          , str1_base_ptr_ (0)
   10687        1145 :          , str0_range_ptr_(0)
   10688        1145 :          , str1_range_ptr_(0)
   10689        1145 :          , condition_  (condition  )
   10690        1145 :          , consequent_ (consequent )
   10691        1145 :          , alternative_(alternative)
   10692             :          {
   10693        1145 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   10694        1145 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   10695             : 
   10696        1145 :             range_.cache.first  = range_.n0_c.second;
   10697        1145 :             range_.cache.second = range_.n1_c.second;
   10698             : 
   10699        1145 :             if (is_generally_string_node(trinary_node<T>::branch_[0].first))
   10700             :             {
   10701        1145 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
   10702             : 
   10703        1145 :                if (0 == str0_base_ptr_)
   10704           0 :                   return;
   10705             : 
   10706        1145 :                str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
   10707             : 
   10708        1145 :                if (0 == str0_range_ptr_)
   10709           0 :                   return;
   10710             :             }
   10711             : 
   10712        1145 :             if (is_generally_string_node(trinary_node<T>::branch_[1].first))
   10713             :             {
   10714        1145 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
   10715             : 
   10716        1145 :                if (0 == str1_base_ptr_)
   10717           0 :                   return;
   10718             : 
   10719        1145 :                str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
   10720             : 
   10721        1145 :                if (0 == str1_range_ptr_)
   10722           0 :                   return;
   10723             :             }
   10724             : 
   10725        3435 :             initialised_ = str0_base_ptr_  &&
   10726        1145 :                            str1_base_ptr_  &&
   10727        3435 :                            str0_range_ptr_ &&
   10728        1145 :                            str1_range_ptr_ ;
   10729             : 
   10730        1145 :             assert(valid());
   10731           0 :          }
   10732             : 
   10733        1145 :          inline T value() const exprtk_override
   10734             :          {
   10735        1145 :             std::size_t r0 = 0;
   10736        1145 :             std::size_t r1 = 0;
   10737             : 
   10738        1145 :             if (is_true(condition_))
   10739             :             {
   10740         580 :                consequent_->value();
   10741             : 
   10742         580 :                const range_t& range = str0_range_ptr_->range_ref();
   10743             : 
   10744         580 :                if (range(r0, r1, str0_base_ptr_->size()))
   10745             :                {
   10746         580 :                   const std::size_t size = (r1 - r0);
   10747             : 
   10748         580 :                   value_.assign(str0_base_ptr_->base() + r0, size);
   10749             : 
   10750         580 :                   range_.n1_c.second  = value_.size();
   10751         580 :                   range_.cache.second = range_.n1_c.second;
   10752             : 
   10753         580 :                   return T(1);
   10754             :                }
   10755             :             }
   10756             :             else
   10757             :             {
   10758         565 :                alternative_->value();
   10759             : 
   10760         565 :                const range_t& range = str1_range_ptr_->range_ref();
   10761             : 
   10762         565 :                if (range(r0, r1, str1_base_ptr_->size()))
   10763             :                {
   10764         565 :                   const std::size_t size = (r1 - r0);
   10765             : 
   10766         565 :                   value_.assign(str1_base_ptr_->base() + r0, size);
   10767             : 
   10768         565 :                   range_.n1_c.second  = value_.size();
   10769         565 :                   range_.cache.second = range_.n1_c.second;
   10770             : 
   10771         565 :                   return T(0);
   10772             :                }
   10773             :             }
   10774             : 
   10775           0 :             return std::numeric_limits<T>::quiet_NaN();
   10776             :          }
   10777             : 
   10778        1100 :          std::string str() const exprtk_override
   10779             :          {
   10780        1100 :             return value_;
   10781             :          }
   10782             : 
   10783          45 :          char_cptr base() const exprtk_override
   10784             :          {
   10785          45 :             return &value_[0];
   10786             :          }
   10787             : 
   10788        1145 :          std::size_t size() const exprtk_override
   10789             :          {
   10790        1145 :             return value_.size();
   10791             :          }
   10792             : 
   10793        1145 :          range_t& range_ref() exprtk_override
   10794             :          {
   10795        1145 :             return range_;
   10796             :          }
   10797             : 
   10798           0 :          const range_t& range_ref() const exprtk_override
   10799             :          {
   10800           0 :             return range_;
   10801             :          }
   10802             : 
   10803       27070 :          inline typename expression_node<T>::node_type type() const exprtk_override
   10804             :          {
   10805       27070 :             return expression_node<T>::e_strcondition;
   10806             :          }
   10807             : 
   10808        3660 :          inline bool valid() const exprtk_override
   10809             :          {
   10810             :             return
   10811        7320 :                initialised_                         &&
   10812        3660 :                condition_  && condition_  ->valid() &&
   10813        3660 :                consequent_ && consequent_ ->valid() &&
   10814        7320 :                alternative_&& alternative_->valid() ;
   10815             :          }
   10816             : 
   10817             :       private:
   10818             : 
   10819             :          bool initialised_;
   10820             :          str_base_ptr str0_base_ptr_;
   10821             :          str_base_ptr str1_base_ptr_;
   10822             :          irange_ptr   str0_range_ptr_;
   10823             :          irange_ptr   str1_range_ptr_;
   10824             :          mutable range_t     range_;
   10825             :          mutable std::string value_;
   10826             : 
   10827             :          expression_ptr condition_;
   10828             :          expression_ptr consequent_;
   10829             :          expression_ptr alternative_;
   10830             :       };
   10831             : 
   10832             :       template <typename T>
   10833             :       class cons_conditional_str_node exprtk_final
   10834             :                                       : public binary_node     <T>
   10835             :                                       , public string_base_node<T>
   10836             :                                       , public range_interface <T>
   10837             :       {
   10838             :       public:
   10839             : 
   10840             :          typedef typename range_interface<T>::range_t range_t;
   10841             :          typedef range_t*             range_ptr;
   10842             :          typedef range_interface <T>  irange_t;
   10843             :          typedef irange_t*            irange_ptr;
   10844             :          typedef expression_node <T>* expression_ptr;
   10845             :          typedef string_base_node<T>* str_base_ptr;
   10846             : 
   10847             :          using binary_node<T>::branch;
   10848             : 
   10849             :          cons_conditional_str_node(expression_ptr condition,
   10850             :                                    expression_ptr consequent)
   10851             :          : binary_node<T>(details::e_default, consequent, condition)
   10852             :          , initialised_(false)
   10853             :          , str0_base_ptr_ (0)
   10854             :          , str0_range_ptr_(0)
   10855             :          , condition_ (condition )
   10856             :          , consequent_(consequent)
   10857             :          {
   10858             :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   10859             :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   10860             : 
   10861             :             range_.cache.first  = range_.n0_c.second;
   10862             :             range_.cache.second = range_.n1_c.second;
   10863             : 
   10864             :             if (is_generally_string_node(branch(0)))
   10865             :             {
   10866             :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   10867             : 
   10868             :                if (0 == str0_base_ptr_)
   10869             :                   return;
   10870             : 
   10871             :                str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
   10872             : 
   10873             :                if (0 == str0_range_ptr_)
   10874             :                   return;
   10875             :             }
   10876             : 
   10877             :             initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
   10878             :             assert(valid());
   10879             :          }
   10880             : 
   10881             :          inline T value() const exprtk_override
   10882             :          {
   10883             :             if (is_true(condition_))
   10884             :             {
   10885             :                consequent_->value();
   10886             : 
   10887             :                const range_t& range = str0_range_ptr_->range_ref();
   10888             : 
   10889             :                std::size_t r0 = 0;
   10890             :                std::size_t r1 = 0;
   10891             : 
   10892             :                if (range(r0, r1, str0_base_ptr_->size()))
   10893             :                {
   10894             :                   const std::size_t size = (r1 - r0);
   10895             : 
   10896             :                   value_.assign(str0_base_ptr_->base() + r0, size);
   10897             : 
   10898             :                   range_.n1_c.second  = value_.size();
   10899             :                   range_.cache.second = range_.n1_c.second;
   10900             : 
   10901             :                   return T(1);
   10902             :                }
   10903             :             }
   10904             : 
   10905             :             return std::numeric_limits<T>::quiet_NaN();
   10906             :          }
   10907             : 
   10908             :          std::string str() const
   10909             :          {
   10910             :             return value_;
   10911             :          }
   10912             : 
   10913             :          char_cptr base() const
   10914             :          {
   10915             :             return &value_[0];
   10916             :          }
   10917             : 
   10918             :          std::size_t size() const
   10919             :          {
   10920             :             return value_.size();
   10921             :          }
   10922             : 
   10923             :          range_t& range_ref()
   10924             :          {
   10925             :             return range_;
   10926             :          }
   10927             : 
   10928             :          const range_t& range_ref() const
   10929             :          {
   10930             :             return range_;
   10931             :          }
   10932             : 
   10933             :          inline typename expression_node<T>::node_type type() const exprtk_override
   10934             :          {
   10935             :             return expression_node<T>::e_strccondition;
   10936             :          }
   10937             : 
   10938             :          inline bool valid() const exprtk_override
   10939             :          {
   10940             :             return
   10941             :                initialised_                         &&
   10942             :                condition_  && condition_  ->valid() &&
   10943             :                consequent_ && consequent_ ->valid() ;
   10944             :          }
   10945             : 
   10946             :       private:
   10947             : 
   10948             :          bool initialised_;
   10949             :          str_base_ptr str0_base_ptr_;
   10950             :          irange_ptr   str0_range_ptr_;
   10951             :          mutable range_t     range_;
   10952             :          mutable std::string value_;
   10953             : 
   10954             :          expression_ptr condition_;
   10955             :          expression_ptr consequent_;
   10956             :       };
   10957             : 
   10958             :       template <typename T, typename VarArgFunction>
   10959             :       class str_vararg_node exprtk_final
   10960             :                             : public expression_node <T>
   10961             :                             , public string_base_node<T>
   10962             :                             , public range_interface <T>
   10963             :       {
   10964             :       public:
   10965             : 
   10966             :          typedef typename range_interface<T>::range_t range_t;
   10967             :          typedef range_t*             range_ptr;
   10968             :          typedef range_interface <T>  irange_t;
   10969             :          typedef irange_t*            irange_ptr;
   10970             :          typedef expression_node <T>* expression_ptr;
   10971             :          typedef string_base_node<T>* str_base_ptr;
   10972             :          typedef std::pair<expression_ptr,bool> branch_t;
   10973             : 
   10974             :          template <typename Allocator,
   10975             :                    template <typename, typename> class Sequence>
   10976          85 :          explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
   10977          85 :          : initialised_(false)
   10978          85 :          , str_base_ptr_ (0)
   10979          85 :          , str_range_ptr_(0)
   10980             :          {
   10981          85 :             construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
   10982             : 
   10983          85 :             if (0 == final_node_.first)
   10984           0 :                return;
   10985          85 :             else if (!is_generally_string_node(final_node_.first))
   10986           0 :                return;
   10987             : 
   10988          85 :             str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first);
   10989             : 
   10990          85 :             if (0 == str_base_ptr_)
   10991           0 :                return;
   10992             : 
   10993          85 :             str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first);
   10994             : 
   10995          85 :             if (0 == str_range_ptr_)
   10996           0 :                return;
   10997             : 
   10998          85 :             if (arg_list.size() > 1)
   10999             :             {
   11000          85 :                const std::size_t arg_list_size = arg_list.size() - 1;
   11001             : 
   11002          85 :                arg_list_.resize(arg_list_size);
   11003             : 
   11004         245 :                for (std::size_t i = 0; i < arg_list_size; ++i)
   11005             :                {
   11006         160 :                   if (arg_list[i] && arg_list[i]->valid())
   11007             :                   {
   11008         160 :                      construct_branch_pair(arg_list_[i], arg_list[i]);
   11009             :                   }
   11010             :                   else
   11011             :                   {
   11012           0 :                      arg_list_.clear();
   11013           0 :                      return;
   11014             :                   }
   11015             :                }
   11016             : 
   11017          85 :                initialised_ = true;
   11018             :             }
   11019             : 
   11020          85 :             initialised_ &= str_base_ptr_ && str_range_ptr_;
   11021          85 :             assert(valid());
   11022           0 :          }
   11023             : 
   11024          85 :          inline T value() const exprtk_override
   11025             :          {
   11026          85 :             if (!arg_list_.empty())
   11027             :             {
   11028          85 :                VarArgFunction::process(arg_list_);
   11029             :             }
   11030             : 
   11031          85 :             final_node_.first->value();
   11032             : 
   11033          85 :             return std::numeric_limits<T>::quiet_NaN();
   11034             :          }
   11035             : 
   11036          40 :          std::string str() const exprtk_override
   11037             :          {
   11038          40 :             return str_base_ptr_->str();
   11039             :          }
   11040             : 
   11041          45 :          char_cptr base() const exprtk_override
   11042             :          {
   11043          45 :             return str_base_ptr_->base();
   11044             :          }
   11045             : 
   11046          85 :          std::size_t size() const exprtk_override
   11047             :          {
   11048          85 :             return str_base_ptr_->size();
   11049             :          }
   11050             : 
   11051          85 :          range_t& range_ref() exprtk_override
   11052             :          {
   11053          85 :             return str_range_ptr_->range_ref();
   11054             :          }
   11055             : 
   11056           0 :          const range_t& range_ref() const exprtk_override
   11057             :          {
   11058           0 :             return str_range_ptr_->range_ref();
   11059             :          }
   11060             : 
   11061        1285 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11062             :          {
   11063        1285 :             return expression_node<T>::e_stringvararg;
   11064             :          }
   11065             : 
   11066         390 :          inline bool valid() const exprtk_override
   11067             :          {
   11068             :             return
   11069         780 :                initialised_ &&
   11070         390 :                final_node_.first && final_node_.first->valid();
   11071             :          }
   11072             : 
   11073          85 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   11074             :          {
   11075          85 :             expression_node<T>::ndb_t::collect(final_node_ , node_delete_list);
   11076          85 :             expression_node<T>::ndb_t::collect(arg_list_   , node_delete_list);
   11077          85 :          }
   11078             : 
   11079         215 :          std::size_t node_depth() const exprtk_override
   11080             :          {
   11081         215 :             return std::max(
   11082         215 :                expression_node<T>::ndb_t::compute_node_depth(final_node_),
   11083         430 :                expression_node<T>::ndb_t::compute_node_depth(arg_list_  ));
   11084             :          }
   11085             : 
   11086             :       private:
   11087             : 
   11088             :          bool                  initialised_;
   11089             :          branch_t              final_node_;
   11090             :          str_base_ptr          str_base_ptr_;
   11091             :          irange_ptr            str_range_ptr_;
   11092             :          std::vector<branch_t> arg_list_;
   11093             :       };
   11094             :       #endif
   11095             : 
   11096             :       template <typename T, std::size_t N>
   11097         640 :       inline T axn(const T a, const T x)
   11098             :       {
   11099             :          // a*x^n
   11100         640 :          return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
   11101             :       }
   11102             : 
   11103             :       template <typename T, std::size_t N>
   11104         320 :       inline T axnb(const T a, const T x, const T b)
   11105             :       {
   11106             :          // a*x^n+b
   11107         320 :          return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
   11108             :       }
   11109             : 
   11110             :       template <typename T>
   11111             :       struct sf_base
   11112             :       {
   11113             :          typedef typename details::functor_t<T>::Type Type;
   11114             :          typedef typename details::functor_t<T> functor_t;
   11115             :          typedef typename functor_t::qfunc_t quaternary_functor_t;
   11116             :          typedef typename functor_t::tfunc_t trinary_functor_t;
   11117             :          typedef typename functor_t::bfunc_t binary_functor_t;
   11118             :          typedef typename functor_t::ufunc_t unary_functor_t;
   11119             :       };
   11120             : 
   11121             :       #define define_sfop3(NN, OP0, OP1)                 \
   11122             :       template <typename T>                              \
   11123             :       struct sf##NN##_op : public sf_base<T>             \
   11124             :       {                                                  \
   11125             :          typedef typename sf_base<T>::Type const Type;   \
   11126             :          static inline T process(Type x, Type y, Type z) \
   11127             :          {                                               \
   11128             :             return (OP0);                                \
   11129             :          }                                               \
   11130             :          static inline std::string id()                  \
   11131             :          {                                               \
   11132             :             return (OP1);                                \
   11133             :          }                                               \
   11134             :       };                                                 \
   11135             : 
   11136      364380 :       define_sfop3(00,(x + y) / z       ,"(t+t)/t")
   11137      364491 :       define_sfop3(01,(x + y) * z       ,"(t+t)*t")
   11138      364881 :       define_sfop3(02,(x + y) - z       ,"(t+t)-t")
   11139      379971 :       define_sfop3(03,(x + y) + z       ,"(t+t)+t")
   11140     4992772 :       define_sfop3(04,(x - y) + z       ,"(t-t)+t")
   11141      362689 :       define_sfop3(05,(x - y) / z       ,"(t-t)/t")
   11142      365236 :       define_sfop3(06,(x - y) * z       ,"(t-t)*t")
   11143   104377688 :       define_sfop3(07,(x * y) + z       ,"(t*t)+t")
   11144      370528 :       define_sfop3(08,(x * y) - z       ,"(t*t)-t")
   11145      496001 :       define_sfop3(09,(x * y) / z       ,"(t*t)/t")
   11146     5143451 :       define_sfop3(10,(x * y) * z       ,"(t*t)*t")
   11147      376356 :       define_sfop3(11,(x / y) + z       ,"(t/t)+t")
   11148      369943 :       define_sfop3(12,(x / y) - z       ,"(t/t)-t")
   11149      319666 :       define_sfop3(13,(x / y) / z       ,"(t/t)/t")
   11150      469991 :       define_sfop3(14,(x / y) * z       ,"(t/t)*t")
   11151      355266 :       define_sfop3(15,x / (y + z)       ,"t/(t+t)")
   11152      354976 :       define_sfop3(16,x / (y - z)       ,"t/(t-t)")
   11153      520761 :       define_sfop3(17,x / (y * z)       ,"t/(t*t)")
   11154      319666 :       define_sfop3(18,x / (y / z)       ,"t/(t/t)")
   11155      360506 :       define_sfop3(19,x * (y + z)       ,"t*(t+t)")
   11156      355506 :       define_sfop3(20,x * (y - z)       ,"t*(t-t)")
   11157      393394 :       define_sfop3(21,x * (y * z)       ,"t*(t*t)")
   11158      353901 :       define_sfop3(22,x * (y / z)       ,"t*(t/t)")
   11159      390271 :       define_sfop3(23,x - (y + z)       ,"t-(t+t)")
   11160      347926 :       define_sfop3(24,x - (y - z)       ,"t-(t-t)")
   11161      369141 :       define_sfop3(25,x - (y / z)       ,"t-(t/t)")
   11162     6383639 :       define_sfop3(26,x - (y * z)       ,"t-(t*t)")
   11163      868722 :       define_sfop3(27,x + (y * z)       ,"t+(t*t)")
   11164      371106 :       define_sfop3(28,x + (y / z)       ,"t+(t/t)")
   11165      348336 :       define_sfop3(29,x + (y + z)       ,"t+(t+t)")
   11166      347266 :       define_sfop3(30,x + (y - z)       ,"t+(t-t)")
   11167          40 :       define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
   11168          40 :       define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
   11169          40 :       define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
   11170          40 :       define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
   11171          40 :       define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
   11172          40 :       define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
   11173          40 :       define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
   11174          40 :       define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
   11175          40 :       define_sfop3(39,x * numeric::log(y)   + z,"")
   11176          40 :       define_sfop3(40,x * numeric::log(y)   - z,"")
   11177          40 :       define_sfop3(41,x * numeric::log10(y) + z,"")
   11178          40 :       define_sfop3(42,x * numeric::log10(y) - z,"")
   11179          40 :       define_sfop3(43,x * numeric::sin(y) + z  ,"")
   11180          40 :       define_sfop3(44,x * numeric::sin(y) - z  ,"")
   11181          40 :       define_sfop3(45,x * numeric::cos(y) + z  ,"")
   11182          40 :       define_sfop3(46,x * numeric::cos(y) - z  ,"")
   11183          40 :       define_sfop3(47,details::is_true(x) ? y : z,"")
   11184             : 
   11185             :       #define define_sfop4(NN, OP0, OP1)                         \
   11186             :       template <typename T>                                      \
   11187             :       struct sf##NN##_op : public sf_base<T>                     \
   11188             :       {                                                          \
   11189             :          typedef typename sf_base<T>::Type const Type;           \
   11190             :          static inline T process(Type x, Type y, Type z, Type w) \
   11191             :          {                                                       \
   11192             :             return (OP0);                                        \
   11193             :          }                                                       \
   11194             :          static inline std::string id()                          \
   11195             :          {                                                       \
   11196             :             return (OP1);                                        \
   11197             :          }                                                       \
   11198             :       };                                                         \
   11199             : 
   11200      322756 :       define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
   11201      322921 :       define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
   11202      322756 :       define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
   11203      322861 :       define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
   11204      326611 :       define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
   11205      327791 :       define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
   11206      322906 :       define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
   11207      319666 :       define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
   11208      326241 :       define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
   11209      322797 :       define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
   11210      322756 :       define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
   11211      322761 :       define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
   11212      322756 :       define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
   11213      326051 :       define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
   11214      326231 :       define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
   11215      319666 :       define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
   11216      326361 :       define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
   11217      322756 :       define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
   11218      322756 :       define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
   11219      323636 :       define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
   11220      324391 :       define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
   11221      322756 :       define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
   11222      322756 :       define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
   11223      325901 :       define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
   11224      319666 :       define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
   11225      326364 :       define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
   11226      325756 :       define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
   11227      323481 :       define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
   11228      324601 :       define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
   11229      324079 :       define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
   11230      324161 :       define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
   11231      326421 :       define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
   11232      322756 :       define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
   11233      322756 :       define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
   11234      322781 :       define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
   11235      322781 :       define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
   11236             : 
   11237          40 :       define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
   11238          40 :       define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
   11239          40 :       define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
   11240          40 :       define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
   11241          40 :       define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
   11242          40 :       define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
   11243          40 :       define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
   11244          40 :       define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
   11245          75 :       define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
   11246          75 :       define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
   11247          75 :       define_sfop4(94,((x <  y) ? z : w),"")
   11248          75 :       define_sfop4(95,((x <= y) ? z : w),"")
   11249          75 :       define_sfop4(96,((x >  y) ? z : w),"")
   11250          75 :       define_sfop4(97,((x >= y) ? z : w),"")
   11251          75 :       define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
   11252          40 :       define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
   11253             : 
   11254      327616 :       define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
   11255      324411 :       define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
   11256      325341 :       define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
   11257      324381 :       define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
   11258      325491 :       define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
   11259      324891 :       define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
   11260      327156 :       define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
   11261      324061 :       define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
   11262      322716 :       define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
   11263      322696 :       define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
   11264      320351 :       define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
   11265      322696 :       define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
   11266      322916 :       define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
   11267      323356 :       define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
   11268      323016 :       define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
   11269      323216 :       define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
   11270      322876 :       define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
   11271      322696 :       define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
   11272      322696 :       define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
   11273      322696 :       define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
   11274      322696 :       define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
   11275      322696 :       define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
   11276      322696 :       define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
   11277      322696 :       define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
   11278      322696 :       define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
   11279      322696 :       define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
   11280      323131 :       define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
   11281      322696 :       define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
   11282      322271 :       define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
   11283      322696 :       define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
   11284      322266 :       define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
   11285      322696 :       define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
   11286      323126 :       define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
   11287      322861 :       define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
   11288      322546 :       define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
   11289      322706 :       define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
   11290      642327 :       define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
   11291           0 :       define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
   11292      322711 :       define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
   11293      322866 :       define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
   11294      321801 :       define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
   11295      319626 :       define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
   11296      322546 :       define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
   11297      320351 :       define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
   11298      322606 :       define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
   11299      322546 :       define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
   11300      328326 :       define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
   11301      328226 :       define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
   11302      319626 :       define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
   11303      319626 :       define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
   11304      320786 :       define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
   11305      320786 :       define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
   11306      320866 :       define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
   11307      320786 :       define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
   11308      321591 :       define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
   11309      320931 :       define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
   11310      321491 :       define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
   11311      320931 :       define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
   11312      320931 :       define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
   11313      321371 :       define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
   11314      323021 :       define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
   11315      335911 :       define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
   11316             : 
   11317             :       #undef define_sfop3
   11318             :       #undef define_sfop4
   11319             : 
   11320             :       template <typename T, typename SpecialFunction>
   11321             :       class sf3_node exprtk_final : public trinary_node<T>
   11322             :       {
   11323             :       public:
   11324             : 
   11325             :          typedef expression_node<T>* expression_ptr;
   11326             : 
   11327         720 :          sf3_node(const operator_type& opr,
   11328             :                   expression_ptr branch0,
   11329             :                   expression_ptr branch1,
   11330             :                   expression_ptr branch2)
   11331         720 :          : trinary_node<T>(opr, branch0, branch1, branch2)
   11332         720 :          {}
   11333             : 
   11334         720 :          inline T value() const exprtk_override
   11335             :          {
   11336         720 :             const T x = trinary_node<T>::branch_[0].first->value();
   11337         720 :             const T y = trinary_node<T>::branch_[1].first->value();
   11338         720 :             const T z = trinary_node<T>::branch_[2].first->value();
   11339             : 
   11340        1440 :             return SpecialFunction::process(x, y, z);
   11341             :          }
   11342             :       };
   11343             : 
   11344             :       template <typename T, typename SpecialFunction>
   11345             :       class sf4_node exprtk_final : public quaternary_node<T>
   11346             :       {
   11347             :       public:
   11348             : 
   11349             :          typedef expression_node<T>* expression_ptr;
   11350             : 
   11351         815 :          sf4_node(const operator_type& opr,
   11352             :                   expression_ptr branch0,
   11353             :                   expression_ptr branch1,
   11354             :                   expression_ptr branch2,
   11355             :                   expression_ptr branch3)
   11356         815 :          : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
   11357         815 :          {}
   11358             : 
   11359         815 :          inline T value() const exprtk_override
   11360             :          {
   11361         815 :             const T x = quaternary_node<T>::branch_[0].first->value();
   11362         815 :             const T y = quaternary_node<T>::branch_[1].first->value();
   11363         815 :             const T z = quaternary_node<T>::branch_[2].first->value();
   11364         815 :             const T w = quaternary_node<T>::branch_[3].first->value();
   11365             : 
   11366        1630 :             return SpecialFunction::process(x, y, z, w);
   11367             :          }
   11368             :       };
   11369             : 
   11370             :       template <typename T, typename SpecialFunction>
   11371             :       class sf3_var_node exprtk_final : public expression_node<T>
   11372             :       {
   11373             :       public:
   11374             : 
   11375             :          typedef expression_node<T>* expression_ptr;
   11376             : 
   11377        1200 :          sf3_var_node(const T& v0, const T& v1, const T& v2)
   11378        1200 :          : v0_(v0)
   11379        1200 :          , v1_(v1)
   11380        1200 :          , v2_(v2)
   11381        1200 :          {}
   11382             : 
   11383        1200 :          inline T value() const exprtk_override
   11384             :          {
   11385        1200 :             return SpecialFunction::process(v0_, v1_, v2_);
   11386             :          }
   11387             : 
   11388       15600 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11389             :          {
   11390       15600 :             return expression_node<T>::e_trinary;
   11391             :          }
   11392             : 
   11393             :       private:
   11394             : 
   11395             :          sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
   11396             :          sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
   11397             : 
   11398             :          const T& v0_;
   11399             :          const T& v1_;
   11400             :          const T& v2_;
   11401             :       };
   11402             : 
   11403             :       template <typename T, typename SpecialFunction>
   11404             :       class sf4_var_node exprtk_final : public expression_node<T>
   11405             :       {
   11406             :       public:
   11407             : 
   11408             :          typedef expression_node<T>* expression_ptr;
   11409             : 
   11410        1510 :          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
   11411        1510 :          : v0_(v0)
   11412        1510 :          , v1_(v1)
   11413        1510 :          , v2_(v2)
   11414        1510 :          , v3_(v3)
   11415        1510 :          {}
   11416             : 
   11417        1510 :          inline T value() const exprtk_override
   11418             :          {
   11419        1510 :             return SpecialFunction::process(v0_, v1_, v2_, v3_);
   11420             :          }
   11421             : 
   11422       19630 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11423             :          {
   11424       19630 :             return expression_node<T>::e_trinary;
   11425             :          }
   11426             : 
   11427             :       private:
   11428             : 
   11429             :          sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
   11430             :          sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
   11431             : 
   11432             :          const T& v0_;
   11433             :          const T& v1_;
   11434             :          const T& v2_;
   11435             :          const T& v3_;
   11436             :       };
   11437             : 
   11438             :       template <typename T, typename VarArgFunction>
   11439             :       class vararg_node exprtk_final : public expression_node<T>
   11440             :       {
   11441             :       public:
   11442             : 
   11443             :          typedef expression_node<T>* expression_ptr;
   11444             :          typedef std::pair<expression_ptr,bool> branch_t;
   11445             : 
   11446             :          template <typename Allocator,
   11447             :                    template <typename, typename> class Sequence>
   11448       37359 :          explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
   11449       37359 :          : initialised_(false)
   11450             :          {
   11451       37359 :             arg_list_.resize(arg_list.size());
   11452             : 
   11453      143683 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   11454             :             {
   11455      106324 :                if (arg_list[i] && arg_list[i]->valid())
   11456             :                {
   11457      106324 :                   construct_branch_pair(arg_list_[i],arg_list[i]);
   11458             :                }
   11459             :                else
   11460             :                {
   11461           0 :                   arg_list_.clear();
   11462           0 :                   return;
   11463             :                }
   11464             :             }
   11465             : 
   11466       37359 :             initialised_ = (arg_list_.size() == arg_list.size());
   11467       37359 :             assert(valid());
   11468           0 :          }
   11469             : 
   11470    10165508 :          inline T value() const exprtk_override
   11471             :          {
   11472    10165508 :             return VarArgFunction::process(arg_list_);
   11473             :          }
   11474             : 
   11475      187705 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11476             :          {
   11477      187705 :             return expression_node<T>::e_vararg;
   11478             :          }
   11479             : 
   11480       86798 :          inline bool valid() const exprtk_override
   11481             :          {
   11482       86798 :             return initialised_;
   11483             :          }
   11484             : 
   11485       37359 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   11486             :          {
   11487       37359 :             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
   11488       37359 :          }
   11489             : 
   11490       48210 :          std::size_t node_depth() const exprtk_override
   11491             :          {
   11492       48210 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
   11493             :          }
   11494             : 
   11495             :       private:
   11496             : 
   11497             :          std::vector<branch_t> arg_list_;
   11498             :          bool initialised_;
   11499             :       };
   11500             : 
   11501             :       template <typename T, typename VarArgFunction>
   11502             :       class vararg_varnode exprtk_final : public expression_node<T>
   11503             :       {
   11504             :       public:
   11505             : 
   11506             :          typedef expression_node<T>* expression_ptr;
   11507             : 
   11508             :          template <typename Allocator,
   11509             :                    template <typename, typename> class Sequence>
   11510        2308 :          explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
   11511        2308 :          : initialised_(false)
   11512             :          {
   11513        2308 :             arg_list_.resize(arg_list.size());
   11514             : 
   11515        7435 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   11516             :             {
   11517        5127 :                if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i]))
   11518             :                {
   11519        5127 :                   variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
   11520        5127 :                   arg_list_[i] = (&var_node_ptr->ref());
   11521             :                }
   11522             :                else
   11523             :                {
   11524           0 :                   arg_list_.clear();
   11525           0 :                   return;
   11526             :                }
   11527             :             }
   11528             : 
   11529        2308 :             initialised_ = (arg_list.size() == arg_list_.size());
   11530        2308 :             assert(valid());
   11531           0 :          }
   11532             : 
   11533        2308 :          inline T value() const exprtk_override
   11534             :          {
   11535        2308 :             return VarArgFunction::process(arg_list_);
   11536             :          }
   11537             : 
   11538       58623 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11539             :          {
   11540       58623 :             return expression_node<T>::e_vararg;
   11541             :          }
   11542             : 
   11543        8034 :          inline bool valid() const exprtk_override
   11544             :          {
   11545        8034 :             return initialised_;
   11546             :          }
   11547             : 
   11548             :       private:
   11549             : 
   11550             :          std::vector<const T*> arg_list_;
   11551             :          bool initialised_;
   11552             :       };
   11553             : 
   11554             :       template <typename T, typename VecFunction>
   11555             :       class vectorize_node exprtk_final : public expression_node<T>
   11556             :       {
   11557             :       public:
   11558             : 
   11559             :          typedef expression_node<T>* expression_ptr;
   11560             :          typedef std::pair<expression_ptr,bool> branch_t;
   11561             : 
   11562        1741 :          explicit vectorize_node(const expression_ptr v)
   11563        1741 :          : ivec_ptr_(0)
   11564             :          {
   11565        1741 :             construct_branch_pair(v_, v);
   11566             : 
   11567        1741 :             if (is_ivector_node(v_.first))
   11568             :             {
   11569        1741 :                ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
   11570             :             }
   11571        1741 :          }
   11572             : 
   11573        2060 :          inline T value() const exprtk_override
   11574             :          {
   11575        2060 :             v_.first->value();
   11576        2060 :             return VecFunction::process(ivec_ptr_);
   11577             :          }
   11578             : 
   11579       44298 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11580             :          {
   11581       44298 :             return expression_node<T>::e_vecfunc;
   11582             :          }
   11583             : 
   11584        3906 :          inline bool valid() const exprtk_override
   11585             :          {
   11586        3906 :             return ivec_ptr_ && v_.first && v_.first->valid();
   11587             :          }
   11588             : 
   11589        1741 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   11590             :          {
   11591        1741 :             expression_node<T>::ndb_t::collect(v_, node_delete_list);
   11592        1741 :          }
   11593             : 
   11594        3863 :          std::size_t node_depth() const exprtk_override
   11595             :          {
   11596        3863 :             return expression_node<T>::ndb_t::compute_node_depth(v_);
   11597             :          }
   11598             : 
   11599             :       private:
   11600             : 
   11601             :          vector_interface<T>* ivec_ptr_;
   11602             :          branch_t                    v_;
   11603             :       };
   11604             : 
   11605             :       template <typename T>
   11606             :       class assignment_node exprtk_final : public binary_node<T>
   11607             :       {
   11608             :       public:
   11609             : 
   11610             :          typedef expression_node<T>* expression_ptr;
   11611             :          using binary_node<T>::branch;
   11612             : 
   11613       27695 :          assignment_node(const operator_type& opr,
   11614             :                          expression_ptr branch0,
   11615             :                          expression_ptr branch1)
   11616             :          : binary_node<T>(opr, branch0, branch1)
   11617       27695 :          , var_node_ptr_(0)
   11618             :          {
   11619       27695 :             if (is_variable_node(branch(0)))
   11620             :             {
   11621       27695 :                var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
   11622             :             }
   11623       27695 :          }
   11624             : 
   11625    26750724 :          inline T value() const exprtk_override
   11626             :          {
   11627    26750724 :             T& result = var_node_ptr_->ref();
   11628    26750724 :                result = branch(1)->value();
   11629             : 
   11630    26750724 :             return result;
   11631             :          }
   11632             : 
   11633       61328 :          inline bool valid() const exprtk_override
   11634             :          {
   11635       61328 :             return var_node_ptr_ && binary_node<T>::valid();
   11636             :          }
   11637             : 
   11638             :       private:
   11639             : 
   11640             :          variable_node<T>* var_node_ptr_;
   11641             :       };
   11642             : 
   11643             :       template <typename T>
   11644             :       class assignment_vec_elem_node exprtk_final : public binary_node<T>
   11645             :       {
   11646             :       public:
   11647             : 
   11648             :          typedef expression_node<T>* expression_ptr;
   11649             :          using binary_node<T>::branch;
   11650             : 
   11651          83 :          assignment_vec_elem_node(const operator_type& opr,
   11652             :                                   expression_ptr branch0,
   11653             :                                   expression_ptr branch1)
   11654             :          : binary_node<T>(opr, branch0, branch1)
   11655          83 :          , vec_node_ptr_(0)
   11656             :          {
   11657          83 :             if (is_vector_elem_node(branch(0)))
   11658             :             {
   11659          83 :                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
   11660             :             }
   11661             : 
   11662          83 :             assert(valid());
   11663          83 :          }
   11664             : 
   11665    22850849 :          inline T value() const exprtk_override
   11666             :          {
   11667    22850849 :             T& result = vec_node_ptr_->ref();
   11668    22850849 :                result = branch(1)->value();
   11669             : 
   11670    22850849 :             return result;
   11671             :          }
   11672             : 
   11673         246 :          inline bool valid() const exprtk_override
   11674             :          {
   11675         246 :             return vec_node_ptr_ && binary_node<T>::valid();
   11676             :          }
   11677             : 
   11678             :       private:
   11679             : 
   11680             :          vector_elem_node<T>* vec_node_ptr_;
   11681             :       };
   11682             : 
   11683             :       template <typename T>
   11684             :       class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T>
   11685             :       {
   11686             :       public:
   11687             : 
   11688             :          typedef expression_node<T>* expression_ptr;
   11689             :          using binary_node<T>::branch;
   11690             : 
   11691          20 :          assignment_vec_elem_rtc_node(const operator_type& opr,
   11692             :                                       expression_ptr branch0,
   11693             :                                       expression_ptr branch1)
   11694             :          : binary_node<T>(opr, branch0, branch1)
   11695          20 :          , vec_node_ptr_(0)
   11696             :          {
   11697          20 :             if (is_vector_elem_rtc_node(branch(0)))
   11698             :             {
   11699          20 :                vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
   11700             :             }
   11701             : 
   11702          20 :             assert(valid());
   11703          20 :          }
   11704             : 
   11705         150 :          inline T value() const exprtk_override
   11706             :          {
   11707         150 :             T& result = vec_node_ptr_->ref();
   11708         150 :                result = branch(1)->value();
   11709             : 
   11710         150 :             return result;
   11711             :          }
   11712             : 
   11713          40 :          inline bool valid() const exprtk_override
   11714             :          {
   11715          40 :             return vec_node_ptr_ && binary_node<T>::valid();
   11716             :          }
   11717             : 
   11718             :       private:
   11719             : 
   11720             :          vector_elem_rtc_node<T>* vec_node_ptr_;
   11721             :       };
   11722             : 
   11723             :       template <typename T>
   11724             :       class assignment_rebasevec_elem_node exprtk_final : public binary_node<T>
   11725             :       {
   11726             :       public:
   11727             : 
   11728             :          typedef expression_node<T>* expression_ptr;
   11729             :          using expression_node<T>::branch;
   11730             : 
   11731           0 :          assignment_rebasevec_elem_node(const operator_type& opr,
   11732             :                                         expression_ptr branch0,
   11733             :                                         expression_ptr branch1)
   11734             :          : binary_node<T>(opr, branch0, branch1)
   11735           0 :          , rbvec_node_ptr_(0)
   11736             :          {
   11737           0 :             if (is_rebasevector_elem_node(branch(0)))
   11738             :             {
   11739           0 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
   11740             :             }
   11741             : 
   11742           0 :             assert(valid());
   11743           0 :          }
   11744             : 
   11745           0 :          inline T value() const exprtk_override
   11746             :          {
   11747           0 :             T& result = rbvec_node_ptr_->ref();
   11748           0 :                result = branch(1)->value();
   11749             : 
   11750           0 :             return result;
   11751             :          }
   11752             : 
   11753           0 :          inline bool valid() const exprtk_override
   11754             :          {
   11755           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   11756             :          }
   11757             : 
   11758             :       private:
   11759             : 
   11760             :          rebasevector_elem_node<T>* rbvec_node_ptr_;
   11761             :       };
   11762             : 
   11763             :       template <typename T>
   11764             :       class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T>
   11765             :       {
   11766             :       public:
   11767             : 
   11768             :          typedef expression_node<T>* expression_ptr;
   11769             :          using expression_node<T>::branch;
   11770             : 
   11771           0 :          assignment_rebasevec_elem_rtc_node(const operator_type& opr,
   11772             :                                         expression_ptr branch0,
   11773             :                                         expression_ptr branch1)
   11774             :          : binary_node<T>(opr, branch0, branch1)
   11775           0 :          , rbvec_node_ptr_(0)
   11776             :          {
   11777           0 :             if (is_rebasevector_elem_rtc_node(branch(0)))
   11778             :             {
   11779           0 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
   11780             :             }
   11781             : 
   11782           0 :             assert(valid());
   11783           0 :          }
   11784             : 
   11785           0 :          inline T value() const exprtk_override
   11786             :          {
   11787           0 :             T& result = rbvec_node_ptr_->ref();
   11788           0 :                result = branch(1)->value();
   11789             : 
   11790           0 :             return result;
   11791             :          }
   11792             : 
   11793           0 :          inline bool valid() const exprtk_override
   11794             :          {
   11795           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   11796             :          }
   11797             : 
   11798             :       private:
   11799             : 
   11800             :          rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
   11801             :       };
   11802             : 
   11803             :       template <typename T>
   11804             :       class assignment_rebasevec_celem_node exprtk_final : public binary_node<T>
   11805             :       {
   11806             :       public:
   11807             : 
   11808             :          typedef expression_node<T>* expression_ptr;
   11809             :          using binary_node<T>::branch;
   11810             : 
   11811           0 :          assignment_rebasevec_celem_node(const operator_type& opr,
   11812             :                                          expression_ptr branch0,
   11813             :                                          expression_ptr branch1)
   11814             :          : binary_node<T>(opr, branch0, branch1)
   11815           0 :          , rbvec_node_ptr_(0)
   11816             :          {
   11817           0 :             if (is_rebasevector_celem_node(branch(0)))
   11818             :             {
   11819           0 :                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
   11820             :             }
   11821             : 
   11822           0 :             assert(valid());
   11823           0 :          }
   11824             : 
   11825           0 :          inline T value() const exprtk_override
   11826             :          {
   11827           0 :             T& result = rbvec_node_ptr_->ref();
   11828           0 :                result = branch(1)->value();
   11829             : 
   11830           0 :             return result;
   11831             :          }
   11832             : 
   11833           0 :          inline bool valid() const exprtk_override
   11834             :          {
   11835           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   11836             :          }
   11837             : 
   11838             :       private:
   11839             : 
   11840             :          rebasevector_celem_node<T>* rbvec_node_ptr_;
   11841             :       };
   11842             : 
   11843             :       template <typename T>
   11844             :       class assignment_vec_node exprtk_final
   11845             :                                 : public binary_node     <T>
   11846             :                                 , public vector_interface<T>
   11847             :       {
   11848             :       public:
   11849             : 
   11850             :          typedef expression_node<T>* expression_ptr;
   11851             :          typedef vector_node<T>*     vector_node_ptr;
   11852             :          typedef vec_data_store<T>   vds_t;
   11853             : 
   11854             :          using binary_node<T>::branch;
   11855             : 
   11856         114 :          assignment_vec_node(const operator_type& opr,
   11857             :                              expression_ptr branch0,
   11858             :                              expression_ptr branch1)
   11859             :          : binary_node<T>(opr, branch0, branch1)
   11860         114 :          , vec_node_ptr_(0)
   11861             :          {
   11862         114 :             if (is_vector_node(branch(0)))
   11863             :             {
   11864         114 :                vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   11865         114 :                vds()         = vec_node_ptr_->vds();
   11866             :             }
   11867             : 
   11868         114 :             assert(valid());
   11869         114 :          }
   11870             : 
   11871         114 :          inline T value() const exprtk_override
   11872             :          {
   11873         114 :             const T v = branch(1)->value();
   11874             : 
   11875         114 :             T* vec = vds().data();
   11876             : 
   11877         114 :             loop_unroll::details lud(size());
   11878         114 :             const T* upper_bound = vec + lud.upper_bound;
   11879             : 
   11880         114 :             while (vec < upper_bound)
   11881             :             {
   11882             :                #define exprtk_loop(N) \
   11883             :                vec[N] = v;            \
   11884             : 
   11885           0 :                exprtk_loop( 0) exprtk_loop( 1)
   11886           0 :                exprtk_loop( 2) exprtk_loop( 3)
   11887             :                #ifndef exprtk_disable_superscalar_unroll
   11888           0 :                exprtk_loop( 4) exprtk_loop( 5)
   11889           0 :                exprtk_loop( 6) exprtk_loop( 7)
   11890           0 :                exprtk_loop( 8) exprtk_loop( 9)
   11891           0 :                exprtk_loop(10) exprtk_loop(11)
   11892           0 :                exprtk_loop(12) exprtk_loop(13)
   11893           0 :                exprtk_loop(14) exprtk_loop(15)
   11894             :                #endif
   11895             : 
   11896           0 :                vec += lud.batch_size;
   11897             :             }
   11898             : 
   11899         114 :             switch (lud.remainder)
   11900             :             {
   11901             :                #define case_stmt(N) \
   11902             :                case N : *vec++ = v; \
   11903             :                exprtk_fallthrough   \
   11904             : 
   11905             :                #ifndef exprtk_disable_superscalar_unroll
   11906           0 :                case_stmt(15) case_stmt(14)
   11907           0 :                case_stmt(13) case_stmt(12)
   11908           0 :                case_stmt(11) case_stmt(10)
   11909          93 :                case_stmt( 9) case_stmt( 8)
   11910          99 :                case_stmt( 7) case_stmt( 6)
   11911         105 :                case_stmt( 5) case_stmt( 4)
   11912             :                #endif
   11913         111 :                case_stmt( 3) case_stmt( 2)
   11914         114 :                case 1 : *vec++ = v;
   11915             :             }
   11916             : 
   11917             :             #undef exprtk_loop
   11918             :             #undef case_stmt
   11919             : 
   11920         228 :             return vec_node_ptr_->value();
   11921             :          }
   11922             : 
   11923           0 :          vector_node_ptr vec() const exprtk_override
   11924             :          {
   11925           0 :             return vec_node_ptr_;
   11926             :          }
   11927             : 
   11928           0 :          vector_node_ptr vec() exprtk_override
   11929             :          {
   11930           0 :             return vec_node_ptr_;
   11931             :          }
   11932             : 
   11933        1254 :          inline typename expression_node<T>::node_type type() const exprtk_override
   11934             :          {
   11935        1254 :             return expression_node<T>::e_vecvalass;
   11936             :          }
   11937             : 
   11938         342 :          inline bool valid() const exprtk_override
   11939             :          {
   11940             :             return
   11941         684 :                vec_node_ptr_ &&
   11942         684 :                (vds().size() <= vec_node_ptr_->vec_holder().base_size()) &&
   11943         684 :                binary_node<T>::valid();
   11944             :          }
   11945             : 
   11946         114 :          std::size_t size() const exprtk_override
   11947             :          {
   11948         114 :             return vec_node_ptr_->vec_holder().size();
   11949             :          }
   11950             : 
   11951           0 :          std::size_t base_size() const exprtk_override
   11952             :          {
   11953           0 :             return vec_node_ptr_->vec_holder().base_size();
   11954             :          }
   11955             : 
   11956         114 :          vds_t& vds() exprtk_override
   11957             :          {
   11958         114 :             return vds_;
   11959             :          }
   11960             : 
   11961         456 :          const vds_t& vds() const exprtk_override
   11962             :          {
   11963         456 :             return vds_;
   11964             :          }
   11965             : 
   11966             :       private:
   11967             : 
   11968             :          vector_node<T>* vec_node_ptr_;
   11969             :          vds_t           vds_;
   11970             :       };
   11971             : 
   11972             :       template <typename T>
   11973             :       class assignment_vecvec_node exprtk_final
   11974             :                                    : public binary_node     <T>
   11975             :                                    , public vector_interface<T>
   11976             :       {
   11977             :       public:
   11978             : 
   11979             :          typedef expression_node<T>* expression_ptr;
   11980             :          typedef vector_node<T>*     vector_node_ptr;
   11981             :          typedef vec_data_store<T>   vds_t;
   11982             : 
   11983             :          using binary_node<T>::branch;
   11984             : 
   11985        1156 :          assignment_vecvec_node(const operator_type& opr,
   11986             :                                 expression_ptr branch0,
   11987             :                                 expression_ptr branch1)
   11988             :          : binary_node<T>(opr, branch0, branch1)
   11989        1156 :          , vec0_node_ptr_(0)
   11990        1156 :          , vec1_node_ptr_(0)
   11991        1156 :          , initialised_(false)
   11992        1156 :          , src_is_ivec_(false)
   11993             :          {
   11994        1156 :             if (is_vector_node(branch(0)))
   11995             :             {
   11996        1156 :                vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   11997        1156 :                vds()          = vec0_node_ptr_->vds();
   11998             :             }
   11999             : 
   12000        1156 :             if (is_vector_node(branch(1)))
   12001             :             {
   12002         339 :                vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
   12003         339 :                vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
   12004             :             }
   12005         817 :             else if (is_ivector_node(branch(1)))
   12006             :             {
   12007         817 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   12008             : 
   12009         817 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   12010             :                {
   12011         817 :                   vec1_node_ptr_ = vi->vec();
   12012             : 
   12013         817 :                   if (!vi->side_effect())
   12014             :                   {
   12015         657 :                      vi->vds()    = vds();
   12016         657 :                      src_is_ivec_ = true;
   12017             :                   }
   12018             :                   else
   12019         160 :                      vds_t::match_sizes(vds(),vi->vds());
   12020             :                }
   12021             :             }
   12022             : 
   12023        1156 :             initialised_ =
   12024        2312 :                vec0_node_ptr_               &&
   12025        1156 :                vec1_node_ptr_               &&
   12026        1156 :                (size() <= base_size())      &&
   12027        3468 :                (vds_.size() <= base_size()) &&
   12028        1156 :                binary_node<T>::valid();
   12029             : 
   12030        1156 :             assert(valid());
   12031        1156 :          }
   12032             : 
   12033        1156 :          inline T value() const exprtk_override
   12034             :          {
   12035        1156 :             branch(1)->value();
   12036             : 
   12037        1156 :             if (src_is_ivec_)
   12038         657 :                return vec0_node_ptr_->value();
   12039             : 
   12040         499 :             T* vec0 = vec0_node_ptr_->vds().data();
   12041         499 :             T* vec1 = vec1_node_ptr_->vds().data();
   12042             : 
   12043         499 :             loop_unroll::details lud(size());
   12044         499 :             const T* upper_bound = vec0 + lud.upper_bound;
   12045             : 
   12046         499 :             while (vec0 < upper_bound)
   12047             :             {
   12048             :                #define exprtk_loop(N) \
   12049             :                vec0[N] = vec1[N];     \
   12050             : 
   12051           0 :                exprtk_loop( 0) exprtk_loop( 1)
   12052           0 :                exprtk_loop( 2) exprtk_loop( 3)
   12053             :                #ifndef exprtk_disable_superscalar_unroll
   12054           0 :                exprtk_loop( 4) exprtk_loop( 5)
   12055           0 :                exprtk_loop( 6) exprtk_loop( 7)
   12056           0 :                exprtk_loop( 8) exprtk_loop( 9)
   12057           0 :                exprtk_loop(10) exprtk_loop(11)
   12058           0 :                exprtk_loop(12) exprtk_loop(13)
   12059           0 :                exprtk_loop(14) exprtk_loop(15)
   12060             :                #endif
   12061             : 
   12062           0 :                vec0 += lud.batch_size;
   12063           0 :                vec1 += lud.batch_size;
   12064             :             }
   12065             : 
   12066         499 :             switch (lud.remainder)
   12067             :             {
   12068             :                #define case_stmt(N,fall_through) \
   12069             :                case N : *vec0++ = *vec1++;       \
   12070             :                fall_through                      \
   12071             : 
   12072             :                #ifndef exprtk_disable_superscalar_unroll
   12073           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   12074           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   12075           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   12076           2 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   12077           8 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   12078         159 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   12079             :                #endif
   12080         414 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   12081         499 :                case_stmt( 1, (void)0;)
   12082             :             }
   12083             : 
   12084             :             #undef exprtk_loop
   12085             :             #undef case_stmt
   12086             : 
   12087         499 :             return vec0_node_ptr_->value();
   12088             :          }
   12089             : 
   12090           0 :          vector_node_ptr vec() exprtk_override
   12091             :          {
   12092           0 :             return vec0_node_ptr_;
   12093             :          }
   12094             : 
   12095           0 :          vector_node_ptr vec() const exprtk_override
   12096             :          {
   12097           0 :             return vec0_node_ptr_;
   12098             :          }
   12099             : 
   12100       12758 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12101             :          {
   12102       12758 :             return expression_node<T>::e_vecvecass;
   12103             :          }
   12104             : 
   12105        3468 :          inline bool valid() const exprtk_override
   12106             :          {
   12107        3468 :             return initialised_;
   12108             :          }
   12109             : 
   12110        1655 :          std::size_t size() const exprtk_override
   12111             :          {
   12112        1655 :             return std::min(
   12113        1655 :                vec0_node_ptr_->vec_holder().size(),
   12114        3310 :                vec1_node_ptr_->vec_holder().size());
   12115             :          }
   12116             : 
   12117        2312 :          std::size_t base_size() const exprtk_override
   12118             :          {
   12119        2312 :             return std::min(
   12120        2312 :                vec0_node_ptr_->vec_holder().base_size(),
   12121        4624 :                vec1_node_ptr_->vec_holder().base_size());
   12122             :          }
   12123             : 
   12124        2312 :          vds_t& vds() exprtk_override
   12125             :          {
   12126        2312 :             return vds_;
   12127             :          }
   12128             : 
   12129           0 :          const vds_t& vds() const exprtk_override
   12130             :          {
   12131           0 :             return vds_;
   12132             :          }
   12133             : 
   12134             :       private:
   12135             : 
   12136             :          vector_node<T>* vec0_node_ptr_;
   12137             :          vector_node<T>* vec1_node_ptr_;
   12138             :          bool            initialised_;
   12139             :          bool            src_is_ivec_;
   12140             :          vds_t           vds_;
   12141             :       };
   12142             : 
   12143             :       template <typename T, typename Operation>
   12144             :       class assignment_op_node exprtk_final : public binary_node<T>
   12145             :       {
   12146             :       public:
   12147             : 
   12148             :          typedef expression_node<T>* expression_ptr;
   12149             :          using binary_node<T>::branch;
   12150             : 
   12151        4690 :          assignment_op_node(const operator_type& opr,
   12152             :                             expression_ptr branch0,
   12153             :                             expression_ptr branch1)
   12154             :          : binary_node<T>(opr, branch0, branch1)
   12155        4690 :          , var_node_ptr_(0)
   12156             :          {
   12157        4690 :             if (is_variable_node(branch(0)))
   12158             :             {
   12159        4690 :                var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
   12160             :             }
   12161             : 
   12162        4690 :             assert(valid());
   12163        4690 :          }
   12164             : 
   12165   158667892 :          inline T value() const exprtk_override
   12166             :          {
   12167   158667892 :             T& v = var_node_ptr_->ref();
   12168   158667892 :             v = Operation::process(v,branch(1)->value());
   12169             : 
   12170   158667892 :             return v;
   12171             :          }
   12172             : 
   12173       10755 :          inline bool valid() const exprtk_override
   12174             :          {
   12175       10755 :             return var_node_ptr_ && binary_node<T>::valid();
   12176             :          }
   12177             : 
   12178             :       private:
   12179             : 
   12180             :          variable_node<T>* var_node_ptr_;
   12181             :       };
   12182             : 
   12183             :       template <typename T, typename Operation>
   12184             :       class assignment_vec_elem_op_node exprtk_final : public binary_node<T>
   12185             :       {
   12186             :       public:
   12187             : 
   12188             :          typedef expression_node<T>* expression_ptr;
   12189             :          using binary_node<T>::branch;
   12190             : 
   12191         500 :          assignment_vec_elem_op_node(const operator_type& opr,
   12192             :                                      expression_ptr branch0,
   12193             :                                      expression_ptr branch1)
   12194             :          : binary_node<T>(opr, branch0, branch1)
   12195         500 :          , vec_node_ptr_(0)
   12196             :          {
   12197         500 :             if (is_vector_elem_node(branch(0)))
   12198             :             {
   12199         500 :                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
   12200             :             }
   12201             : 
   12202         500 :             assert(valid());
   12203         500 :          }
   12204             : 
   12205        1100 :          inline T value() const exprtk_override
   12206             :          {
   12207        1100 :             T& v = vec_node_ptr_->ref();
   12208        1100 :                v = Operation::process(v,branch(1)->value());
   12209             : 
   12210        1100 :             return v;
   12211             :          }
   12212             : 
   12213        1500 :          inline bool valid() const exprtk_override
   12214             :          {
   12215        1500 :             return vec_node_ptr_ && binary_node<T>::valid();
   12216             :          }
   12217             : 
   12218             :       private:
   12219             : 
   12220             :          vector_elem_node<T>* vec_node_ptr_;
   12221             :       };
   12222             : 
   12223             :       template <typename T, typename Operation>
   12224             :       class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T>
   12225             :       {
   12226             :       public:
   12227             : 
   12228             :          typedef expression_node<T>* expression_ptr;
   12229             :          using binary_node<T>::branch;
   12230             : 
   12231          12 :          assignment_vec_elem_op_rtc_node(const operator_type& opr,
   12232             :                                      expression_ptr branch0,
   12233             :                                      expression_ptr branch1)
   12234             :          : binary_node<T>(opr, branch0, branch1)
   12235          12 :          , vec_node_ptr_(0)
   12236             :          {
   12237          12 :             if (is_vector_elem_rtc_node(branch(0)))
   12238             :             {
   12239          12 :                vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
   12240             :             }
   12241             : 
   12242          12 :             assert(valid());
   12243          12 :          }
   12244             : 
   12245          18 :          inline T value() const exprtk_override
   12246             :          {
   12247          18 :             T& v = vec_node_ptr_->ref();
   12248          18 :                v = Operation::process(v,branch(1)->value());
   12249             : 
   12250          18 :             return v;
   12251             :          }
   12252             : 
   12253          46 :          inline bool valid() const exprtk_override
   12254             :          {
   12255          46 :             return vec_node_ptr_ && binary_node<T>::valid();
   12256             :          }
   12257             : 
   12258             :       private:
   12259             : 
   12260             :          vector_elem_rtc_node<T>* vec_node_ptr_;
   12261             :       };
   12262             : 
   12263             :       template <typename T, typename Operation>
   12264             :       class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T>
   12265             :       {
   12266             :       public:
   12267             : 
   12268             :          typedef expression_node<T>* expression_ptr;
   12269             :          using binary_node<T>::branch;
   12270             : 
   12271           0 :          assignment_vec_celem_op_rtc_node(const operator_type& opr,
   12272             :                                      expression_ptr branch0,
   12273             :                                      expression_ptr branch1)
   12274             :          : binary_node<T>(opr, branch0, branch1)
   12275           0 :          , vec_node_ptr_(0)
   12276             :          {
   12277           0 :             if (is_vector_celem_rtc_node(branch(0)))
   12278             :             {
   12279           0 :                vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0));
   12280             :             }
   12281             : 
   12282           0 :             assert(valid());
   12283           0 :          }
   12284             : 
   12285           0 :          inline T value() const exprtk_override
   12286             :          {
   12287           0 :             T& v = vec_node_ptr_->ref();
   12288           0 :                v = Operation::process(v,branch(1)->value());
   12289             : 
   12290           0 :             return v;
   12291             :          }
   12292             : 
   12293           0 :          inline bool valid() const exprtk_override
   12294             :          {
   12295           0 :             return vec_node_ptr_ && binary_node<T>::valid();
   12296             :          }
   12297             : 
   12298             :       private:
   12299             : 
   12300             :          vector_celem_rtc_node<T>* vec_node_ptr_;
   12301             :       };
   12302             : 
   12303             :       template <typename T, typename Operation>
   12304             :       class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T>
   12305             :       {
   12306             :       public:
   12307             : 
   12308             :          typedef expression_node<T>* expression_ptr;
   12309             :          using binary_node<T>::branch;
   12310             : 
   12311         300 :          assignment_rebasevec_elem_op_node(const operator_type& opr,
   12312             :                                            expression_ptr branch0,
   12313             :                                            expression_ptr branch1)
   12314             :          : binary_node<T>(opr, branch0, branch1)
   12315         300 :          , rbvec_node_ptr_(0)
   12316             :          {
   12317         300 :             if (is_rebasevector_elem_node(branch(0)))
   12318             :             {
   12319         300 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
   12320             :             }
   12321             : 
   12322         300 :             assert(valid());
   12323         300 :          }
   12324             : 
   12325         300 :          inline T value() const exprtk_override
   12326             :          {
   12327         300 :             T& v = rbvec_node_ptr_->ref();
   12328         300 :                v = Operation::process(v,branch(1)->value());
   12329             : 
   12330         300 :             return v;
   12331             :          }
   12332             : 
   12333         900 :          inline bool valid() const exprtk_override
   12334             :          {
   12335         900 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12336             :          }
   12337             : 
   12338             :       private:
   12339             : 
   12340             :          rebasevector_elem_node<T>* rbvec_node_ptr_;
   12341             :       };
   12342             : 
   12343             :       template <typename T, typename Operation>
   12344             :       class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T>
   12345             :       {
   12346             :       public:
   12347             : 
   12348             :          typedef expression_node<T>* expression_ptr;
   12349             :          using binary_node<T>::branch;
   12350             : 
   12351         300 :          assignment_rebasevec_celem_op_node(const operator_type& opr,
   12352             :                                             expression_ptr branch0,
   12353             :                                             expression_ptr branch1)
   12354             :          : binary_node<T>(opr, branch0, branch1)
   12355         300 :          , rbvec_node_ptr_(0)
   12356             :          {
   12357         300 :             if (is_rebasevector_celem_node(branch(0)))
   12358             :             {
   12359         300 :                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
   12360             :             }
   12361             : 
   12362         300 :             assert(valid());
   12363         300 :          }
   12364             : 
   12365         300 :          inline T value() const exprtk_override
   12366             :          {
   12367         300 :             T& v = rbvec_node_ptr_->ref();
   12368         300 :                v = Operation::process(v,branch(1)->value());
   12369             : 
   12370         300 :             return v;
   12371             :          }
   12372             : 
   12373         900 :          inline bool valid() const exprtk_override
   12374             :          {
   12375         900 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12376             :          }
   12377             : 
   12378             :       private:
   12379             : 
   12380             :          rebasevector_celem_node<T>* rbvec_node_ptr_;
   12381             :       };
   12382             : 
   12383             :       template <typename T, typename Operation>
   12384             :       class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T>
   12385             :       {
   12386             :       public:
   12387             : 
   12388             :          typedef expression_node<T>* expression_ptr;
   12389             :          using binary_node<T>::branch;
   12390             : 
   12391           0 :          assignment_rebasevec_elem_op_rtc_node(const operator_type& opr,
   12392             :                                            expression_ptr branch0,
   12393             :                                            expression_ptr branch1)
   12394             :          : binary_node<T>(opr, branch0, branch1)
   12395           0 :          , rbvec_node_ptr_(0)
   12396             :          {
   12397           0 :             if (is_rebasevector_elem_rtc_node(branch(0)))
   12398             :             {
   12399           0 :                rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
   12400             :             }
   12401             : 
   12402           0 :             assert(valid());
   12403           0 :          }
   12404             : 
   12405           0 :          inline T value() const exprtk_override
   12406             :          {
   12407           0 :             T& v = rbvec_node_ptr_->ref();
   12408           0 :                v = Operation::process(v,branch(1)->value());
   12409             : 
   12410           0 :             return v;
   12411             :          }
   12412             : 
   12413           0 :          inline bool valid() const exprtk_override
   12414             :          {
   12415           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12416             :          }
   12417             : 
   12418             :       private:
   12419             : 
   12420             :          rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
   12421             :       };
   12422             : 
   12423             :       template <typename T, typename Operation>
   12424             :       class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T>
   12425             :       {
   12426             :       public:
   12427             : 
   12428             :          typedef expression_node<T>* expression_ptr;
   12429             :          using binary_node<T>::branch;
   12430             : 
   12431           0 :          assignment_rebasevec_celem_op_rtc_node(const operator_type& opr,
   12432             :                                             expression_ptr branch0,
   12433             :                                             expression_ptr branch1)
   12434             :          : binary_node<T>(opr, branch0, branch1)
   12435           0 :          , rbvec_node_ptr_(0)
   12436             :          {
   12437           0 :             if (is_rebasevector_celem_rtc_node(branch(0)))
   12438             :             {
   12439           0 :                rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0));
   12440             :             }
   12441             : 
   12442           0 :             assert(valid());
   12443           0 :          }
   12444             : 
   12445           0 :          inline T value() const exprtk_override
   12446             :          {
   12447           0 :             T& v = rbvec_node_ptr_->ref();
   12448           0 :                v = Operation::process(v,branch(1)->value());
   12449             : 
   12450           0 :             return v;
   12451             :          }
   12452             : 
   12453           0 :          inline bool valid() const exprtk_override
   12454             :          {
   12455           0 :             return rbvec_node_ptr_ && binary_node<T>::valid();
   12456             :          }
   12457             : 
   12458             :       private:
   12459             : 
   12460             :          rebasevector_celem_rtc_node<T>* rbvec_node_ptr_;
   12461             :       };
   12462             : 
   12463             :       template <typename T, typename Operation>
   12464             :       class assignment_vec_op_node exprtk_final
   12465             :                                    : public binary_node     <T>
   12466             :                                    , public vector_interface<T>
   12467             :       {
   12468             :       public:
   12469             : 
   12470             :          typedef expression_node<T>* expression_ptr;
   12471             :          typedef vector_node<T>*     vector_node_ptr;
   12472             :          typedef vec_data_store<T>   vds_t;
   12473             : 
   12474             :          using binary_node<T>::branch;
   12475             : 
   12476        2462 :          assignment_vec_op_node(const operator_type& opr,
   12477             :                                 expression_ptr branch0,
   12478             :                                 expression_ptr branch1)
   12479             :          : binary_node<T>(opr, branch0, branch1)
   12480        2462 :          , vec_node_ptr_(0)
   12481             :          {
   12482        2462 :             if (is_vector_node(branch(0)))
   12483             :             {
   12484        2462 :                vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   12485        2462 :                vds()         = vec_node_ptr_->vds();
   12486             :             }
   12487             : 
   12488        2462 :             assert(valid());
   12489        2462 :          }
   12490             : 
   12491        2489 :          inline T value() const exprtk_override
   12492             :          {
   12493        2489 :             const T v = branch(1)->value();
   12494             : 
   12495        2489 :             T* vec = vds().data();
   12496             : 
   12497        2489 :             loop_unroll::details lud(size());
   12498        2489 :             const T* upper_bound = vec + lud.upper_bound;
   12499             : 
   12500        2489 :             while (vec < upper_bound)
   12501             :             {
   12502             :                #define exprtk_loop(N)       \
   12503             :                Operation::assign(vec[N],v); \
   12504             : 
   12505           0 :                exprtk_loop( 0) exprtk_loop( 1)
   12506           0 :                exprtk_loop( 2) exprtk_loop( 3)
   12507             :                #ifndef exprtk_disable_superscalar_unroll
   12508           0 :                exprtk_loop( 4) exprtk_loop( 5)
   12509           0 :                exprtk_loop( 6) exprtk_loop( 7)
   12510           0 :                exprtk_loop( 8) exprtk_loop( 9)
   12511           0 :                exprtk_loop(10) exprtk_loop(11)
   12512           0 :                exprtk_loop(12) exprtk_loop(13)
   12513           0 :                exprtk_loop(14) exprtk_loop(15)
   12514             :                #endif
   12515             : 
   12516           0 :                vec += lud.batch_size;
   12517             :             }
   12518             : 
   12519        2489 :             switch (lud.remainder)
   12520             :             {
   12521             :                #define case_stmt(N,fall_through)     \
   12522             :                case N : Operation::assign(*vec++,v); \
   12523             :                fall_through                          \
   12524             : 
   12525             :                #ifndef exprtk_disable_superscalar_unroll
   12526           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   12527           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   12528           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   12529          18 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   12530          28 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   12531         308 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   12532             :                #endif
   12533        2164 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   12534        2489 :                case_stmt( 1, (void)0;)
   12535             :             }
   12536             : 
   12537             :             #undef exprtk_loop
   12538             :             #undef case_stmt
   12539             : 
   12540        4978 :             return vec_node_ptr_->value();
   12541             :          }
   12542             : 
   12543           0 :          vector_node_ptr vec() const exprtk_override
   12544             :          {
   12545           0 :             return vec_node_ptr_;
   12546             :          }
   12547             : 
   12548        2152 :          vector_node_ptr vec() exprtk_override
   12549             :          {
   12550        2152 :             return vec_node_ptr_;
   12551             :          }
   12552             : 
   12553       41403 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12554             :          {
   12555       41403 :             return expression_node<T>::e_vecopvalass;
   12556             :          }
   12557             : 
   12558       11793 :          inline bool valid() const exprtk_override
   12559             :          {
   12560             :             return
   12561       23586 :                vec_node_ptr_           &&
   12562       23586 :                (size() <= base_size()) &&
   12563       23586 :                binary_node<T>::valid() ;
   12564             :          }
   12565             : 
   12566       14327 :          std::size_t size() const exprtk_override
   12567             :          {
   12568       14327 :             return vec_node_ptr_->vec_holder().size();
   12569             :          }
   12570             : 
   12571       11793 :          std::size_t base_size() const exprtk_override
   12572             :          {
   12573       11793 :             return vec_node_ptr_->vec_holder().base_size();
   12574             :          }
   12575             : 
   12576        3289 :          vds_t& vds() exprtk_override
   12577             :          {
   12578        3289 :             return vds_;
   12579             :          }
   12580             : 
   12581        2489 :          const vds_t& vds() const exprtk_override
   12582             :          {
   12583        2489 :             return vds_;
   12584             :          }
   12585             : 
   12586         160 :          bool side_effect() const exprtk_override
   12587             :          {
   12588         160 :             return true;
   12589             :          }
   12590             : 
   12591             :       private:
   12592             : 
   12593             :          vector_node<T>* vec_node_ptr_;
   12594             :          vds_t           vds_;
   12595             :       };
   12596             : 
   12597             :       template <typename T, typename Operation>
   12598             :       class assignment_vecvec_op_node exprtk_final
   12599             :                                       : public binary_node     <T>
   12600             :                                       , public vector_interface<T>
   12601             :       {
   12602             :       public:
   12603             : 
   12604             :          typedef expression_node<T>* expression_ptr;
   12605             :          typedef vector_node<T>*     vector_node_ptr;
   12606             :          typedef vec_data_store<T>   vds_t;
   12607             : 
   12608             :          using binary_node<T>::branch;
   12609             : 
   12610         721 :          assignment_vecvec_op_node(const operator_type& opr,
   12611             :                                    expression_ptr branch0,
   12612             :                                    expression_ptr branch1)
   12613             :          : binary_node<T>(opr, branch0, branch1)
   12614         721 :          , vec0_node_ptr_(0)
   12615         721 :          , vec1_node_ptr_(0)
   12616         721 :          , initialised_(false)
   12617             :          {
   12618         721 :             if (is_vector_node(branch(0)))
   12619             :             {
   12620         721 :                vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
   12621         721 :                vds()          = vec0_node_ptr_->vds();
   12622             :             }
   12623             : 
   12624         721 :             if (is_vector_node(branch(1)))
   12625             :             {
   12626         320 :                vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
   12627         320 :                vec1_node_ptr_->vds() = vds();
   12628             :             }
   12629         401 :             else if (is_ivector_node(branch(1)))
   12630             :             {
   12631         401 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   12632             : 
   12633         401 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   12634             :                {
   12635         401 :                   vec1_node_ptr_ = vi->vec();
   12636         401 :                   vec1_node_ptr_->vds() = vi->vds();
   12637             :                }
   12638             :                else
   12639           0 :                   vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
   12640             :             }
   12641             : 
   12642         721 :             initialised_ =
   12643        1442 :                vec0_node_ptr_          &&
   12644         721 :                vec1_node_ptr_          &&
   12645        2163 :                (size() <= base_size()) &&
   12646         721 :                binary_node<T>::valid();
   12647             : 
   12648         721 :             assert(valid());
   12649         721 :          }
   12650             : 
   12651         721 :          inline T value() const exprtk_override
   12652             :          {
   12653         721 :             branch(0)->value();
   12654         721 :             branch(1)->value();
   12655             : 
   12656         721 :                   T* vec0 = vec0_node_ptr_->vds().data();
   12657         721 :             const T* vec1 = vec1_node_ptr_->vds().data();
   12658             : 
   12659         721 :             loop_unroll::details lud(size());
   12660         721 :             const T* upper_bound = vec0 + lud.upper_bound;
   12661             : 
   12662         721 :             while (vec0 < upper_bound)
   12663             :             {
   12664             :                #define exprtk_loop(N)                          \
   12665             :                vec0[N] = Operation::process(vec0[N], vec1[N]); \
   12666             : 
   12667           0 :                exprtk_loop( 0) exprtk_loop( 1)
   12668           0 :                exprtk_loop( 2) exprtk_loop( 3)
   12669             :                #ifndef exprtk_disable_superscalar_unroll
   12670           0 :                exprtk_loop( 4) exprtk_loop( 5)
   12671           0 :                exprtk_loop( 6) exprtk_loop( 7)
   12672           0 :                exprtk_loop( 8) exprtk_loop( 9)
   12673           0 :                exprtk_loop(10) exprtk_loop(11)
   12674           0 :                exprtk_loop(12) exprtk_loop(13)
   12675           0 :                exprtk_loop(14) exprtk_loop(15)
   12676             :                #endif
   12677             : 
   12678           0 :                vec0 += lud.batch_size;
   12679           0 :                vec1 += lud.batch_size;
   12680             :             }
   12681             : 
   12682         721 :             int i = 0;
   12683             : 
   12684         721 :             switch (lud.remainder)
   12685             :             {
   12686             :                #define case_stmt(N,fall_through)                                 \
   12687             :                case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
   12688             :                fall_through                                                      \
   12689             : 
   12690             :                #ifndef exprtk_disable_superscalar_unroll
   12691           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   12692           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   12693           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   12694          18 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   12695          18 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   12696          63 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   12697             :                #endif
   12698         601 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   12699         721 :                case_stmt( 1, (void)0;)
   12700             :             }
   12701             : 
   12702             :             #undef exprtk_loop
   12703             :             #undef case_stmt
   12704             : 
   12705        1442 :             return vec0_node_ptr_->value();
   12706             :          }
   12707             : 
   12708           0 :          vector_node_ptr vec() const exprtk_override
   12709             :          {
   12710           0 :             return vec0_node_ptr_;
   12711             :          }
   12712             : 
   12713           0 :          vector_node_ptr vec() exprtk_override
   12714             :          {
   12715           0 :             return vec0_node_ptr_;
   12716             :          }
   12717             : 
   12718        7931 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12719             :          {
   12720        7931 :             return expression_node<T>::e_vecopvecass;
   12721             :          }
   12722             : 
   12723        2163 :          inline bool valid() const exprtk_override
   12724             :          {
   12725        2163 :             return initialised_;
   12726             :          }
   12727             : 
   12728        1442 :          std::size_t size() const exprtk_override
   12729             :          {
   12730        1442 :             return std::min(
   12731        1442 :                vec0_node_ptr_->vec_holder().size(),
   12732        2884 :                vec1_node_ptr_->vec_holder().size());
   12733             :          }
   12734             : 
   12735         721 :          std::size_t base_size() const exprtk_override
   12736             :          {
   12737         721 :             return std::min(
   12738         721 :                vec0_node_ptr_->vec_holder().base_size(),
   12739        1442 :                vec1_node_ptr_->vec_holder().base_size());
   12740             :          }
   12741             : 
   12742        1041 :          vds_t& vds() exprtk_override
   12743             :          {
   12744        1041 :             return vds_;
   12745             :          }
   12746             : 
   12747           0 :          const vds_t& vds() const exprtk_override
   12748             :          {
   12749           0 :             return vds_;
   12750             :          }
   12751             : 
   12752           0 :          bool side_effect() const exprtk_override
   12753             :          {
   12754           0 :             return true;
   12755             :          }
   12756             : 
   12757             :       private:
   12758             : 
   12759             :          vector_node<T>* vec0_node_ptr_;
   12760             :          vector_node<T>* vec1_node_ptr_;
   12761             :          bool            initialised_;
   12762             :          vds_t           vds_;
   12763             :       };
   12764             : 
   12765             :       template <typename T>
   12766             :       struct memory_context_t
   12767             :       {
   12768             :          typedef vector_node<T>*  vector_node_ptr;
   12769             :          typedef vector_holder<T> vector_holder_t;
   12770             :          typedef vector_holder_t* vector_holder_ptr;
   12771             : 
   12772       31858 :          memory_context_t()
   12773       31858 :          : temp_(0)
   12774       31858 :          , temp_vec_node_(0)
   12775       31858 :          {}
   12776             : 
   12777       15929 :          void clear()
   12778             :          {
   12779       15929 :             delete temp_vec_node_;
   12780       15929 :             delete temp_;
   12781       15929 :          }
   12782             : 
   12783             :          vector_holder_ptr temp_;
   12784             :          vector_node_ptr   temp_vec_node_;
   12785             :       };
   12786             : 
   12787             :       template <typename T>
   12788        6721 :       inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder,
   12789             :                                                      vec_data_store<T>& vds)
   12790             :       {
   12791        6721 :          memory_context_t<T> result_ctxt;
   12792       13442 :          result_ctxt.temp_  = (vec_holder.rebaseable()) ?
   12793         359 :                               new vector_holder<T>(vec_holder,vds) :
   12794        6362 :                               new vector_holder<T>(vds) ;
   12795        6721 :          result_ctxt.temp_vec_node_ = new vector_node  <T>(vds,result_ctxt.temp_);
   12796        6721 :          return result_ctxt;
   12797             :       }
   12798             : 
   12799             :       template <typename T>
   12800        9208 :       inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0,
   12801             :                                                      vector_holder<T>& vec_holder1,
   12802             :                                                      vec_data_store<T>& vds)
   12803             :       {
   12804        9208 :          memory_context_t<T> result_ctxt;
   12805             : 
   12806        9208 :          if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable())
   12807        9089 :             result_ctxt.temp_ = new vector_holder<T>(vds);
   12808         119 :          else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable())
   12809          17 :             result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds);
   12810         102 :          else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable())
   12811          27 :             result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds);
   12812             :          else
   12813             :          {
   12814         150 :             result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ?
   12815          75 :                                 new vector_holder<T>(vec_holder0, vds) :
   12816           0 :                                 new vector_holder<T>(vec_holder1, vds) ;
   12817             :          }
   12818             : 
   12819        9208 :          result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_);
   12820        9208 :          return result_ctxt;
   12821             :       }
   12822             : 
   12823             :       template <typename T, typename Operation>
   12824             :       class vec_binop_vecvec_node exprtk_final
   12825             :                                   : public binary_node     <T>
   12826             :                                   , public vector_interface<T>
   12827             :       {
   12828             :       public:
   12829             : 
   12830             :          typedef expression_node<T>* expression_ptr;
   12831             :          typedef vector_node<T>*     vector_node_ptr;
   12832             :          typedef vector_holder<T>    vector_holder_t;
   12833             :          typedef vector_holder_t*    vector_holder_ptr;
   12834             :          typedef vec_data_store<T>   vds_t;
   12835             :          typedef memory_context_t<T> memory_context;
   12836             : 
   12837             :          using binary_node<T>::branch;
   12838             : 
   12839        8440 :          vec_binop_vecvec_node(const operator_type& opr,
   12840             :                                expression_ptr branch0,
   12841             :                                expression_ptr branch1)
   12842             :          : binary_node<T>(opr, branch0, branch1)
   12843        8440 :          , vec0_node_ptr_(0)
   12844        8440 :          , vec1_node_ptr_(0)
   12845        8440 :          , initialised_(false)
   12846             :          {
   12847        8440 :             bool v0_is_ivec = false;
   12848        8440 :             bool v1_is_ivec = false;
   12849             : 
   12850        8440 :             if (is_vector_node(branch(0)))
   12851             :             {
   12852        6156 :                vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
   12853             :             }
   12854        2284 :             else if (is_ivector_node(branch(0)))
   12855             :             {
   12856        2284 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   12857             : 
   12858        2284 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
   12859             :                {
   12860        2284 :                   vec0_node_ptr_ = vi->vec();
   12861        2284 :                   v0_is_ivec     = true;
   12862             :                }
   12863             :             }
   12864             : 
   12865        8440 :             if (is_vector_node(branch(1)))
   12866             :             {
   12867        6118 :                vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
   12868             :             }
   12869        2322 :             else if (is_ivector_node(branch(1)))
   12870             :             {
   12871        2322 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   12872             : 
   12873        2322 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   12874             :                {
   12875        2322 :                   vec1_node_ptr_ = vi->vec();
   12876        2322 :                   v1_is_ivec     = true;
   12877             :                }
   12878             :             }
   12879             : 
   12880        8440 :             if (vec0_node_ptr_ && vec1_node_ptr_)
   12881             :             {
   12882        8440 :                vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
   12883        8440 :                vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
   12884             : 
   12885        8440 :                if (v0_is_ivec && (vec0.base_size() <= vec1.base_size()))
   12886             :                {
   12887        1995 :                   vds_ = vds_t(vec0_node_ptr_->vds());
   12888             :                }
   12889        6445 :                else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size()))
   12890             :                {
   12891         828 :                   vds_ = vds_t(vec1_node_ptr_->vds());
   12892             :                }
   12893             :                else
   12894             :                {
   12895        5617 :                   vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size()));
   12896             :                }
   12897             : 
   12898        8440 :                memory_context_ = make_memory_context(vec0, vec1, vds());
   12899             : 
   12900        8440 :                initialised_ =
   12901       16880 :                   (size() <= base_size()) &&
   12902        8440 :                   binary_node<T>::valid();
   12903             :             }
   12904             : 
   12905        8440 :             assert(valid());
   12906        8440 :          }
   12907             : 
   12908       16880 :         ~vec_binop_vecvec_node()
   12909             :          {
   12910        8440 :             memory_context_.clear();
   12911       16880 :          }
   12912             : 
   12913        8904 :          inline T value() const exprtk_override
   12914             :          {
   12915        8904 :             branch(0)->value();
   12916        8904 :             branch(1)->value();
   12917             : 
   12918        8904 :             const T* vec0 = vec0_node_ptr_->vds().data();
   12919        8904 :             const T* vec1 = vec1_node_ptr_->vds().data();
   12920        8904 :                   T* vec2 = vds().data();
   12921             : 
   12922        8904 :             loop_unroll::details lud(size());
   12923        8904 :             const T* upper_bound = vec2 + lud.upper_bound;
   12924             : 
   12925    25477654 :             while (vec2 < upper_bound)
   12926             :             {
   12927             :                #define exprtk_loop(N)                          \
   12928             :                vec2[N] = Operation::process(vec0[N], vec1[N]); \
   12929             : 
   12930    25468750 :                exprtk_loop( 0) exprtk_loop( 1)
   12931    25468750 :                exprtk_loop( 2) exprtk_loop( 3)
   12932             :                #ifndef exprtk_disable_superscalar_unroll
   12933    25468750 :                exprtk_loop( 4) exprtk_loop( 5)
   12934    25468750 :                exprtk_loop( 6) exprtk_loop( 7)
   12935    25468750 :                exprtk_loop( 8) exprtk_loop( 9)
   12936    25468750 :                exprtk_loop(10) exprtk_loop(11)
   12937    25468750 :                exprtk_loop(12) exprtk_loop(13)
   12938    25468750 :                exprtk_loop(14) exprtk_loop(15)
   12939             :                #endif
   12940             : 
   12941    25468750 :                vec0 += lud.batch_size;
   12942    25468750 :                vec1 += lud.batch_size;
   12943    25468750 :                vec2 += lud.batch_size;
   12944             :             }
   12945             : 
   12946        8904 :             int i = 0;
   12947             : 
   12948        8904 :             switch (lud.remainder)
   12949             :             {
   12950             :                #define case_stmt(N)                                              \
   12951             :                case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
   12952             :                exprtk_fallthrough                                                \
   12953             : 
   12954             :                #ifndef exprtk_disable_superscalar_unroll
   12955           0 :                case_stmt(15) case_stmt(14)
   12956           0 :                case_stmt(13) case_stmt(12)
   12957           0 :                case_stmt(11) case_stmt(10)
   12958         370 :                case_stmt( 9) case_stmt( 8)
   12959         379 :                case_stmt( 7) case_stmt( 6)
   12960        2570 :                case_stmt( 5) case_stmt( 4)
   12961             :                #endif
   12962        7704 :                case_stmt( 3) case_stmt( 2)
   12963        8429 :                case_stmt( 1)
   12964        8904 :                default: break;
   12965             :             }
   12966             : 
   12967             :             #undef exprtk_loop
   12968             :             #undef case_stmt
   12969             : 
   12970       17808 :             return (vds().data())[0];
   12971             :          }
   12972             : 
   12973           0 :          vector_node_ptr vec() const exprtk_override
   12974             :          {
   12975           0 :             return memory_context_.temp_vec_node_;
   12976             :          }
   12977             : 
   12978        4396 :          vector_node_ptr vec() exprtk_override
   12979             :          {
   12980        4396 :             return memory_context_.temp_vec_node_;
   12981             :          }
   12982             : 
   12983       72408 :          inline typename expression_node<T>::node_type type() const exprtk_override
   12984             :          {
   12985       72408 :             return expression_node<T>::e_vecvecarith;
   12986             :          }
   12987             : 
   12988       30981 :          inline bool valid() const exprtk_override
   12989             :          {
   12990       30981 :             return initialised_;
   12991             :          }
   12992             : 
   12993       18387 :          std::size_t size() const exprtk_override
   12994             :          {
   12995       18387 :             return std::min(
   12996       18387 :                vec0_node_ptr_->vec_holder().size(),
   12997       36774 :                vec1_node_ptr_->vec_holder().size());
   12998             :          }
   12999             : 
   13000        8440 :          std::size_t base_size() const exprtk_override
   13001             :          {
   13002        8440 :             return std::min(
   13003        8440 :                vec0_node_ptr_->vec_holder().base_size(),
   13004       16880 :                vec1_node_ptr_->vec_holder().base_size());
   13005             :          }
   13006             : 
   13007        9566 :          vds_t& vds() exprtk_override
   13008             :          {
   13009        9566 :             return vds_;
   13010             :          }
   13011             : 
   13012       17808 :          const vds_t& vds() const exprtk_override
   13013             :          {
   13014       17808 :             return vds_;
   13015             :          }
   13016             : 
   13017             :       private:
   13018             : 
   13019             :          vector_node_ptr vec0_node_ptr_;
   13020             :          vector_node_ptr vec1_node_ptr_;
   13021             :          bool            initialised_;
   13022             :          vds_t           vds_;
   13023             :          memory_context  memory_context_;
   13024             :       };
   13025             : 
   13026             :       template <typename T, typename Operation>
   13027             :       class vec_binop_vecval_node exprtk_final
   13028             :                                   : public binary_node     <T>
   13029             :                                   , public vector_interface<T>
   13030             :       {
   13031             :       public:
   13032             : 
   13033             :          typedef expression_node<T>* expression_ptr;
   13034             :          typedef vector_node<T>*     vector_node_ptr;
   13035             :          typedef vector_holder<T>    vector_holder_t;
   13036             :          typedef vector_holder_t*    vector_holder_ptr;
   13037             :          typedef vec_data_store<T>   vds_t;
   13038             :          typedef memory_context_t<T> memory_context;
   13039             : 
   13040             :          using binary_node<T>::branch;
   13041             : 
   13042        2604 :          vec_binop_vecval_node(const operator_type& opr,
   13043             :                                expression_ptr branch0,
   13044             :                                expression_ptr branch1)
   13045             :          : binary_node<T>(opr, branch0, branch1)
   13046        2604 :          , vec0_node_ptr_(0)
   13047             :          {
   13048        2604 :             bool v0_is_ivec = false;
   13049             : 
   13050        2604 :             if (is_vector_node(branch(0)))
   13051             :             {
   13052        1239 :                vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
   13053             :             }
   13054        1365 :             else if (is_ivector_node(branch(0)))
   13055             :             {
   13056        1365 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13057             : 
   13058        1365 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
   13059             :                {
   13060        1365 :                   vec0_node_ptr_ = vi->vec();
   13061        1365 :                   v0_is_ivec     = true;
   13062             :                }
   13063             :             }
   13064             : 
   13065        2604 :             if (vec0_node_ptr_)
   13066             :             {
   13067        2604 :                if (v0_is_ivec)
   13068        1365 :                   vds() = vec0_node_ptr_->vds();
   13069             :                else
   13070        1239 :                   vds() = vds_t(vec0_node_ptr_->base_size());
   13071             : 
   13072        2604 :                memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
   13073             :             }
   13074             : 
   13075        2604 :             assert(valid());
   13076        2604 :          }
   13077             : 
   13078        5208 :         ~vec_binop_vecval_node()
   13079             :          {
   13080        2604 :             memory_context_.clear();
   13081        5208 :          }
   13082             : 
   13083        3695 :          inline T value() const exprtk_override
   13084             :          {
   13085        3695 :                         branch(0)->value();
   13086        3695 :             const T v = branch(1)->value();
   13087             : 
   13088        3695 :             const T* vec0 = vec0_node_ptr_->vds().data();
   13089        3695 :                   T* vec1 = vds().data();
   13090             : 
   13091        3695 :             loop_unroll::details lud(size());
   13092        3695 :             const T* upper_bound = vec0 + lud.upper_bound;
   13093             : 
   13094    25659945 :             while (vec0 < upper_bound)
   13095             :             {
   13096             :                #define exprtk_loop(N)                    \
   13097             :                vec1[N] = Operation::process(vec0[N], v); \
   13098             : 
   13099    25656250 :                exprtk_loop( 0) exprtk_loop( 1)
   13100    25656250 :                exprtk_loop( 2) exprtk_loop( 3)
   13101             :                #ifndef exprtk_disable_superscalar_unroll
   13102    25656250 :                exprtk_loop( 4) exprtk_loop( 5)
   13103    25656250 :                exprtk_loop( 6) exprtk_loop( 7)
   13104    25656250 :                exprtk_loop( 8) exprtk_loop( 9)
   13105    25656250 :                exprtk_loop(10) exprtk_loop(11)
   13106    25656250 :                exprtk_loop(12) exprtk_loop(13)
   13107    25656250 :                exprtk_loop(14) exprtk_loop(15)
   13108             :                #endif
   13109             : 
   13110    25656250 :                vec0 += lud.batch_size;
   13111    25656250 :                vec1 += lud.batch_size;
   13112             :             }
   13113             : 
   13114        3695 :             int i = 0;
   13115             : 
   13116        3695 :             switch (lud.remainder)
   13117             :             {
   13118             :                #define case_stmt(N,fall_through)                           \
   13119             :                case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
   13120             :                fall_through                                                \
   13121             : 
   13122             :                #ifndef exprtk_disable_superscalar_unroll
   13123           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   13124           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   13125           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   13126         284 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   13127         384 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   13128        2200 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   13129             :                #endif
   13130        3062 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   13131        3190 :                case_stmt( 1, (void)0;)
   13132             :             }
   13133             : 
   13134             :             #undef exprtk_loop
   13135             :             #undef case_stmt
   13136             : 
   13137        7390 :             return (vds().data())[0];
   13138             :          }
   13139             : 
   13140           0 :          vector_node_ptr vec() const exprtk_override
   13141             :          {
   13142           0 :             return memory_context_.temp_vec_node_;
   13143             :          }
   13144             : 
   13145        2419 :          vector_node_ptr vec() exprtk_override
   13146             :          {
   13147        2419 :             return memory_context_.temp_vec_node_;
   13148             :          }
   13149             : 
   13150       27585 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13151             :          {
   13152       27585 :             return expression_node<T>::e_vecvalarith;
   13153             :          }
   13154             : 
   13155       15100 :          inline bool valid() const exprtk_override
   13156             :          {
   13157             :             return
   13158       30200 :                vec0_node_ptr_          &&
   13159       30200 :                (size() <= base_size()) &&
   13160       30200 :                binary_node<T>::valid();
   13161             :          }
   13162             : 
   13163       19114 :          std::size_t size() const exprtk_override
   13164             :          {
   13165       19114 :             return vec0_node_ptr_->size();
   13166             :          }
   13167             : 
   13168       15100 :          std::size_t base_size() const exprtk_override
   13169             :          {
   13170       15100 :             return vec0_node_ptr_->vec_holder().base_size();
   13171             :          }
   13172             : 
   13173        5579 :          vds_t& vds() exprtk_override
   13174             :          {
   13175        5579 :             return vds_;
   13176             :          }
   13177             : 
   13178        7390 :          const vds_t& vds() const exprtk_override
   13179             :          {
   13180        7390 :             return vds_;
   13181             :          }
   13182             : 
   13183             :       private:
   13184             : 
   13185             :          vector_node_ptr   vec0_node_ptr_;
   13186             :          vds_t             vds_;
   13187             :          memory_context    memory_context_;
   13188             :       };
   13189             : 
   13190             :       template <typename T, typename Operation>
   13191             :       class vec_binop_valvec_node exprtk_final
   13192             :                                   : public binary_node     <T>
   13193             :                                   , public vector_interface<T>
   13194             :       {
   13195             :       public:
   13196             : 
   13197             :          typedef expression_node<T>* expression_ptr;
   13198             :          typedef vector_node<T>*     vector_node_ptr;
   13199             :          typedef vector_holder<T>    vector_holder_t;
   13200             :          typedef vector_holder_t*    vector_holder_ptr;
   13201             :          typedef vec_data_store<T>   vds_t;
   13202             :          typedef memory_context_t<T> memory_context;
   13203             : 
   13204             :          using binary_node<T>::branch;
   13205             : 
   13206        2687 :          vec_binop_valvec_node(const operator_type& opr,
   13207             :                                expression_ptr branch0,
   13208             :                                expression_ptr branch1)
   13209             :          : binary_node<T>(opr, branch0, branch1)
   13210        2687 :          , vec1_node_ptr_(0)
   13211             :          {
   13212        2687 :             bool v1_is_ivec = false;
   13213             : 
   13214        2687 :             if (is_vector_node(branch(1)))
   13215             :             {
   13216        1437 :                vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
   13217             :             }
   13218        1250 :             else if (is_ivector_node(branch(1)))
   13219             :             {
   13220        1250 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13221             : 
   13222        1250 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
   13223             :                {
   13224        1250 :                   vec1_node_ptr_ = vi->vec();
   13225        1250 :                   v1_is_ivec     = true;
   13226             :                }
   13227             :             }
   13228             : 
   13229        2687 :             if (vec1_node_ptr_)
   13230             :             {
   13231        2687 :                if (v1_is_ivec)
   13232        1250 :                   vds() = vec1_node_ptr_->vds();
   13233             :                else
   13234        1437 :                   vds() = vds_t(vec1_node_ptr_->base_size());
   13235             : 
   13236        2687 :                memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds());
   13237             :             }
   13238             : 
   13239        2687 :             assert(valid());
   13240        2687 :          }
   13241             : 
   13242        5374 :         ~vec_binop_valvec_node()
   13243             :          {
   13244        2687 :             memory_context_.clear();
   13245        5374 :          }
   13246             : 
   13247        3916 :          inline T value() const exprtk_override
   13248             :          {
   13249        3916 :             const T v = branch(0)->value();
   13250        3916 :                         branch(1)->value();
   13251             : 
   13252        3916 :                   T* vec0 = vds().data();
   13253        3916 :             const T* vec1 = vec1_node_ptr_->vds().data();
   13254             : 
   13255        3916 :             loop_unroll::details lud(size());
   13256        3916 :             const T* upper_bound = vec0 + lud.upper_bound;
   13257             : 
   13258    50660166 :             while (vec0 < upper_bound)
   13259             :             {
   13260             :                #define exprtk_loop(N)                    \
   13261             :                vec0[N] = Operation::process(v, vec1[N]); \
   13262             : 
   13263    50656250 :                exprtk_loop( 0) exprtk_loop( 1)
   13264    50656250 :                exprtk_loop( 2) exprtk_loop( 3)
   13265             :                #ifndef exprtk_disable_superscalar_unroll
   13266    50656250 :                exprtk_loop( 4) exprtk_loop( 5)
   13267    50656250 :                exprtk_loop( 6) exprtk_loop( 7)
   13268    50656250 :                exprtk_loop( 8) exprtk_loop( 9)
   13269    50656250 :                exprtk_loop(10) exprtk_loop(11)
   13270    50656250 :                exprtk_loop(12) exprtk_loop(13)
   13271    50656250 :                exprtk_loop(14) exprtk_loop(15)
   13272             :                #endif
   13273             : 
   13274    50656250 :                vec0 += lud.batch_size;
   13275    50656250 :                vec1 += lud.batch_size;
   13276             :             }
   13277             : 
   13278        3916 :             int i = 0;
   13279             : 
   13280        3916 :             switch (lud.remainder)
   13281             :             {
   13282             :                #define case_stmt(N,fall_through)                           \
   13283             :                case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
   13284             :                fall_through                                                \
   13285             : 
   13286             :                #ifndef exprtk_disable_superscalar_unroll
   13287           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   13288           0 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   13289           0 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   13290         157 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   13291         185 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   13292        1939 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   13293             :                #endif
   13294        2877 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   13295        3011 :                case_stmt( 1, (void)0;)
   13296             :             }
   13297             : 
   13298             :             #undef exprtk_loop
   13299             :             #undef case_stmt
   13300             : 
   13301        7832 :             return (vds().data())[0];
   13302             :          }
   13303             : 
   13304           0 :          vector_node_ptr vec() const exprtk_override
   13305             :          {
   13306           0 :             return memory_context_.temp_vec_node_;
   13307             :          }
   13308             : 
   13309        2624 :          vector_node_ptr vec() exprtk_override
   13310             :          {
   13311        2624 :             return memory_context_.temp_vec_node_;
   13312             :          }
   13313             : 
   13314       27915 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13315             :          {
   13316       27915 :             return expression_node<T>::e_vecvalarith;
   13317             :          }
   13318             : 
   13319       15515 :          inline bool valid() const exprtk_override
   13320             :          {
   13321             :             return
   13322       31030 :                vec1_node_ptr_               &&
   13323       15515 :                (size() <= base_size())      &&
   13324       46545 :                (vds_.size() <= base_size()) &&
   13325       31030 :                binary_node<T>::valid();
   13326             :          }
   13327             : 
   13328       20027 :          std::size_t size() const exprtk_override
   13329             :          {
   13330       20027 :             return vec1_node_ptr_->vec_holder().size();
   13331             :          }
   13332             : 
   13333       31030 :          std::size_t base_size() const exprtk_override
   13334             :          {
   13335       31030 :             return vec1_node_ptr_->vec_holder().base_size();
   13336             :          }
   13337             : 
   13338        5675 :          vds_t& vds() exprtk_override
   13339             :          {
   13340        5675 :             return vds_;
   13341             :          }
   13342             : 
   13343        7832 :          const vds_t& vds() const exprtk_override
   13344             :          {
   13345        7832 :             return vds_;
   13346             :          }
   13347             : 
   13348             :       private:
   13349             : 
   13350             :          vector_node_ptr   vec1_node_ptr_;
   13351             :          vds_t             vds_;
   13352             :          memory_context    memory_context_;
   13353             :       };
   13354             : 
   13355             :       template <typename T, typename Operation>
   13356             :       class unary_vector_node exprtk_final
   13357             :                               : public unary_node      <T>
   13358             :                               , public vector_interface<T>
   13359             :       {
   13360             :       public:
   13361             : 
   13362             :          typedef expression_node<T>* expression_ptr;
   13363             :          typedef vector_node<T>*     vector_node_ptr;
   13364             :          typedef vector_holder<T>    vector_holder_t;
   13365             :          typedef vector_holder_t*    vector_holder_ptr;
   13366             :          typedef vec_data_store<T>   vds_t;
   13367             :          typedef memory_context_t<T> memory_context;
   13368             : 
   13369             :          using expression_node<T>::branch;
   13370             : 
   13371        1430 :          unary_vector_node(const operator_type& opr, expression_ptr branch0)
   13372             :          : unary_node<T>(opr, branch0)
   13373        1430 :          , vec0_node_ptr_(0)
   13374             :          {
   13375        1430 :             bool vec0_is_ivec = false;
   13376             : 
   13377        1430 :             if (is_vector_node(branch(0)))
   13378             :             {
   13379          96 :                vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
   13380             :             }
   13381        1334 :             else if (is_ivector_node(branch(0)))
   13382             :             {
   13383        1334 :                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   13384             : 
   13385        1334 :                if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
   13386             :                {
   13387        1334 :                   vec0_node_ptr_ = vi->vec();
   13388        1334 :                   vec0_is_ivec   = true;
   13389             :                }
   13390             :             }
   13391             : 
   13392        1430 :             if (vec0_node_ptr_)
   13393             :             {
   13394        1430 :                if (vec0_is_ivec)
   13395        1334 :                   vds_ = vec0_node_ptr_->vds();
   13396             :                else
   13397          96 :                   vds_ = vds_t(vec0_node_ptr_->base_size());
   13398             : 
   13399        1430 :                memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
   13400             :             }
   13401             : 
   13402        1430 :             assert(valid());
   13403        1430 :          }
   13404             : 
   13405        2860 :         ~unary_vector_node()
   13406             :          {
   13407        1430 :             memory_context_.clear();
   13408        2860 :          }
   13409             : 
   13410        1495 :          inline T value() const exprtk_override
   13411             :          {
   13412        1495 :             branch()->value();
   13413             : 
   13414        1495 :             const T* vec0 = vec0_node_ptr_->vds().data();
   13415        1495 :                   T* vec1 = vds().data();
   13416             : 
   13417        1495 :             loop_unroll::details lud(size());
   13418        1495 :             const T* upper_bound = vec0 + lud.upper_bound;
   13419             : 
   13420      688995 :             while (vec0 < upper_bound)
   13421             :             {
   13422             :                #define exprtk_loop(N)                 \
   13423             :                vec1[N] = Operation::process(vec0[N]); \
   13424             : 
   13425      687500 :                exprtk_loop( 0) exprtk_loop( 1)
   13426      687500 :                exprtk_loop( 2) exprtk_loop( 3)
   13427             :                #ifndef exprtk_disable_superscalar_unroll
   13428      687500 :                exprtk_loop( 4) exprtk_loop( 5)
   13429      687500 :                exprtk_loop( 6) exprtk_loop( 7)
   13430      687500 :                exprtk_loop( 8) exprtk_loop( 9)
   13431      687500 :                exprtk_loop(10) exprtk_loop(11)
   13432      687500 :                exprtk_loop(12) exprtk_loop(13)
   13433      687500 :                exprtk_loop(14) exprtk_loop(15)
   13434             :                #endif
   13435             : 
   13436      687500 :                vec0 += lud.batch_size;
   13437      687500 :                vec1 += lud.batch_size;
   13438             :             }
   13439             : 
   13440        1495 :             int i = 0;
   13441             : 
   13442        1495 :             switch (lud.remainder)
   13443             :             {
   13444             :                #define case_stmt(N)                                     \
   13445             :                case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
   13446             :                exprtk_fallthrough                                       \
   13447             : 
   13448             :                #ifndef exprtk_disable_superscalar_unroll
   13449           0 :                case_stmt(15) case_stmt(14)
   13450           0 :                case_stmt(13) case_stmt(12)
   13451           0 :                case_stmt(11) case_stmt(10)
   13452         125 :                case_stmt( 9) case_stmt( 8)
   13453         125 :                case_stmt( 7) case_stmt( 6)
   13454        1305 :                case_stmt( 5) case_stmt( 4)
   13455             :                #endif
   13456        1385 :                case_stmt( 3) case_stmt( 2)
   13457        1385 :                case_stmt( 1)
   13458        1495 :                default: break;
   13459             :             }
   13460             : 
   13461             :             #undef exprtk_loop
   13462             :             #undef case_stmt
   13463             : 
   13464        2990 :             return (vds().data())[0];
   13465             :          }
   13466             : 
   13467           0 :          vector_node_ptr vec() const exprtk_override
   13468             :          {
   13469           0 :             return memory_context_.temp_vec_node_;
   13470             :          }
   13471             : 
   13472        1430 :          vector_node_ptr vec() exprtk_override
   13473             :          {
   13474        1430 :             return memory_context_.temp_vec_node_;
   13475             :          }
   13476             : 
   13477       15997 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13478             :          {
   13479       15997 :             return expression_node<T>::e_vecunaryop;
   13480             :          }
   13481             : 
   13482        9019 :          inline bool valid() const exprtk_override
   13483             :          {
   13484        9019 :             return vec0_node_ptr_ && unary_node<T>::valid();
   13485             :          }
   13486             : 
   13487        1575 :          std::size_t size() const exprtk_override
   13488             :          {
   13489        1575 :             return vec0_node_ptr_->vec_holder().size();
   13490             :          }
   13491             : 
   13492           0 :          std::size_t base_size() const exprtk_override
   13493             :          {
   13494           0 :             return vec0_node_ptr_->vec_holder().base_size();
   13495             :          }
   13496             : 
   13497        1470 :          vds_t& vds() exprtk_override
   13498             :          {
   13499        1470 :             return vds_;
   13500             :          }
   13501             : 
   13502        2990 :          const vds_t& vds() const exprtk_override
   13503             :          {
   13504        2990 :             return vds_;
   13505             :          }
   13506             : 
   13507             :       private:
   13508             : 
   13509             :          vector_node_ptr vec0_node_ptr_;
   13510             :          vds_t           vds_;
   13511             :          memory_context  memory_context_;
   13512             :       };
   13513             : 
   13514             :       template <typename T>
   13515             :       class conditional_vector_node exprtk_final
   13516             :                                     : public expression_node <T>
   13517             :                                     , public vector_interface<T>
   13518             :       {
   13519             :       public:
   13520             : 
   13521             :          typedef expression_node <T>* expression_ptr;
   13522             :          typedef vector_interface<T>* vec_interface_ptr;
   13523             :          typedef vector_node     <T>* vector_node_ptr;
   13524             :          typedef vector_holder   <T>  vector_holder_t;
   13525             :          typedef vector_holder_t*     vector_holder_ptr;
   13526             :          typedef vec_data_store  <T>  vds_t;
   13527             :          typedef memory_context_t<T> memory_context;
   13528             :          typedef std::pair<expression_ptr,bool> branch_t;
   13529             : 
   13530         768 :          conditional_vector_node(expression_ptr condition,
   13531             :                                  expression_ptr consequent,
   13532             :                                  expression_ptr alternative)
   13533         768 :          : consequent_node_ptr_ (0)
   13534         768 :          , alternative_node_ptr_(0)
   13535         768 :          , temp_vec_node_       (0)
   13536         768 :          , temp_                (0)
   13537         768 :          , result_vec_size_     (0)
   13538         768 :          , initialised_         (false)
   13539             :          {
   13540         768 :             construct_branch_pair(condition_  , condition  );
   13541         768 :             construct_branch_pair(consequent_ , consequent );
   13542         768 :             construct_branch_pair(alternative_, alternative);
   13543             : 
   13544         768 :             if (details::is_ivector_node(consequent_.first))
   13545             :             {
   13546         768 :                vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first);
   13547             : 
   13548         768 :                if (0 != ivec_ptr)
   13549             :                {
   13550         768 :                   consequent_node_ptr_ = ivec_ptr->vec();
   13551             :                }
   13552             :             }
   13553             : 
   13554         768 :             if (details::is_ivector_node(alternative_.first))
   13555             :             {
   13556         768 :                vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first);
   13557             : 
   13558         768 :                if (0 != ivec_ptr)
   13559             :                {
   13560         768 :                   alternative_node_ptr_ = ivec_ptr->vec();
   13561             :                }
   13562             :             }
   13563             : 
   13564         768 :             if (consequent_node_ptr_ && alternative_node_ptr_)
   13565             :             {
   13566         768 :                const std::size_t vec_size =
   13567         768 :                   std::max(consequent_node_ptr_ ->vec_holder().base_size(),
   13568         768 :                            alternative_node_ptr_->vec_holder().base_size());
   13569             : 
   13570         768 :                vds_            = vds_t(vec_size);
   13571         768 :                memory_context_ = make_memory_context(
   13572         768 :                   consequent_node_ptr_ ->vec_holder(),
   13573         768 :                   alternative_node_ptr_->vec_holder(),
   13574         768 :                   vds());
   13575             : 
   13576         768 :                initialised_ = (vec_size > 0);
   13577             :             }
   13578             : 
   13579         768 :             assert(initialised_);
   13580         768 :          }
   13581             : 
   13582        1536 :         ~conditional_vector_node()
   13583             :          {
   13584         768 :             memory_context_.clear();
   13585        1536 :          }
   13586             : 
   13587         777 :          inline T value() const exprtk_override
   13588             :          {
   13589         777 :             T result = T(0);
   13590         777 :             T* source_vector = 0;
   13591         777 :             T* result_vector = vds().data();
   13592             : 
   13593         777 :             if (is_true(condition_))
   13594             :             {
   13595         397 :                result           = consequent_.first->value();
   13596         397 :                source_vector    = consequent_node_ptr_->vds().data();
   13597         397 :                result_vec_size_ = consequent_node_ptr_->size();
   13598             :             }
   13599             :             else
   13600             :             {
   13601         380 :                result           = alternative_.first->value();
   13602         380 :                source_vector    = alternative_node_ptr_->vds().data();
   13603         380 :                result_vec_size_ = alternative_node_ptr_->size();
   13604             :             }
   13605             : 
   13606        3240 :             for (std::size_t i = 0; i < result_vec_size_; ++i)
   13607             :             {
   13608        2463 :                result_vector[i] = source_vector[i];
   13609             :             }
   13610             : 
   13611         777 :             return result;
   13612             :          }
   13613             : 
   13614           0 :          vector_node_ptr vec() const exprtk_override
   13615             :          {
   13616           0 :             return memory_context_.temp_vec_node_;
   13617             :          }
   13618             : 
   13619         777 :          vector_node_ptr vec() exprtk_override
   13620             :          {
   13621         777 :             return memory_context_.temp_vec_node_;
   13622             :          }
   13623             : 
   13624       10024 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13625             :          {
   13626       10024 :             return expression_node<T>::e_vecondition;
   13627             :          }
   13628             : 
   13629        1536 :          inline bool valid() const exprtk_override
   13630             :          {
   13631             :             return
   13632        3072 :                initialised_                                      &&
   13633        1536 :                condition_  .first && condition_  .first->valid() &&
   13634        1536 :                consequent_ .first && consequent_ .first->valid() &&
   13635        4608 :                alternative_.first && alternative_.first->valid() &&
   13636        3072 :                size() <= base_size();
   13637             :          }
   13638             : 
   13639        1553 :          std::size_t size() const exprtk_override
   13640             :          {
   13641        1553 :             return result_vec_size_;
   13642             :          }
   13643             : 
   13644        1536 :          std::size_t base_size() const exprtk_override
   13645             :          {
   13646        1536 :             return std::min(
   13647        1536 :                consequent_node_ptr_ ->vec_holder().base_size(),
   13648        3072 :                alternative_node_ptr_->vec_holder().base_size());
   13649             :          }
   13650             : 
   13651         768 :          vds_t& vds() exprtk_override
   13652             :          {
   13653         768 :             return vds_;
   13654             :          }
   13655             : 
   13656         777 :          const vds_t& vds() const exprtk_override
   13657             :          {
   13658         777 :             return vds_;
   13659             :          }
   13660             : 
   13661         768 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   13662             :          {
   13663         768 :             expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
   13664         768 :             expression_node<T>::ndb_t::collect(consequent_  , node_delete_list);
   13665         768 :             expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
   13666         768 :          }
   13667             : 
   13668        1944 :          std::size_t node_depth() const exprtk_override
   13669             :          {
   13670             :             return expression_node<T>::ndb_t::compute_node_depth
   13671        1944 :                (condition_, consequent_, alternative_);
   13672             :          }
   13673             : 
   13674             :       private:
   13675             : 
   13676             :          branch_t            condition_;
   13677             :          branch_t            consequent_;
   13678             :          branch_t            alternative_;
   13679             :          vector_node_ptr     consequent_node_ptr_;
   13680             :          vector_node_ptr     alternative_node_ptr_;
   13681             :          vector_node_ptr     temp_vec_node_;
   13682             :          vector_holder_ptr   temp_;
   13683             :          vds_t               vds_;
   13684             :          mutable std::size_t result_vec_size_;
   13685             :          bool                initialised_;
   13686             :          memory_context      memory_context_;
   13687             :       };
   13688             : 
   13689             :       template <typename T>
   13690             :       class scand_node exprtk_final : public binary_node<T>
   13691             :       {
   13692             :       public:
   13693             : 
   13694             :          typedef expression_node<T>* expression_ptr;
   13695             :          using binary_node<T>::branch;
   13696             : 
   13697         120 :          scand_node(const operator_type& opr,
   13698             :                     expression_ptr branch0,
   13699             :                     expression_ptr branch1)
   13700         120 :          : binary_node<T>(opr, branch0, branch1)
   13701             :          {
   13702         120 :             assert(binary_node<T>::valid());
   13703         120 :          }
   13704             : 
   13705         105 :          inline T value() const exprtk_override
   13706             :          {
   13707             :             return (
   13708         105 :                      std::not_equal_to<T>()
   13709         210 :                         (T(0),branch(0)->value()) &&
   13710           0 :                      std::not_equal_to<T>()
   13711         210 :                         (T(0),branch(1)->value())
   13712         315 :                    ) ? T(1) : T(0);
   13713             :          }
   13714             :       };
   13715             : 
   13716             :       template <typename T>
   13717             :       class scor_node exprtk_final : public binary_node<T>
   13718             :       {
   13719             :       public:
   13720             : 
   13721             :          typedef expression_node<T>* expression_ptr;
   13722             :          using binary_node<T>::branch;
   13723             : 
   13724         105 :          scor_node(const operator_type& opr,
   13725             :                    expression_ptr branch0,
   13726             :                    expression_ptr branch1)
   13727         105 :          : binary_node<T>(opr, branch0, branch1)
   13728             :          {
   13729         105 :             assert(binary_node<T>::valid());
   13730         105 :          }
   13731             : 
   13732         105 :          inline T value() const exprtk_override
   13733             :          {
   13734             :             return (
   13735         105 :                      std::not_equal_to<T>()
   13736         210 :                         (T(0),branch(0)->value()) ||
   13737           0 :                      std::not_equal_to<T>()
   13738         210 :                         (T(0),branch(1)->value())
   13739         315 :                    ) ? T(1) : T(0);
   13740             :          }
   13741             :       };
   13742             : 
   13743             :       template <typename T, typename IFunction, std::size_t N>
   13744             :       class function_N_node exprtk_final : public expression_node<T>
   13745             :       {
   13746             :       public:
   13747             : 
   13748             :          // Function of N parameters.
   13749             :          typedef expression_node<T>* expression_ptr;
   13750             :          typedef std::pair<expression_ptr,bool> branch_t;
   13751             :          typedef IFunction ifunction;
   13752             : 
   13753       60380 :          explicit function_N_node(ifunction* func)
   13754       60380 :          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
   13755       60380 :          , parameter_count_(func->param_count)
   13756       60380 :          , initialised_(false)
   13757       60380 :          {}
   13758             : 
   13759             :          template <std::size_t NumBranches>
   13760      120640 :          bool init_branches(expression_ptr (&b)[NumBranches])
   13761             :          {
   13762             :             // Needed for incompetent and broken msvc compiler versions
   13763             :             #ifdef _MSC_VER
   13764             :              #pragma warning(push)
   13765             :              #pragma warning(disable: 4127)
   13766             :             #endif
   13767             : 
   13768             :             if (N != NumBranches)
   13769             :             {
   13770             :                return false;
   13771             :             }
   13772             : 
   13773      519718 :             for (std::size_t i = 0; i < NumBranches; ++i)
   13774             :             {
   13775      399078 :                if (b[i] && b[i]->valid())
   13776      399078 :                   branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
   13777             :                else
   13778           0 :                   return false;
   13779             :             }
   13780             : 
   13781      120640 :             initialised_ = function_;
   13782      120640 :             assert(valid());
   13783      120640 :             return initialised_;
   13784             : 
   13785             :             #ifdef _MSC_VER
   13786             :              #pragma warning(pop)
   13787             :             #endif
   13788             :          }
   13789             : 
   13790             :          inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
   13791             :          {
   13792             :             return this < (&fn);
   13793             :          }
   13794             : 
   13795    45898398 :          inline T value() const exprtk_override
   13796             :          {
   13797             :             // Needed for incompetent and broken msvc compiler versions
   13798             :             #ifdef _MSC_VER
   13799             :              #pragma warning(push)
   13800             :              #pragma warning(disable: 4127)
   13801             :             #endif
   13802             : 
   13803             :             T v[N];
   13804    45898398 :             evaluate_branches<T,N>::execute(v,branch_);
   13805    91796796 :             return invoke<T,N>::execute(*function_,v);
   13806             : 
   13807             :             #ifdef _MSC_VER
   13808             :              #pragma warning(pop)
   13809             :             #endif
   13810             :          }
   13811             : 
   13812     1635343 :          inline typename expression_node<T>::node_type type() const exprtk_override
   13813             :          {
   13814     1635343 :             return expression_node<T>::e_function;
   13815             :          }
   13816             : 
   13817     1042604 :          inline bool valid() const exprtk_override
   13818             :          {
   13819     1042604 :             return initialised_;
   13820             :          }
   13821             : 
   13822       60380 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   13823             :          {
   13824       60380 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
   13825       60380 :          }
   13826             : 
   13827      176077 :          std::size_t node_depth() const exprtk_override
   13828             :          {
   13829      176077 :             return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
   13830             :          }
   13831             : 
   13832             :          template <typename T_, std::size_t BranchCount>
   13833             :          struct evaluate_branches
   13834             :          {
   13835        8120 :             static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
   13836             :             {
   13837       93380 :                for (std::size_t i = 0; i < BranchCount; ++i)
   13838             :                {
   13839       85260 :                   v[i] = b[i].first->value();
   13840             :                }
   13841        8120 :             }
   13842             :          };
   13843             : 
   13844             :          template <typename T_>
   13845             :          struct evaluate_branches <T_,6>
   13846             :          {
   13847        1215 :             static inline void execute(T_ (&v)[6], const branch_t (&b)[6])
   13848             :             {
   13849        1215 :                v[0] = b[0].first->value();
   13850        1215 :                v[1] = b[1].first->value();
   13851        1215 :                v[2] = b[2].first->value();
   13852        1215 :                v[3] = b[3].first->value();
   13853        1215 :                v[4] = b[4].first->value();
   13854        1215 :                v[5] = b[5].first->value();
   13855        1215 :             }
   13856             :          };
   13857             : 
   13858             :          template <typename T_>
   13859             :          struct evaluate_branches <T_,5>
   13860             :          {
   13861        2024 :             static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
   13862             :             {
   13863        2024 :                v[0] = b[0].first->value();
   13864        2024 :                v[1] = b[1].first->value();
   13865        2024 :                v[2] = b[2].first->value();
   13866        2024 :                v[3] = b[3].first->value();
   13867        2024 :                v[4] = b[4].first->value();
   13868        2024 :             }
   13869             :          };
   13870             : 
   13871             :          template <typename T_>
   13872             :          struct evaluate_branches <T_,4>
   13873             :          {
   13874        5288 :             static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
   13875             :             {
   13876        5288 :                v[0] = b[0].first->value();
   13877        5288 :                v[1] = b[1].first->value();
   13878        5288 :                v[2] = b[2].first->value();
   13879        5288 :                v[3] = b[3].first->value();
   13880        5288 :             }
   13881             :          };
   13882             : 
   13883             :          template <typename T_>
   13884             :          struct evaluate_branches <T_,3>
   13885             :          {
   13886       13924 :             static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
   13887             :             {
   13888       13924 :                v[0] = b[0].first->value();
   13889       13924 :                v[1] = b[1].first->value();
   13890       13924 :                v[2] = b[2].first->value();
   13891       13924 :             }
   13892             :          };
   13893             : 
   13894             :          template <typename T_>
   13895             :          struct evaluate_branches <T_,2>
   13896             :          {
   13897      156842 :             static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
   13898             :             {
   13899      156842 :                v[0] = b[0].first->value();
   13900      156842 :                v[1] = b[1].first->value();
   13901      156842 :             }
   13902             :          };
   13903             : 
   13904             :          template <typename T_>
   13905             :          struct evaluate_branches <T_,1>
   13906             :          {
   13907    45710985 :             static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
   13908             :             {
   13909    45710985 :                v[0] = b[0].first->value();
   13910    45710985 :             }
   13911             :          };
   13912             : 
   13913             :          template <typename T_, std::size_t ParamCount>
   13914             :          struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
   13915             : 
   13916             :          template <typename T_>
   13917             :          struct invoke<T_,20>
   13918             :          {
   13919           0 :             static inline T_ execute(ifunction& f, T_ (&v)[20])
   13920           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]); }
   13921             :          };
   13922             : 
   13923             :          template <typename T_>
   13924             :          struct invoke<T_,19>
   13925             :          {
   13926           0 :             static inline T_ execute(ifunction& f, T_ (&v)[19])
   13927           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]); }
   13928             :          };
   13929             : 
   13930             :          template <typename T_>
   13931             :          struct invoke<T_,18>
   13932             :          {
   13933           0 :             static inline T_ execute(ifunction& f, T_ (&v)[18])
   13934           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]); }
   13935             :          };
   13936             : 
   13937             :          template <typename T_>
   13938             :          struct invoke<T_,17>
   13939             :          {
   13940           0 :             static inline T_ execute(ifunction& f, T_ (&v)[17])
   13941           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]); }
   13942             :          };
   13943             : 
   13944             :          template <typename T_>
   13945             :          struct invoke<T_,16>
   13946             :          {
   13947           0 :             static inline T_ execute(ifunction& f, T_ (&v)[16])
   13948           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]); }
   13949             :          };
   13950             : 
   13951             :          template <typename T_>
   13952             :          struct invoke<T_,15>
   13953             :          {
   13954           0 :             static inline T_ execute(ifunction& f, T_ (&v)[15])
   13955           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]); }
   13956             :          };
   13957             : 
   13958             :          template <typename T_>
   13959             :          struct invoke<T_,14>
   13960             :          {
   13961        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[14])
   13962        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]); }
   13963             :          };
   13964             : 
   13965             :          template <typename T_>
   13966             :          struct invoke<T_,13>
   13967             :          {
   13968        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[13])
   13969        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]); }
   13970             :          };
   13971             : 
   13972             :          template <typename T_>
   13973             :          struct invoke<T_,12>
   13974             :          {
   13975        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[12])
   13976        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]); }
   13977             :          };
   13978             : 
   13979             :          template <typename T_>
   13980             :          struct invoke<T_,11>
   13981             :          {
   13982        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[11])
   13983        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]); }
   13984             :          };
   13985             : 
   13986             :          template <typename T_>
   13987             :          struct invoke<T_,10>
   13988             :          {
   13989        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[10])
   13990        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); }
   13991             :          };
   13992             : 
   13993             :          template <typename T_>
   13994             :          struct invoke<T_,9>
   13995             :          {
   13996        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[9])
   13997        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); }
   13998             :          };
   13999             : 
   14000             :          template <typename T_>
   14001             :          struct invoke<T_,8>
   14002             :          {
   14003        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[8])
   14004        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); }
   14005             :          };
   14006             : 
   14007             :          template <typename T_>
   14008             :          struct invoke<T_,7>
   14009             :          {
   14010        1015 :             static inline T_ execute(ifunction& f, T_ (&v)[7])
   14011        1015 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); }
   14012             :          };
   14013             : 
   14014             :          template <typename T_>
   14015             :          struct invoke<T_,6>
   14016             :          {
   14017        1215 :             static inline T_ execute(ifunction& f, T_ (&v)[6])
   14018        1215 :             { return f(v[0], v[1], v[2], v[3], v[4], v[5]); }
   14019             :          };
   14020             : 
   14021             :          template <typename T_>
   14022             :          struct invoke<T_,5>
   14023             :          {
   14024        2024 :             static inline T_ execute(ifunction& f, T_ (&v)[5])
   14025        2024 :             { return f(v[0], v[1], v[2], v[3], v[4]); }
   14026             :          };
   14027             : 
   14028             :          template <typename T_>
   14029             :          struct invoke<T_,4>
   14030             :          {
   14031        5288 :             static inline T_ execute(ifunction& f, T_ (&v)[4])
   14032        5288 :             { return f(v[0], v[1], v[2], v[3]); }
   14033             :          };
   14034             : 
   14035             :          template <typename T_>
   14036             :          struct invoke<T_,3>
   14037             :          {
   14038       13924 :             static inline T_ execute(ifunction& f, T_ (&v)[3])
   14039       13924 :             { return f(v[0], v[1], v[2]); }
   14040             :          };
   14041             : 
   14042             :          template <typename T_>
   14043             :          struct invoke<T_,2>
   14044             :          {
   14045      156842 :             static inline T_ execute(ifunction& f, T_ (&v)[2])
   14046      156842 :             { return f(v[0], v[1]); }
   14047             :          };
   14048             : 
   14049             :          template <typename T_>
   14050             :          struct invoke<T_,1>
   14051             :          {
   14052    45710985 :             static inline T_ execute(ifunction& f, T_ (&v)[1])
   14053    45710985 :             { return f(v[0]); }
   14054             :          };
   14055             : 
   14056             :       private:
   14057             : 
   14058             :          ifunction*  function_;
   14059             :          std::size_t parameter_count_;
   14060             :          branch_t    branch_[N];
   14061             :          bool        initialised_;
   14062             :       };
   14063             : 
   14064             :       template <typename T, typename IFunction>
   14065             :       class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T>
   14066             :       {
   14067             :       public:
   14068             : 
   14069             :          typedef expression_node<T>* expression_ptr;
   14070             :          typedef IFunction ifunction;
   14071             : 
   14072         231 :          explicit function_N_node(ifunction* func)
   14073         231 :          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
   14074             :          {
   14075         231 :             assert(valid());
   14076         231 :          }
   14077             : 
   14078             :          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
   14079             :          {
   14080             :             return this < (&fn);
   14081             :          }
   14082             : 
   14083       77530 :          inline T value() const exprtk_override
   14084             :          {
   14085       77530 :             return (*function_)();
   14086             :          }
   14087             : 
   14088        3981 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14089             :          {
   14090        3981 :             return expression_node<T>::e_function;
   14091             :          }
   14092             : 
   14093         501 :          inline bool valid() const exprtk_override
   14094             :          {
   14095         501 :             return function_;
   14096             :          }
   14097             : 
   14098             :       private:
   14099             : 
   14100             :          ifunction* function_;
   14101             :       };
   14102             : 
   14103             :       template <typename T, typename VarArgFunction>
   14104             :       class vararg_function_node exprtk_final : public expression_node<T>
   14105             :       {
   14106             :       public:
   14107             : 
   14108             :          typedef expression_node<T>* expression_ptr;
   14109             : 
   14110          49 :          vararg_function_node(VarArgFunction*  func,
   14111             :                               const std::vector<expression_ptr>& arg_list)
   14112          49 :          : function_(func)
   14113          49 :          , arg_list_(arg_list)
   14114             :          {
   14115          49 :             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
   14116          49 :             assert(valid());
   14117          49 :          }
   14118             : 
   14119             :          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
   14120             :          {
   14121             :             return this < (&fn);
   14122             :          }
   14123             : 
   14124          49 :          inline T value() const exprtk_override
   14125             :          {
   14126          49 :             populate_value_list();
   14127          49 :             return (*function_)(value_list_);
   14128             :          }
   14129             : 
   14130         344 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14131             :          {
   14132         344 :             return expression_node<T>::e_vafunction;
   14133             :          }
   14134             : 
   14135         131 :          inline bool valid() const exprtk_override
   14136             :          {
   14137         131 :             return function_;
   14138             :          }
   14139             : 
   14140          49 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14141             :          {
   14142         166 :             for (std::size_t i = 0; i < arg_list_.size(); ++i)
   14143             :             {
   14144         117 :                if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
   14145             :                {
   14146          69 :                   node_delete_list.push_back(&arg_list_[i]);
   14147             :                }
   14148             :             }
   14149          49 :          }
   14150             : 
   14151         144 :          std::size_t node_depth() const exprtk_override
   14152             :          {
   14153         144 :             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
   14154             :          }
   14155             : 
   14156             :       private:
   14157             : 
   14158          49 :          inline void populate_value_list() const
   14159             :          {
   14160         166 :             for (std::size_t i = 0; i < arg_list_.size(); ++i)
   14161             :             {
   14162         117 :                value_list_[i] = arg_list_[i]->value();
   14163             :             }
   14164          49 :          }
   14165             : 
   14166             :          VarArgFunction* function_;
   14167             :          std::vector<expression_ptr> arg_list_;
   14168             :          mutable std::vector<T> value_list_;
   14169             :       };
   14170             : 
   14171             :       template <typename T, typename GenericFunction>
   14172             :       class generic_function_node : public expression_node<T>
   14173             :       {
   14174             :       public:
   14175             : 
   14176             :          typedef type_store<T>       type_store_t;
   14177             :          typedef expression_node<T>* expression_ptr;
   14178             :          typedef variable_node<T>    variable_node_t;
   14179             :          typedef vector_node<T>      vector_node_t;
   14180             :          typedef variable_node_t*    variable_node_ptr_t;
   14181             :          typedef vector_node_t*      vector_node_ptr_t;
   14182             :          typedef range_interface<T>  range_interface_t;
   14183             :          typedef range_data_type<T>  range_data_type_t;
   14184             :          typedef typename range_interface<T>::range_t range_t;
   14185             : 
   14186             :          typedef std::pair<expression_ptr,bool> branch_t;
   14187             :          typedef vector_holder<T>* vh_t;
   14188             :          typedef vector_view<T>*   vecview_t;
   14189             : 
   14190             :          typedef std::vector<T>                 tmp_vs_t;
   14191             :          typedef std::vector<type_store_t>      typestore_list_t;
   14192             :          typedef std::vector<range_data_type_t> range_list_t;
   14193             : 
   14194        2049 :          explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
   14195             :                                         GenericFunction* func = reinterpret_cast<GenericFunction*>(0))
   14196        2049 :          : function_(func)
   14197        2049 :          , arg_list_(arg_list)
   14198        2049 :          {}
   14199             : 
   14200        2106 :          virtual ~generic_function_node()
   14201             :          {
   14202        6709 :             for (std::size_t i = 0; i < vv_list_.size(); ++i)
   14203             :             {
   14204        4660 :                vecview_t& vv = vv_list_[i];
   14205        4660 :                if (vv && typestore_list_[i].vec_data)
   14206             :                {
   14207         111 :                   vv->remove_ref(&typestore_list_[i].vec_data);
   14208         111 :                   typestore_list_[i].vec_data = 0;
   14209             :                }
   14210             :             }
   14211        4155 :          }
   14212             : 
   14213        2049 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14214             :          {
   14215        2049 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   14216        2049 :          }
   14217             : 
   14218        4219 :          std::size_t node_depth() const exprtk_override exprtk_final
   14219             :          {
   14220        4219 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   14221             :          }
   14222             : 
   14223        2049 :          virtual bool init_branches()
   14224             :          {
   14225        2049 :             expr_as_vec1_store_.resize(arg_list_.size(), T(0)               );
   14226        2049 :             typestore_list_    .resize(arg_list_.size(), type_store_t()     );
   14227        2049 :             range_list_        .resize(arg_list_.size(), range_data_type_t());
   14228        2049 :             branch_            .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false));
   14229        2049 :             vv_list_           .resize(arg_list_.size(), vecview_t(0));
   14230             : 
   14231        6709 :             for (std::size_t i = 0; i < arg_list_.size(); ++i)
   14232             :             {
   14233        4660 :                type_store_t& ts = typestore_list_[i];
   14234             : 
   14235        4660 :                if (0 == arg_list_[i])
   14236           0 :                   return false;
   14237        4660 :                else if (is_ivector_node(arg_list_[i]))
   14238             :                {
   14239        2290 :                   vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
   14240             : 
   14241        2290 :                   if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
   14242           0 :                      return false;
   14243             : 
   14244        2290 :                   ts.size = vi->size();
   14245        2290 :                   ts.data = vi->vds().data();
   14246        2290 :                   ts.type = type_store_t::e_vector;
   14247             : 
   14248        2290 :                   if (
   14249        2401 :                        vi->vec()->vec_holder().rebaseable() &&
   14250         111 :                        vi->vec()->vec_holder().rebaseable_instance()
   14251             :                      )
   14252             :                   {
   14253         111 :                      vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance();
   14254         111 :                      vv_list_[i]->set_ref(&ts.vec_data);
   14255             :                   }
   14256             :                }
   14257             :                #ifndef exprtk_disable_string_capabilities
   14258        2370 :                else if (is_generally_string_node(arg_list_[i]))
   14259             :                {
   14260         254 :                   string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
   14261             : 
   14262         254 :                   if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
   14263           0 :                      return false;
   14264             : 
   14265         254 :                   ts.size = sbn->size();
   14266         254 :                   ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
   14267         254 :                   ts.type = type_store_t::e_string;
   14268             : 
   14269         254 :                   range_list_[i].data      = ts.data;
   14270         254 :                   range_list_[i].size      = ts.size;
   14271         254 :                   range_list_[i].type_size = sizeof(char);
   14272         254 :                   range_list_[i].str_node  = sbn;
   14273             : 
   14274         254 :                   range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
   14275             : 
   14276         254 :                   if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
   14277           0 :                      return false;
   14278             : 
   14279         254 :                   const range_t& rp = ri->range_ref();
   14280             : 
   14281         254 :                   if (
   14282         508 :                        rp.const_range() &&
   14283         254 :                        is_const_string_range_node(arg_list_[i])
   14284             :                      )
   14285             :                   {
   14286           0 :                      ts.size = rp.const_size();
   14287           0 :                      ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
   14288           0 :                      range_list_[i].range = reinterpret_cast<range_t*>(0);
   14289             :                   }
   14290             :                   else
   14291             :                   {
   14292         254 :                      range_list_[i].range = &(ri->range_ref());
   14293         254 :                      range_param_list_.push_back(i);
   14294             :                   }
   14295             :                }
   14296             :                #endif
   14297        2116 :                else if (is_variable_node(arg_list_[i]))
   14298             :                {
   14299         357 :                   variable_node_ptr_t var = variable_node_ptr_t(0);
   14300             : 
   14301         357 :                   if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
   14302           0 :                      return false;
   14303             : 
   14304         357 :                   ts.size = 1;
   14305         357 :                   ts.data = &var->ref();
   14306         357 :                   ts.type = type_store_t::e_scalar;
   14307             :                }
   14308             :                else
   14309             :                {
   14310        1759 :                   ts.size = 1;
   14311        1759 :                   ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
   14312        1759 :                   ts.type = type_store_t::e_scalar;
   14313             :                }
   14314             : 
   14315        4660 :                branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
   14316             :             }
   14317             : 
   14318        2049 :             return true;
   14319             :          }
   14320             : 
   14321             :          inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
   14322             :          {
   14323             :             return this < (&fn);
   14324             :          }
   14325             : 
   14326         120 :          inline T value() const exprtk_override
   14327             :          {
   14328         120 :             if (populate_value_list())
   14329             :             {
   14330             :                typedef typename GenericFunction::parameter_list_t parameter_list_t;
   14331             : 
   14332         120 :                return (*function_)(parameter_list_t(typestore_list_));
   14333             :             }
   14334             : 
   14335           0 :             return std::numeric_limits<T>::quiet_NaN();
   14336             :          }
   14337             : 
   14338         337 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14339             :          {
   14340         337 :             return expression_node<T>::e_genfunction;
   14341             :          }
   14342             : 
   14343        7209 :          inline bool valid() const exprtk_override
   14344             :          {
   14345        7209 :             return function_;
   14346             :          }
   14347             : 
   14348             :       protected:
   14349             : 
   14350        3603 :          inline virtual bool populate_value_list() const
   14351             :          {
   14352       11449 :             for (std::size_t i = 0; i < branch_.size(); ++i)
   14353             :             {
   14354        7846 :                expr_as_vec1_store_[i] = branch_[i].first->value();
   14355             :             }
   14356             : 
   14357        3603 :             if (!range_param_list_.empty())
   14358             :             {
   14359         158 :                assert(range_param_list_.size() <= branch_.size());
   14360             : 
   14361         408 :                for (std::size_t i = 0; i < range_param_list_.size(); ++i)
   14362             :                {
   14363         250 :                   const std::size_t  index = range_param_list_[i];
   14364         250 :                   range_data_type_t& rdt   = range_list_[index];
   14365             : 
   14366         250 :                   const range_t& rp = (*rdt.range);
   14367         250 :                   std::size_t r0    = 0;
   14368         250 :                   std::size_t r1    = 0;
   14369             : 
   14370         250 :                   const std::size_t data_size =
   14371             :                   #ifndef exprtk_disable_string_capabilities
   14372         250 :                      rdt.str_node ? rdt.str_node->size() : rdt.size;
   14373             :                   #else
   14374             :                      rdt.size;
   14375             :                   #endif
   14376             : 
   14377         250 :                   if (!rp(r0, r1, data_size))
   14378             :                   {
   14379           0 :                      return false;
   14380             :                   }
   14381             : 
   14382         250 :                   type_store_t& ts = typestore_list_[index];
   14383             : 
   14384         250 :                   ts.size = rp.cache_size();
   14385             :                   #ifndef exprtk_disable_string_capabilities
   14386         250 :                   if (ts.type == type_store_t::e_string)
   14387         250 :                      ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
   14388             :                   else
   14389             :                   #endif
   14390           0 :                      ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
   14391             :                }
   14392             :             }
   14393             : 
   14394        3603 :             return true;
   14395             :          }
   14396             : 
   14397             :          GenericFunction* function_;
   14398             :          mutable typestore_list_t typestore_list_;
   14399             : 
   14400             :       private:
   14401             : 
   14402             :          std::vector<expression_ptr> arg_list_;
   14403             :          std::vector<branch_t>       branch_;
   14404             :          std::vector<vecview_t>      vv_list_;
   14405             :          mutable tmp_vs_t            expr_as_vec1_store_;
   14406             :          mutable range_list_t        range_list_;
   14407             :          std::vector<std::size_t>    range_param_list_;
   14408             :       };
   14409             : 
   14410             :       #ifndef exprtk_disable_string_capabilities
   14411             :       template <typename T, typename StringFunction>
   14412             :       class string_function_node : public generic_function_node<T,StringFunction>
   14413             :                                  , public string_base_node<T>
   14414             :                                  , public range_interface <T>
   14415             :       {
   14416             :       public:
   14417             : 
   14418             :          typedef generic_function_node<T,StringFunction> gen_function_t;
   14419             :          typedef typename range_interface<T>::range_t range_t;
   14420             : 
   14421          72 :          string_function_node(StringFunction* func,
   14422             :                               const std::vector<typename gen_function_t::expression_ptr>& arg_list)
   14423          72 :          : gen_function_t(arg_list,func)
   14424             :          {
   14425          72 :             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
   14426          72 :             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
   14427          72 :             range_.cache.first  = range_.n0_c.second;
   14428          72 :             range_.cache.second = range_.n1_c.second;
   14429          72 :             assert(valid());
   14430          72 :          }
   14431             : 
   14432             :          inline bool operator <(const string_function_node<T,StringFunction>& fn) const
   14433             :          {
   14434             :             return this < (&fn);
   14435             :          }
   14436             : 
   14437           0 :          inline T value() const exprtk_override
   14438             :          {
   14439           0 :             if (gen_function_t::populate_value_list())
   14440             :             {
   14441             :                typedef typename StringFunction::parameter_list_t parameter_list_t;
   14442             : 
   14443             :                const T result =
   14444           0 :                   (*gen_function_t::function_)
   14445           0 :                   (
   14446           0 :                      ret_string_,
   14447           0 :                      parameter_list_t(gen_function_t::typestore_list_)
   14448             :                   );
   14449             : 
   14450           0 :                range_.n1_c.second  = ret_string_.size();
   14451           0 :                range_.cache.second = range_.n1_c.second;
   14452             : 
   14453           0 :                return result;
   14454             :             }
   14455             : 
   14456           0 :             return std::numeric_limits<T>::quiet_NaN();
   14457             :          }
   14458             : 
   14459           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14460             :          {
   14461           0 :             return expression_node<T>::e_strfunction;
   14462             :          }
   14463             : 
   14464         414 :          inline bool valid() const exprtk_override
   14465             :          {
   14466         414 :             return gen_function_t::function_;
   14467             :          }
   14468             : 
   14469           6 :          std::string str() const exprtk_override
   14470             :          {
   14471           6 :             return ret_string_;
   14472             :          }
   14473             : 
   14474          66 :          char_cptr base() const exprtk_override
   14475             :          {
   14476          66 :            return &ret_string_[0];
   14477             :          }
   14478             : 
   14479          72 :          std::size_t size() const exprtk_override
   14480             :          {
   14481          72 :             return ret_string_.size();
   14482             :          }
   14483             : 
   14484          72 :          range_t& range_ref() exprtk_override
   14485             :          {
   14486          72 :             return range_;
   14487             :          }
   14488             : 
   14489           0 :          const range_t& range_ref() const exprtk_override
   14490             :          {
   14491           0 :             return range_;
   14492             :          }
   14493             : 
   14494             :       protected:
   14495             : 
   14496             :          mutable range_t     range_;
   14497             :          mutable std::string ret_string_;
   14498             :       };
   14499             :       #endif
   14500             : 
   14501             :       template <typename T, typename GenericFunction>
   14502             :       class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
   14503             :       {
   14504             :       public:
   14505             : 
   14506             :          typedef generic_function_node<T,GenericFunction> gen_function_t;
   14507             :          typedef typename gen_function_t::range_t         range_t;
   14508             : 
   14509        1804 :          multimode_genfunction_node(GenericFunction* func,
   14510             :                                     const std::size_t& param_seq_index,
   14511             :                                     const std::vector<typename gen_function_t::expression_ptr>& arg_list)
   14512             :          : gen_function_t(arg_list,func)
   14513        1804 :          , param_seq_index_(param_seq_index)
   14514        1804 :          {}
   14515             : 
   14516        3380 :          inline T value() const exprtk_override
   14517             :          {
   14518        3380 :             assert(gen_function_t::valid());
   14519             : 
   14520        3380 :             if (gen_function_t::populate_value_list())
   14521             :             {
   14522             :                typedef typename GenericFunction::parameter_list_t parameter_list_t;
   14523             : 
   14524             :                return
   14525        3380 :                   (*gen_function_t::function_)
   14526        3380 :                   (
   14527        3380 :                      param_seq_index_,
   14528        3380 :                      parameter_list_t(gen_function_t::typestore_list_)
   14529        3380 :                   );
   14530             :             }
   14531             : 
   14532           0 :             return std::numeric_limits<T>::quiet_NaN();
   14533             :          }
   14534             : 
   14535       26671 :          inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
   14536             :          {
   14537       26671 :             return expression_node<T>::e_genfunction;
   14538             :          }
   14539             : 
   14540             :       private:
   14541             : 
   14542             :          std::size_t param_seq_index_;
   14543             :       };
   14544             : 
   14545             :       #ifndef exprtk_disable_string_capabilities
   14546             :       template <typename T, typename StringFunction>
   14547             :       class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction>
   14548             :       {
   14549             :       public:
   14550             : 
   14551             :          typedef string_function_node<T,StringFunction> str_function_t;
   14552             :          typedef typename str_function_t::range_t range_t;
   14553             : 
   14554          72 :          multimode_strfunction_node(StringFunction* func,
   14555             :                                     const std::size_t& param_seq_index,
   14556             :                                     const std::vector<typename str_function_t::expression_ptr>& arg_list)
   14557             :          : str_function_t(func,arg_list)
   14558          72 :          , param_seq_index_(param_seq_index)
   14559          72 :          {}
   14560             : 
   14561          72 :          inline T value() const exprtk_override
   14562             :          {
   14563          72 :             if (str_function_t::populate_value_list())
   14564             :             {
   14565             :                typedef typename StringFunction::parameter_list_t parameter_list_t;
   14566             : 
   14567             :                const T result =
   14568          72 :                   (*str_function_t::function_)
   14569         216 :                   (
   14570          72 :                      param_seq_index_,
   14571          72 :                      str_function_t::ret_string_,
   14572          72 :                      parameter_list_t(str_function_t::typestore_list_)
   14573             :                   );
   14574             : 
   14575          72 :                str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size();
   14576          72 :                str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
   14577             : 
   14578          72 :                return result;
   14579             :             }
   14580             : 
   14581           0 :             return std::numeric_limits<T>::quiet_NaN();
   14582             :          }
   14583             : 
   14584         984 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14585             :          {
   14586         984 :             return expression_node<T>::e_strfunction;
   14587             :          }
   14588             : 
   14589             :       private:
   14590             : 
   14591             :          const std::size_t param_seq_index_;
   14592             :       };
   14593             :       #endif
   14594             : 
   14595             :       class return_exception {};
   14596             : 
   14597             :       template <typename T>
   14598             :       class null_igenfunc
   14599             :       {
   14600             :       public:
   14601             : 
   14602             :          virtual ~null_igenfunc()
   14603             :          {}
   14604             : 
   14605             :          typedef type_store<T> generic_type;
   14606             :          typedef typename generic_type::parameter_list parameter_list_t;
   14607             : 
   14608             :          inline virtual T operator() (parameter_list_t)
   14609             :          {
   14610             :             return std::numeric_limits<T>::quiet_NaN();
   14611             :          }
   14612             :       };
   14613             : 
   14614             :       #ifndef exprtk_disable_return_statement
   14615             :       template <typename T>
   14616             :       class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> >
   14617             :       {
   14618             :       public:
   14619             : 
   14620             :          typedef results_context<T>   results_context_t;
   14621             :          typedef null_igenfunc<T>     igeneric_function_t;
   14622             :          typedef igeneric_function_t* igeneric_function_ptr;
   14623             :          typedef generic_function_node<T,igeneric_function_t> gen_function_t;
   14624             : 
   14625         116 :          return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
   14626             :                      results_context_t& rc)
   14627             :          : gen_function_t  (arg_list)
   14628         116 :          , results_context_(&rc)
   14629         116 :          {}
   14630             : 
   14631          31 :          inline T value() const exprtk_override
   14632             :          {
   14633          31 :             if (
   14634          62 :                  (0 != results_context_) &&
   14635          31 :                  gen_function_t::populate_value_list()
   14636             :                )
   14637             :             {
   14638             :                typedef typename type_store<T>::parameter_list parameter_list_t;
   14639             : 
   14640          31 :                results_context_->
   14641          31 :                   assign(parameter_list_t(gen_function_t::typestore_list_));
   14642             : 
   14643          31 :                throw return_exception();
   14644             :             }
   14645             : 
   14646           0 :             return std::numeric_limits<T>::quiet_NaN();
   14647             :          }
   14648             : 
   14649         542 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14650             :          {
   14651         542 :             return expression_node<T>::e_return;
   14652             :          }
   14653             : 
   14654         162 :          inline bool valid() const exprtk_override
   14655             :          {
   14656         162 :             return results_context_;
   14657             :          }
   14658             : 
   14659             :       private:
   14660             : 
   14661             :          results_context_t* results_context_;
   14662             :       };
   14663             : 
   14664             :       template <typename T>
   14665             :       class return_envelope_node exprtk_final : public expression_node<T>
   14666             :       {
   14667             :       public:
   14668             : 
   14669             :          typedef expression_node<T>* expression_ptr;
   14670             :          typedef results_context<T>  results_context_t;
   14671             :          typedef std::pair<expression_ptr,bool> branch_t;
   14672             : 
   14673         111 :          return_envelope_node(expression_ptr body, results_context_t& rc)
   14674         111 :          : results_context_(&rc  )
   14675         111 :          , return_invoked_ (false)
   14676             :          {
   14677         111 :             construct_branch_pair(body_, body);
   14678         111 :             assert(valid());
   14679         111 :          }
   14680             : 
   14681         111 :          inline T value() const exprtk_override
   14682             :          {
   14683             :             try
   14684             :             {
   14685         111 :                return_invoked_ = false;
   14686         111 :                results_context_->clear();
   14687             : 
   14688         111 :                return body_.first->value();
   14689             :             }
   14690          31 :             catch(const return_exception&)
   14691             :             {
   14692          31 :                return_invoked_ = true;
   14693             : 
   14694          31 :                return std::numeric_limits<T>::quiet_NaN();
   14695             :             }
   14696             :          }
   14697             : 
   14698         222 :          inline typename expression_node<T>::node_type type() const exprtk_override
   14699             :          {
   14700         222 :             return expression_node<T>::e_retenv;
   14701             :          }
   14702             : 
   14703         111 :          inline bool valid() const exprtk_override
   14704             :          {
   14705         111 :             return results_context_ && body_.first;
   14706             :          }
   14707             : 
   14708         111 :          inline bool* retinvk_ptr()
   14709             :          {
   14710         111 :             return &return_invoked_;
   14711             :          }
   14712             : 
   14713         111 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   14714             :          {
   14715         111 :             expression_node<T>::ndb_t::collect(body_, node_delete_list);
   14716         111 :          }
   14717             : 
   14718         111 :          std::size_t node_depth() const exprtk_override
   14719             :          {
   14720         111 :             return expression_node<T>::ndb_t::compute_node_depth(body_);
   14721             :          }
   14722             : 
   14723             :       private:
   14724             : 
   14725             :          results_context_t* results_context_;
   14726             :          mutable bool        return_invoked_;
   14727             :          branch_t                      body_;
   14728             :       };
   14729             :       #endif
   14730             : 
   14731             :       #define exprtk_define_unary_op(OpName)                    \
   14732             :       template <typename T>                                     \
   14733             :       struct OpName##_op                                        \
   14734             :       {                                                         \
   14735             :          typedef typename functor_t<T>::Type Type;              \
   14736             :          typedef typename expression_node<T>::node_type node_t; \
   14737             :                                                                 \
   14738             :          static inline T process(Type v)                        \
   14739             :          {                                                      \
   14740             :             return numeric:: OpName (v);                        \
   14741             :          }                                                      \
   14742             :                                                                 \
   14743             :          static inline node_t type()                            \
   14744             :          {                                                      \
   14745             :             return expression_node<T>::e_##OpName;              \
   14746             :          }                                                      \
   14747             :                                                                 \
   14748             :          static inline details::operator_type operation()       \
   14749             :          {                                                      \
   14750             :             return details::e_##OpName;                         \
   14751             :          }                                                      \
   14752             :       };                                                        \
   14753             : 
   14754    11109658 :       exprtk_define_unary_op(abs  )
   14755        1560 :       exprtk_define_unary_op(acos )
   14756        1740 :       exprtk_define_unary_op(acosh)
   14757        1740 :       exprtk_define_unary_op(asin )
   14758        1800 :       exprtk_define_unary_op(asinh)
   14759        1800 :       exprtk_define_unary_op(atan )
   14760           0 :       exprtk_define_unary_op(atanh)
   14761        1440 :       exprtk_define_unary_op(ceil )
   14762    40030707 :       exprtk_define_unary_op(cos  )
   14763        1740 :       exprtk_define_unary_op(cosh )
   14764        1806 :       exprtk_define_unary_op(cot  )
   14765        1560 :       exprtk_define_unary_op(csc  )
   14766        1440 :       exprtk_define_unary_op(d2g  )
   14767        1800 :       exprtk_define_unary_op(d2r  )
   14768    30001450 :       exprtk_define_unary_op(erf  )
   14769    30001570 :       exprtk_define_unary_op(erfc )
   14770        1800 :       exprtk_define_unary_op(exp  )
   14771        1560 :       exprtk_define_unary_op(expm1)
   14772        1440 :       exprtk_define_unary_op(floor)
   14773        2604 :       exprtk_define_unary_op(frac )
   14774        1560 :       exprtk_define_unary_op(g2d  )
   14775        3070 :       exprtk_define_unary_op(log  )
   14776        3190 :       exprtk_define_unary_op(log10)
   14777           0 :       exprtk_define_unary_op(log2 )
   14778        1440 :       exprtk_define_unary_op(log1p)
   14779           0 :       exprtk_define_unary_op(ncdf )
   14780      137006 :       exprtk_define_unary_op(neg  )
   14781         112 :       exprtk_define_unary_op(notl )
   14782           0 :       exprtk_define_unary_op(pos  )
   14783        1740 :       exprtk_define_unary_op(r2d  )
   14784        1800 :       exprtk_define_unary_op(round)
   14785        1440 :       exprtk_define_unary_op(sec  )
   14786        4098 :       exprtk_define_unary_op(sgn  )
   14787   144367544 :       exprtk_define_unary_op(sin  )
   14788           0 :       exprtk_define_unary_op(sinc )
   14789        1560 :       exprtk_define_unary_op(sinh )
   14790     6003291 :       exprtk_define_unary_op(sqrt )
   14791      290673 :       exprtk_define_unary_op(tan  )
   14792        1740 :       exprtk_define_unary_op(tanh )
   14793         940 :       exprtk_define_unary_op(trunc)
   14794             :       #undef exprtk_define_unary_op
   14795             : 
   14796             :       template <typename T>
   14797             :       struct opr_base
   14798             :       {
   14799             :          typedef typename details::functor_t<T>::Type    Type;
   14800             :          typedef typename details::functor_t<T>::RefType RefType;
   14801             :          typedef typename details::functor_t<T> functor_t;
   14802             :          typedef typename functor_t::qfunc_t    quaternary_functor_t;
   14803             :          typedef typename functor_t::tfunc_t    trinary_functor_t;
   14804             :          typedef typename functor_t::bfunc_t    binary_functor_t;
   14805             :          typedef typename functor_t::ufunc_t    unary_functor_t;
   14806             :       };
   14807             : 
   14808             :       template <typename T>
   14809             :       struct add_op : public opr_base<T>
   14810             :       {
   14811             :          typedef typename opr_base<T>::Type    Type;
   14812             :          typedef typename opr_base<T>::RefType RefType;
   14813             : 
   14814   255241015 :          static inline T process(Type t1, Type t2) { return t1 + t2; }
   14815             :          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
   14816        5478 :          static inline void assign(RefType t1, Type t2) { t1 += t2; }
   14817     1754103 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
   14818      118096 :          static inline details::operator_type operation() { return details::e_add; }
   14819             :       };
   14820             : 
   14821             :       template <typename T>
   14822             :       struct mul_op : public opr_base<T>
   14823             :       {
   14824             :          typedef typename opr_base<T>::Type    Type;
   14825             :          typedef typename opr_base<T>::RefType RefType;
   14826             : 
   14827   895463476 :          static inline T process(Type t1, Type t2) { return t1 * t2; }
   14828             :          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
   14829         240 :          static inline void assign(RefType t1, Type t2) { t1 *= t2; }
   14830     3948750 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
   14831      211943 :          static inline details::operator_type operation() { return details::e_mul; }
   14832             :       };
   14833             : 
   14834             :       template <typename T>
   14835             :       struct sub_op : public opr_base<T>
   14836             :       {
   14837             :          typedef typename opr_base<T>::Type    Type;
   14838             :          typedef typename opr_base<T>::RefType RefType;
   14839             : 
   14840   445980346 :          static inline T process(Type t1, Type t2) { return t1 - t2; }
   14841             :          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
   14842         959 :          static inline void assign(RefType t1, Type t2) { t1 -= t2; }
   14843     1580599 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
   14844      116071 :          static inline details::operator_type operation() { return details::e_sub; }
   14845             :       };
   14846             : 
   14847             :       template <typename T>
   14848             :       struct div_op : public opr_base<T>
   14849             :       {
   14850             :          typedef typename opr_base<T>::Type    Type;
   14851             :          typedef typename opr_base<T>::RefType RefType;
   14852             : 
   14853   400186030 :          static inline T process(Type t1, Type t2) { return t1 / t2; }
   14854             :          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
   14855         240 :          static inline void assign(RefType t1, Type t2) { t1 /= t2; }
   14856     3003234 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
   14857      182838 :          static inline details::operator_type operation() { return details::e_div; }
   14858             :       };
   14859             : 
   14860             :       template <typename T>
   14861             :       struct mod_op : public opr_base<T>
   14862             :       {
   14863             :          typedef typename opr_base<T>::Type    Type;
   14864             :          typedef typename opr_base<T>::RefType RefType;
   14865             : 
   14866      118103 :          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
   14867           0 :          static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
   14868         118 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
   14869           6 :          static inline details::operator_type operation() { return details::e_mod; }
   14870             :       };
   14871             : 
   14872             :       template <typename T>
   14873             :       struct pow_op : public opr_base<T>
   14874             :       {
   14875             :          typedef typename opr_base<T>::Type    Type;
   14876             :          typedef typename opr_base<T>::RefType RefType;
   14877             : 
   14878        1380 :          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
   14879             :          static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
   14880        3714 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
   14881         406 :          static inline details::operator_type operation() { return details::e_pow; }
   14882             :       };
   14883             : 
   14884             :       template <typename T>
   14885             :       struct lt_op : public opr_base<T>
   14886             :       {
   14887             :          typedef typename opr_base<T>::Type Type;
   14888             : 
   14889    43491219 :          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
   14890         656 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
   14891       16070 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
   14892         121 :          static inline details::operator_type operation() { return details::e_lt; }
   14893             :       };
   14894             : 
   14895             :       template <typename T>
   14896             :       struct lte_op : public opr_base<T>
   14897             :       {
   14898             :          typedef typename opr_base<T>::Type Type;
   14899             : 
   14900    60009490 :          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
   14901         155 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
   14902       13274 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
   14903           0 :          static inline details::operator_type operation() { return details::e_lte; }
   14904             :       };
   14905             : 
   14906             :       template <typename T>
   14907             :       struct gt_op : public opr_base<T>
   14908             :       {
   14909             :          typedef typename opr_base<T>::Type Type;
   14910             : 
   14911       39008 :          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
   14912         655 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
   14913       17862 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
   14914         151 :          static inline details::operator_type operation() { return details::e_gt; }
   14915             :       };
   14916             : 
   14917             :       template <typename T>
   14918             :       struct gte_op : public opr_base<T>
   14919             :       {
   14920             :          typedef typename opr_base<T>::Type Type;
   14921             : 
   14922         675 :          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
   14923         155 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
   14924        1480 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
   14925           0 :          static inline details::operator_type operation() { return details::e_gte; }
   14926             :       };
   14927             : 
   14928             :       template <typename T>
   14929             :       struct eq_op : public opr_base<T>
   14930             :       {
   14931             :          typedef typename opr_base<T>::Type Type;
   14932    94976957 :          static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
   14933       25666 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
   14934      266475 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
   14935        5247 :          static inline details::operator_type operation() { return details::e_eq; }
   14936             :       };
   14937             : 
   14938             :       template <typename T>
   14939             :       struct equal_op : public opr_base<T>
   14940             :       {
   14941             :          typedef typename opr_base<T>::Type Type;
   14942             : 
   14943         360 :          static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
   14944             :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
   14945             :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
   14946             :          static inline details::operator_type operation() { return details::e_equal; }
   14947             :       };
   14948             : 
   14949             :       template <typename T>
   14950             :       struct ne_op : public opr_base<T>
   14951             :       {
   14952             :          typedef typename opr_base<T>::Type Type;
   14953             : 
   14954        1817 :          static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
   14955        2450 :          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
   14956       14060 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
   14957         120 :          static inline details::operator_type operation() { return details::e_ne; }
   14958             :       };
   14959             : 
   14960             :       template <typename T>
   14961             :       struct and_op : public opr_base<T>
   14962             :       {
   14963             :          typedef typename opr_base<T>::Type Type;
   14964             : 
   14965        8694 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
   14966         570 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
   14967           0 :          static inline details::operator_type operation() { return details::e_and; }
   14968             :       };
   14969             : 
   14970             :       template <typename T>
   14971             :       struct nand_op : public opr_base<T>
   14972             :       {
   14973             :          typedef typename opr_base<T>::Type Type;
   14974             : 
   14975           4 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
   14976          68 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
   14977           0 :          static inline details::operator_type operation() { return details::e_nand; }
   14978             :       };
   14979             : 
   14980             :       template <typename T>
   14981             :       struct or_op : public opr_base<T>
   14982             :       {
   14983             :          typedef typename opr_base<T>::Type Type;
   14984             : 
   14985    11406052 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
   14986         570 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
   14987           0 :          static inline details::operator_type operation() { return details::e_or; }
   14988             :       };
   14989             : 
   14990             :       template <typename T>
   14991             :       struct nor_op : public opr_base<T>
   14992             :       {
   14993             :          typedef typename opr_base<T>::Type Type;
   14994             : 
   14995           4 :          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
   14996          68 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
   14997           0 :          static inline details::operator_type operation() { return details::e_nor; }
   14998             :       };
   14999             : 
   15000             :       template <typename T>
   15001             :       struct xor_op : public opr_base<T>
   15002             :       {
   15003             :          typedef typename opr_base<T>::Type Type;
   15004             : 
   15005          25 :          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
   15006           0 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
   15007           0 :          static inline details::operator_type operation() { return details::e_xor; }
   15008             :       };
   15009             : 
   15010             :       template <typename T>
   15011             :       struct xnor_op : public opr_base<T>
   15012             :       {
   15013             :          typedef typename opr_base<T>::Type Type;
   15014             : 
   15015           0 :          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
   15016           0 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
   15017           0 :          static inline details::operator_type operation() { return details::e_xnor; }
   15018             :       };
   15019             : 
   15020             :       template <typename T>
   15021             :       struct in_op : public opr_base<T>
   15022             :       {
   15023             :          typedef typename opr_base<T>::Type Type;
   15024             : 
   15025             :          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
   15026         760 :          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
   15027        9300 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
   15028           0 :          static inline details::operator_type operation() { return details::e_in; }
   15029             :       };
   15030             : 
   15031             :       template <typename T>
   15032             :       struct like_op : public opr_base<T>
   15033             :       {
   15034             :          typedef typename opr_base<T>::Type Type;
   15035             : 
   15036             :          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
   15037        2965 :          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
   15038       18550 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
   15039           0 :          static inline details::operator_type operation() { return details::e_like; }
   15040             :       };
   15041             : 
   15042             :       template <typename T>
   15043             :       struct ilike_op : public opr_base<T>
   15044             :       {
   15045             :          typedef typename opr_base<T>::Type Type;
   15046             : 
   15047             :          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
   15048        2965 :          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
   15049       18550 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
   15050           0 :          static inline details::operator_type operation() { return details::e_ilike; }
   15051             :       };
   15052             : 
   15053             :       template <typename T>
   15054             :       struct inrange_op : public opr_base<T>
   15055             :       {
   15056             :          typedef typename opr_base<T>::Type Type;
   15057             : 
   15058             :          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
   15059         300 :          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
   15060             :          {
   15061         300 :             return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
   15062             :          }
   15063        1500 :          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
   15064           0 :          static inline details::operator_type operation() { return details::e_inrange; }
   15065             :       };
   15066             : 
   15067             :       template <typename T>
   15068             :       inline T value(details::expression_node<T>* n)
   15069             :       {
   15070             :          return n->value();
   15071             :       }
   15072             : 
   15073             :       template <typename T>
   15074    31817168 :       inline T value(std::pair<details::expression_node<T>*,bool> n)
   15075             :       {
   15076    31817168 :          return n.first->value();
   15077             :       }
   15078             : 
   15079             :       template <typename T>
   15080        5111 :       inline T value(const T* t)
   15081             :       {
   15082        5111 :          return (*t);
   15083             :       }
   15084             : 
   15085             :       template <typename T>
   15086             :       inline T value(const T& t)
   15087             :       {
   15088             :          return t;
   15089             :       }
   15090             : 
   15091             :       template <typename T>
   15092             :       struct vararg_add_op exprtk_final : public opr_base<T>
   15093             :       {
   15094             :          typedef typename opr_base<T>::Type Type;
   15095             : 
   15096             :          template <typename Type,
   15097             :                    typename Allocator,
   15098             :                    template <typename, typename> class Sequence>
   15099         191 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15100             :          {
   15101         191 :             switch (arg_list.size())
   15102             :             {
   15103           0 :                case 0  : return T(0);
   15104           0 :                case 1  : return process_1(arg_list);
   15105          30 :                case 2  : return process_2(arg_list);
   15106          30 :                case 3  : return process_3(arg_list);
   15107          30 :                case 4  : return process_4(arg_list);
   15108          30 :                case 5  : return process_5(arg_list);
   15109          71 :                default :
   15110             :                          {
   15111          71 :                             T result = T(0);
   15112             : 
   15113         569 :                             for (std::size_t i = 0; i < arg_list.size(); ++i)
   15114             :                             {
   15115         498 :                                result += value(arg_list[i]);
   15116             :                             }
   15117             : 
   15118          71 :                             return result;
   15119             :                          }
   15120             :             }
   15121             :          }
   15122             : 
   15123             :          template <typename Sequence>
   15124           0 :          static inline T process_1(const Sequence& arg_list)
   15125             :          {
   15126           0 :             return value(arg_list[0]);
   15127             :          }
   15128             : 
   15129             :          template <typename Sequence>
   15130          30 :          static inline T process_2(const Sequence& arg_list)
   15131             :          {
   15132          30 :             return value(arg_list[0]) + value(arg_list[1]);
   15133             :          }
   15134             : 
   15135             :          template <typename Sequence>
   15136          30 :          static inline T process_3(const Sequence& arg_list)
   15137             :          {
   15138          30 :             return value(arg_list[0]) + value(arg_list[1]) +
   15139          30 :                    value(arg_list[2]) ;
   15140             :          }
   15141             : 
   15142             :          template <typename Sequence>
   15143          30 :          static inline T process_4(const Sequence& arg_list)
   15144             :          {
   15145          30 :             return value(arg_list[0]) + value(arg_list[1]) +
   15146          30 :                    value(arg_list[2]) + value(arg_list[3]) ;
   15147             :          }
   15148             : 
   15149             :          template <typename Sequence>
   15150          30 :          static inline T process_5(const Sequence& arg_list)
   15151             :          {
   15152          30 :             return value(arg_list[0]) + value(arg_list[1]) +
   15153          30 :                    value(arg_list[2]) + value(arg_list[3]) +
   15154          30 :                    value(arg_list[4]) ;
   15155             :          }
   15156             :       };
   15157             : 
   15158             :       template <typename T>
   15159             :       struct vararg_mul_op exprtk_final : public opr_base<T>
   15160             :       {
   15161             :          typedef typename opr_base<T>::Type Type;
   15162             : 
   15163             :          template <typename Type,
   15164             :                    typename Allocator,
   15165             :                    template <typename, typename> class Sequence>
   15166         164 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15167             :          {
   15168         164 :             switch (arg_list.size())
   15169             :             {
   15170           0 :                case 0  : return T(0);
   15171           0 :                case 1  : return process_1(arg_list);
   15172          30 :                case 2  : return process_2(arg_list);
   15173          30 :                case 3  : return process_3(arg_list);
   15174          30 :                case 4  : return process_4(arg_list);
   15175          30 :                case 5  : return process_5(arg_list);
   15176          44 :                default :
   15177             :                          {
   15178          44 :                             T result = T(value(arg_list[0]));
   15179             : 
   15180         304 :                             for (std::size_t i = 1; i < arg_list.size(); ++i)
   15181             :                             {
   15182         260 :                                result *= value(arg_list[i]);
   15183             :                             }
   15184             : 
   15185          44 :                             return result;
   15186             :                          }
   15187             :             }
   15188             :          }
   15189             : 
   15190             :          template <typename Sequence>
   15191           0 :          static inline T process_1(const Sequence& arg_list)
   15192             :          {
   15193           0 :             return value(arg_list[0]);
   15194             :          }
   15195             : 
   15196             :          template <typename Sequence>
   15197          30 :          static inline T process_2(const Sequence& arg_list)
   15198             :          {
   15199          30 :             return value(arg_list[0]) * value(arg_list[1]);
   15200             :          }
   15201             : 
   15202             :          template <typename Sequence>
   15203          30 :          static inline T process_3(const Sequence& arg_list)
   15204             :          {
   15205          30 :             return value(arg_list[0]) * value(arg_list[1]) *
   15206          30 :                    value(arg_list[2]) ;
   15207             :          }
   15208             : 
   15209             :          template <typename Sequence>
   15210          30 :          static inline T process_4(const Sequence& arg_list)
   15211             :          {
   15212          30 :             return value(arg_list[0]) * value(arg_list[1]) *
   15213          30 :                    value(arg_list[2]) * value(arg_list[3]) ;
   15214             :          }
   15215             : 
   15216             :          template <typename Sequence>
   15217          30 :          static inline T process_5(const Sequence& arg_list)
   15218             :          {
   15219          30 :             return value(arg_list[0]) * value(arg_list[1]) *
   15220          30 :                    value(arg_list[2]) * value(arg_list[3]) *
   15221          30 :                    value(arg_list[4]) ;
   15222             :          }
   15223             :       };
   15224             : 
   15225             :       template <typename T>
   15226             :       struct vararg_avg_op exprtk_final : public opr_base<T>
   15227             :       {
   15228             :          typedef typename opr_base<T>::Type Type;
   15229             : 
   15230             :          template <typename Type,
   15231             :                    typename Allocator,
   15232             :                    template <typename, typename> class Sequence>
   15233         247 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15234             :          {
   15235         247 :             switch (arg_list.size())
   15236             :             {
   15237           0 :                case 0  : return T(0);
   15238           0 :                case 1  : return process_1(arg_list);
   15239          55 :                case 2  : return process_2(arg_list);
   15240          55 :                case 3  : return process_3(arg_list);
   15241          55 :                case 4  : return process_4(arg_list);
   15242          55 :                case 5  : return process_5(arg_list);
   15243          27 :                default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size());
   15244             :             }
   15245             :          }
   15246             : 
   15247             :          template <typename Sequence>
   15248           0 :          static inline T process_1(const Sequence& arg_list)
   15249             :          {
   15250           0 :             return value(arg_list[0]);
   15251             :          }
   15252             : 
   15253             :          template <typename Sequence>
   15254          55 :          static inline T process_2(const Sequence& arg_list)
   15255             :          {
   15256          55 :             return (value(arg_list[0]) + value(arg_list[1])) / T(2);
   15257             :          }
   15258             : 
   15259             :          template <typename Sequence>
   15260          55 :          static inline T process_3(const Sequence& arg_list)
   15261             :          {
   15262          55 :             return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
   15263             :          }
   15264             : 
   15265             :          template <typename Sequence>
   15266          55 :          static inline T process_4(const Sequence& arg_list)
   15267             :          {
   15268          55 :             return (value(arg_list[0]) + value(arg_list[1]) +
   15269          55 :                     value(arg_list[2]) + value(arg_list[3])) / T(4);
   15270             :          }
   15271             : 
   15272             :          template <typename Sequence>
   15273          55 :          static inline T process_5(const Sequence& arg_list)
   15274             :          {
   15275          55 :             return (value(arg_list[0]) + value(arg_list[1]) +
   15276          55 :                     value(arg_list[2]) + value(arg_list[3]) +
   15277          55 :                     value(arg_list[4])) / T(5);
   15278             :          }
   15279             :       };
   15280             : 
   15281             :       template <typename T>
   15282             :       struct vararg_min_op exprtk_final : public opr_base<T>
   15283             :       {
   15284             :          typedef typename opr_base<T>::Type Type;
   15285             : 
   15286             :          template <typename Type,
   15287             :                    typename Allocator,
   15288             :                    template <typename, typename> class Sequence>
   15289        4924 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15290             :          {
   15291        4924 :             switch (arg_list.size())
   15292             :             {
   15293           0 :                case 0  : return T(0);
   15294           0 :                case 1  : return process_1(arg_list);
   15295        4690 :                case 2  : return process_2(arg_list);
   15296          82 :                case 3  : return process_3(arg_list);
   15297          55 :                case 4  : return process_4(arg_list);
   15298          56 :                case 5  : return process_5(arg_list);
   15299          41 :                default :
   15300             :                          {
   15301          41 :                             T result = T(value(arg_list[0]));
   15302             : 
   15303         278 :                             for (std::size_t i = 1; i < arg_list.size(); ++i)
   15304             :                             {
   15305         237 :                                const T v = value(arg_list[i]);
   15306             : 
   15307         237 :                                if (v < result)
   15308           1 :                                   result = v;
   15309             :                             }
   15310             : 
   15311          41 :                             return result;
   15312             :                          }
   15313             :             }
   15314             :          }
   15315             : 
   15316             :          template <typename Sequence>
   15317           0 :          static inline T process_1(const Sequence& arg_list)
   15318             :          {
   15319           0 :             return value(arg_list[0]);
   15320             :          }
   15321             : 
   15322             :          template <typename Sequence>
   15323        4690 :          static inline T process_2(const Sequence& arg_list)
   15324             :          {
   15325        4690 :             return std::min<T>(value(arg_list[0]),value(arg_list[1]));
   15326             :          }
   15327             : 
   15328             :          template <typename Sequence>
   15329          82 :          static inline T process_3(const Sequence& arg_list)
   15330             :          {
   15331          82 :             return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
   15332             :          }
   15333             : 
   15334             :          template <typename Sequence>
   15335          55 :          static inline T process_4(const Sequence& arg_list)
   15336             :          {
   15337          55 :             return std::min<T>(
   15338          55 :                         std::min<T>(value(arg_list[0]), value(arg_list[1])),
   15339         110 :                         std::min<T>(value(arg_list[2]), value(arg_list[3])));
   15340             :          }
   15341             : 
   15342             :          template <typename Sequence>
   15343          56 :          static inline T process_5(const Sequence& arg_list)
   15344             :          {
   15345          56 :             return std::min<T>(
   15346          56 :                    std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
   15347          56 :                                std::min<T>(value(arg_list[2]), value(arg_list[3]))),
   15348         112 :                                value(arg_list[4]));
   15349             :          }
   15350             :       };
   15351             : 
   15352             :       template <typename T>
   15353             :       struct vararg_max_op exprtk_final : public opr_base<T>
   15354             :       {
   15355             :          typedef typename opr_base<T>::Type Type;
   15356             : 
   15357             :          template <typename Type,
   15358             :                    typename Allocator,
   15359             :                    template <typename, typename> class Sequence>
   15360         307 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15361             :          {
   15362         307 :             switch (arg_list.size())
   15363             :             {
   15364           0 :                case 0  : return T(0);
   15365           0 :                case 1  : return process_1(arg_list);
   15366         100 :                case 2  : return process_2(arg_list);
   15367          55 :                case 3  : return process_3(arg_list);
   15368          55 :                case 4  : return process_4(arg_list);
   15369          56 :                case 5  : return process_5(arg_list);
   15370          41 :                default :
   15371             :                          {
   15372          41 :                             T result = T(value(arg_list[0]));
   15373             : 
   15374         278 :                             for (std::size_t i = 1; i < arg_list.size(); ++i)
   15375             :                             {
   15376         237 :                                const T v = value(arg_list[i]);
   15377             : 
   15378         237 :                                if (v > result)
   15379         237 :                                   result = v;
   15380             :                             }
   15381             : 
   15382          41 :                             return result;
   15383             :                          }
   15384             :             }
   15385             :          }
   15386             : 
   15387             :          template <typename Sequence>
   15388           0 :          static inline T process_1(const Sequence& arg_list)
   15389             :          {
   15390           0 :             return value(arg_list[0]);
   15391             :          }
   15392             : 
   15393             :          template <typename Sequence>
   15394         100 :          static inline T process_2(const Sequence& arg_list)
   15395             :          {
   15396         100 :             return std::max<T>(value(arg_list[0]),value(arg_list[1]));
   15397             :          }
   15398             : 
   15399             :          template <typename Sequence>
   15400          55 :          static inline T process_3(const Sequence& arg_list)
   15401             :          {
   15402          55 :             return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
   15403             :          }
   15404             : 
   15405             :          template <typename Sequence>
   15406          55 :          static inline T process_4(const Sequence& arg_list)
   15407             :          {
   15408          55 :             return std::max<T>(
   15409          55 :                         std::max<T>(value(arg_list[0]), value(arg_list[1])),
   15410         110 :                         std::max<T>(value(arg_list[2]), value(arg_list[3])));
   15411             :          }
   15412             : 
   15413             :          template <typename Sequence>
   15414          56 :          static inline T process_5(const Sequence& arg_list)
   15415             :          {
   15416          56 :             return std::max<T>(
   15417          56 :                    std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
   15418          56 :                                std::max<T>(value(arg_list[2]), value(arg_list[3]))),
   15419         112 :                                value(arg_list[4]));
   15420             :          }
   15421             :       };
   15422             : 
   15423             :       template <typename T>
   15424             :       struct vararg_mand_op exprtk_final : public opr_base<T>
   15425             :       {
   15426             :          typedef typename opr_base<T>::Type Type;
   15427             : 
   15428             :          template <typename Type,
   15429             :                    typename Allocator,
   15430             :                    template <typename, typename> class Sequence>
   15431         256 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15432             :          {
   15433         256 :             switch (arg_list.size())
   15434             :             {
   15435           0 :                case 1  : return process_1(arg_list);
   15436         249 :                case 2  : return process_2(arg_list);
   15437           2 :                case 3  : return process_3(arg_list);
   15438           2 :                case 4  : return process_4(arg_list);
   15439           2 :                case 5  : return process_5(arg_list);
   15440           1 :                default :
   15441             :                          {
   15442           6 :                             for (std::size_t i = 0; i < arg_list.size(); ++i)
   15443             :                             {
   15444           6 :                                if (std::equal_to<T>()(T(0), value(arg_list[i])))
   15445           1 :                                   return T(0);
   15446             :                             }
   15447             : 
   15448           0 :                             return T(1);
   15449             :                          }
   15450             :             }
   15451             :          }
   15452             : 
   15453             :          template <typename Sequence>
   15454           0 :          static inline T process_1(const Sequence& arg_list)
   15455             :          {
   15456           0 :             return std::not_equal_to<T>()
   15457           0 :                       (T(0), value(arg_list[0])) ? T(1) : T(0);
   15458             :          }
   15459             : 
   15460             :          template <typename Sequence>
   15461         249 :          static inline T process_2(const Sequence& arg_list)
   15462             :          {
   15463             :             return (
   15464         374 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   15465         374 :                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
   15466         614 :                    ) ? T(1) : T(0);
   15467             :          }
   15468             : 
   15469             :          template <typename Sequence>
   15470           2 :          static inline T process_3(const Sequence& arg_list)
   15471             :          {
   15472             :             return (
   15473           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   15474           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
   15475           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
   15476           4 :                    ) ? T(1) : T(0);
   15477             :          }
   15478             : 
   15479             :          template <typename Sequence>
   15480           2 :          static inline T process_4(const Sequence& arg_list)
   15481             :          {
   15482             :             return (
   15483           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   15484           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
   15485           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
   15486           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
   15487           4 :                    ) ? T(1) : T(0);
   15488             :          }
   15489             : 
   15490             :          template <typename Sequence>
   15491           2 :          static inline T process_5(const Sequence& arg_list)
   15492             :          {
   15493             :             return (
   15494           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
   15495           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
   15496           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
   15497           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
   15498           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
   15499           4 :                    ) ? T(1) : T(0);
   15500             :          }
   15501             :       };
   15502             : 
   15503             :       template <typename T>
   15504             :       struct vararg_mor_op exprtk_final : public opr_base<T>
   15505             :       {
   15506             :          typedef typename opr_base<T>::Type Type;
   15507             : 
   15508             :          template <typename Type,
   15509             :                    typename Allocator,
   15510             :                    template <typename, typename> class Sequence>
   15511         257 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15512             :          {
   15513         257 :             switch (arg_list.size())
   15514             :             {
   15515           0 :                case 1  : return process_1(arg_list);
   15516         250 :                case 2  : return process_2(arg_list);
   15517           3 :                case 3  : return process_3(arg_list);
   15518           1 :                case 4  : return process_4(arg_list);
   15519           1 :                case 5  : return process_5(arg_list);
   15520           2 :                default :
   15521             :                          {
   15522          15 :                             for (std::size_t i = 0; i < arg_list.size(); ++i)
   15523             :                             {
   15524          14 :                                if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
   15525           1 :                                   return T(1);
   15526             :                             }
   15527             : 
   15528           1 :                             return T(0);
   15529             :                          }
   15530             :             }
   15531             :          }
   15532             : 
   15533             :          template <typename Sequence>
   15534           0 :          static inline T process_1(const Sequence& arg_list)
   15535             :          {
   15536           0 :             return std::not_equal_to<T>()
   15537           0 :                       (T(0), value(arg_list[0])) ? T(1) : T(0);
   15538             :          }
   15539             : 
   15540             :          template <typename Sequence>
   15541         250 :          static inline T process_2(const Sequence& arg_list)
   15542             :          {
   15543             :             return (
   15544         375 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   15545         375 :                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
   15546         615 :                    ) ? T(1) : T(0);
   15547             :          }
   15548             : 
   15549             :          template <typename Sequence>
   15550           3 :          static inline T process_3(const Sequence& arg_list)
   15551             :          {
   15552             :             return (
   15553           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   15554           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
   15555           4 :                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
   15556           4 :                    ) ? T(1) : T(0);
   15557             :          }
   15558             : 
   15559             :          template <typename Sequence>
   15560           1 :          static inline T process_4(const Sequence& arg_list)
   15561             :          {
   15562             :             return (
   15563           1 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   15564           0 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
   15565           0 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
   15566           1 :                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
   15567           1 :                    ) ? T(1) : T(0);
   15568             :          }
   15569             : 
   15570             :          template <typename Sequence>
   15571           1 :          static inline T process_5(const Sequence& arg_list)
   15572             :          {
   15573             :             return (
   15574           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
   15575           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
   15576           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
   15577           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
   15578           2 :                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
   15579           2 :                    ) ? T(1) : T(0);
   15580             :          }
   15581             :       };
   15582             : 
   15583             :       template <typename T>
   15584             :       struct vararg_multi_op exprtk_final : public opr_base<T>
   15585             :       {
   15586             :          typedef typename opr_base<T>::Type Type;
   15587             : 
   15588             :          template <typename Type,
   15589             :                    typename Allocator,
   15590             :                    template <typename, typename> class Sequence>
   15591    10161582 :          static inline T process(const Sequence<Type,Allocator>& arg_list)
   15592             :          {
   15593    10161582 :             switch (arg_list.size())
   15594             :             {
   15595           0 :                case 0  : return std::numeric_limits<T>::quiet_NaN();
   15596          40 :                case 1  : return process_1(arg_list);
   15597     4655525 :                case 2  : return process_2(arg_list);
   15598       15057 :                case 3  : return process_3(arg_list);
   15599     5004324 :                case 4  : return process_4(arg_list);
   15600      486174 :                case 5  : return process_5(arg_list);
   15601         251 :                case 6  : return process_6(arg_list);
   15602           6 :                case 7  : return process_7(arg_list);
   15603         104 :                case 8  : return process_8(arg_list);
   15604         101 :                default :
   15605             :                         {
   15606         909 :                            for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
   15607             :                            {
   15608         808 :                               value(arg_list[i]);
   15609             :                            }
   15610         101 :                            return value(arg_list.back());
   15611             :                         }
   15612             :             }
   15613             :          }
   15614             : 
   15615             :          template <typename Sequence>
   15616          40 :          static inline T process_1(const Sequence& arg_list)
   15617             :          {
   15618          40 :             return value(arg_list[0]);
   15619             :          }
   15620             : 
   15621             :          template <typename Sequence>
   15622     4655525 :          static inline T process_2(const Sequence& arg_list)
   15623             :          {
   15624     4655525 :                    value(arg_list[0]);
   15625     4655475 :             return value(arg_list[1]);
   15626             :          }
   15627             : 
   15628             :          template <typename Sequence>
   15629       15057 :          static inline T process_3(const Sequence& arg_list)
   15630             :          {
   15631       15057 :                    value(arg_list[0]);
   15632       15007 :                    value(arg_list[1]);
   15633       14957 :             return value(arg_list[2]);
   15634             :          }
   15635             : 
   15636             :          template <typename Sequence>
   15637     5004324 :          static inline T process_4(const Sequence& arg_list)
   15638             :          {
   15639     5004324 :                    value(arg_list[0]);
   15640     5004324 :                    value(arg_list[1]);
   15641     5004324 :                    value(arg_list[2]);
   15642     5004324 :             return value(arg_list[3]);
   15643             :          }
   15644             : 
   15645             :          template <typename Sequence>
   15646      486174 :          static inline T process_5(const Sequence& arg_list)
   15647             :          {
   15648      486174 :                    value(arg_list[0]);
   15649      486174 :                    value(arg_list[1]);
   15650      486174 :                    value(arg_list[2]);
   15651      486174 :                    value(arg_list[3]);
   15652      486174 :             return value(arg_list[4]);
   15653             :          }
   15654             : 
   15655             :          template <typename Sequence>
   15656         251 :          static inline T process_6(const Sequence& arg_list)
   15657             :          {
   15658         251 :                    value(arg_list[0]);
   15659         251 :                    value(arg_list[1]);
   15660         251 :                    value(arg_list[2]);
   15661         251 :                    value(arg_list[3]);
   15662         251 :                    value(arg_list[4]);
   15663         251 :             return value(arg_list[5]);
   15664             :          }
   15665             : 
   15666             :          template <typename Sequence>
   15667           6 :          static inline T process_7(const Sequence& arg_list)
   15668             :          {
   15669           6 :                    value(arg_list[0]);
   15670           6 :                    value(arg_list[1]);
   15671           6 :                    value(arg_list[2]);
   15672           6 :                    value(arg_list[3]);
   15673           6 :                    value(arg_list[4]);
   15674           6 :                    value(arg_list[5]);
   15675           6 :             return value(arg_list[6]);
   15676             :          }
   15677             : 
   15678             :          template <typename Sequence>
   15679         104 :          static inline T process_8(const Sequence& arg_list)
   15680             :          {
   15681         104 :                    value(arg_list[0]);
   15682         104 :                    value(arg_list[1]);
   15683         104 :                    value(arg_list[2]);
   15684         104 :                    value(arg_list[3]);
   15685         104 :                    value(arg_list[4]);
   15686         104 :                    value(arg_list[5]);
   15687         104 :                    value(arg_list[6]);
   15688         104 :             return value(arg_list[7]);
   15689             :          }
   15690             :       };
   15691             : 
   15692             :       template <typename T>
   15693             :       struct vec_add_op
   15694             :       {
   15695             :          typedef vector_interface<T>* ivector_ptr;
   15696             : 
   15697        1920 :          static inline T process(const ivector_ptr v)
   15698             :          {
   15699        1920 :             const T* vec = v->vec()->vds().data();
   15700        1920 :             const std::size_t vec_size = v->size();
   15701             : 
   15702        1920 :             loop_unroll::details lud(vec_size);
   15703             : 
   15704        1920 :             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
   15705             :             {
   15706        1390 :                T result = T(0);
   15707        1390 :                int i    = 0;
   15708             : 
   15709        1390 :                switch (vec_size)
   15710             :                {
   15711             :                   #define case_stmt(N,fall_through) \
   15712             :                   case N : result += vec[i++];      \
   15713             :                   fall_through                      \
   15714             : 
   15715             :                   #ifndef exprtk_disable_superscalar_unroll
   15716          10 :                   case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
   15717          10 :                   case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
   15718          10 :                   case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
   15719          13 :                   case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
   15720         253 :                   case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
   15721         612 :                   case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
   15722             : 
   15723             :                   #endif
   15724        1312 :                   case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
   15725        1390 :                   case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
   15726             :                }
   15727             : 
   15728             :                #undef case_stmt
   15729             : 
   15730        1390 :                return result;
   15731             :             }
   15732             : 
   15733         530 :             T r[] = {
   15734             :                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
   15735             :                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
   15736             :                     };
   15737             : 
   15738         530 :             const T* upper_bound = vec + lud.upper_bound;
   15739             : 
   15740    25688060 :             while (vec < upper_bound)
   15741             :             {
   15742             :                #define exprtk_loop(N) \
   15743             :                r[N] += vec[N];        \
   15744             : 
   15745    25687530 :                exprtk_loop( 0) exprtk_loop( 1)
   15746    25687530 :                exprtk_loop( 2) exprtk_loop( 3)
   15747             :                #ifndef exprtk_disable_superscalar_unroll
   15748    25687530 :                exprtk_loop( 4) exprtk_loop( 5)
   15749    25687530 :                exprtk_loop( 6) exprtk_loop( 7)
   15750    25687530 :                exprtk_loop( 8) exprtk_loop( 9)
   15751    25687530 :                exprtk_loop(10) exprtk_loop(11)
   15752    25687530 :                exprtk_loop(12) exprtk_loop(13)
   15753    25687530 :                exprtk_loop(14) exprtk_loop(15)
   15754             :                #endif
   15755             : 
   15756    25687530 :                vec += lud.batch_size;
   15757             :             }
   15758             : 
   15759         530 :             int i = 0;
   15760             : 
   15761         530 :             switch (lud.remainder)
   15762             :             {
   15763             :                #define case_stmt(N,fall_through) \
   15764             :                case N : r[0] += vec[i++];        \
   15765             :                fall_through                      \
   15766             : 
   15767             :                #ifndef exprtk_disable_superscalar_unroll
   15768           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   15769           5 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   15770           5 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   15771           5 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   15772           5 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   15773           5 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   15774             :                #endif
   15775           5 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   15776          15 :                case_stmt( 1, (void)0;)
   15777             :             }
   15778             : 
   15779             :             #undef exprtk_loop
   15780             :             #undef case_stmt
   15781             : 
   15782         530 :             return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
   15783             :                    #ifndef exprtk_disable_superscalar_unroll
   15784         530 :                  + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
   15785         530 :                  + (r[ 8] + r[ 9] + r[10] + r[11])
   15786         530 :                  + (r[12] + r[13] + r[14] + r[15])
   15787             :                    #endif
   15788             :                    ;
   15789             :          }
   15790             :       };
   15791             : 
   15792             :       template <typename T>
   15793             :       struct vec_mul_op
   15794             :       {
   15795             :          typedef vector_interface<T>* ivector_ptr;
   15796             : 
   15797          30 :          static inline T process(const ivector_ptr v)
   15798             :          {
   15799          30 :             const T* vec = v->vec()->vds().data();
   15800          30 :             const std::size_t vec_size = v->vec()->size();
   15801             : 
   15802          30 :             loop_unroll::details lud(vec_size);
   15803             : 
   15804          30 :             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
   15805             :             {
   15806          10 :                T result = T(1);
   15807          10 :                int i    = 0;
   15808             : 
   15809          10 :                switch (vec_size)
   15810             :                {
   15811             :                   #define case_stmt(N,fall_through) \
   15812             :                   case N : result *= vec[i++];      \
   15813             :                   fall_through                      \
   15814             : 
   15815             :                   #ifndef exprtk_disable_superscalar_unroll
   15816          10 :                   case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
   15817          10 :                   case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
   15818          10 :                   case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
   15819          10 :                   case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
   15820          10 :                   case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
   15821          10 :                   case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
   15822             :                   #endif
   15823          10 :                   case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
   15824          10 :                   case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
   15825             :                }
   15826             : 
   15827             :                #undef case_stmt
   15828             : 
   15829          10 :                return result;
   15830             :             }
   15831             : 
   15832          20 :             T r[] = {
   15833             :                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
   15834             :                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
   15835             :                     };
   15836             : 
   15837          20 :             const T* upper_bound = vec + lud.upper_bound;
   15838             : 
   15839          50 :             while (vec < upper_bound)
   15840             :             {
   15841             :                #define exprtk_loop(N) \
   15842             :                r[N] *= vec[N];        \
   15843             : 
   15844          30 :                exprtk_loop( 0) exprtk_loop( 1)
   15845          30 :                exprtk_loop( 2) exprtk_loop( 3)
   15846             :                #ifndef exprtk_disable_superscalar_unroll
   15847          30 :                exprtk_loop( 4) exprtk_loop( 5)
   15848          30 :                exprtk_loop( 6) exprtk_loop( 7)
   15849          30 :                exprtk_loop( 8) exprtk_loop( 9)
   15850          30 :                exprtk_loop(10) exprtk_loop(11)
   15851          30 :                exprtk_loop(12) exprtk_loop(13)
   15852          30 :                exprtk_loop(14) exprtk_loop(15)
   15853             :                #endif
   15854             : 
   15855          30 :                vec += lud.batch_size;
   15856             :             }
   15857             : 
   15858          20 :             int i = 0;
   15859             : 
   15860          20 :             switch (lud.remainder)
   15861             :             {
   15862             :                #define case_stmt(N,fall_through) \
   15863             :                case N : r[0] *= vec[i++];        \
   15864             :                fall_through                      \
   15865             : 
   15866             :                #ifndef exprtk_disable_superscalar_unroll
   15867           0 :                case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
   15868           5 :                case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
   15869           5 :                case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
   15870           5 :                case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
   15871           5 :                case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
   15872           5 :                case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
   15873             :                #endif
   15874           5 :                case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
   15875          15 :                case_stmt( 1, (void)0;)
   15876             :             }
   15877             : 
   15878             :             #undef exprtk_loop
   15879             :             #undef case_stmt
   15880             : 
   15881          20 :             return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
   15882             :                    #ifndef exprtk_disable_superscalar_unroll
   15883          20 :                  * (r[ 4] * r[ 5] * r[ 6] * r[ 7])
   15884          20 :                  * (r[ 8] * r[ 9] * r[10] * r[11])
   15885          20 :                  * (r[12] * r[13] * r[14] * r[15])
   15886             :                    #endif
   15887             :                    ;
   15888             :          }
   15889             :       };
   15890             : 
   15891             :       template <typename T>
   15892             :       struct vec_avg_op
   15893             :       {
   15894             :          typedef vector_interface<T>* ivector_ptr;
   15895             : 
   15896          70 :          static inline T process(const ivector_ptr v)
   15897             :          {
   15898          70 :             const T vec_size = T(v->vec()->size());
   15899          70 :             return vec_add_op<T>::process(v) / vec_size;
   15900             :          }
   15901             :       };
   15902             : 
   15903             :       template <typename T>
   15904             :       struct vec_min_op
   15905             :       {
   15906             :          typedef vector_interface<T>* ivector_ptr;
   15907             : 
   15908          55 :          static inline T process(const ivector_ptr v)
   15909             :          {
   15910          55 :             const T* vec = v->vec()->vds().data();
   15911          55 :             const std::size_t vec_size = v->vec()->size();
   15912             : 
   15913          55 :             T result = vec[0];
   15914             : 
   15915         269 :             for (std::size_t i = 1; i < vec_size; ++i)
   15916             :             {
   15917         214 :                const T v_i = vec[i];
   15918             : 
   15919         214 :                if (v_i < result)
   15920          10 :                   result = v_i;
   15921             :             }
   15922             : 
   15923          55 :             return result;
   15924             :          }
   15925             :       };
   15926             : 
   15927             :       template <typename T>
   15928             :       struct vec_max_op
   15929             :       {
   15930             :          typedef vector_interface<T>* ivector_ptr;
   15931             : 
   15932          55 :          static inline T process(const ivector_ptr v)
   15933             :          {
   15934          55 :             const T* vec = v->vec()->vds().data();
   15935          55 :             const std::size_t vec_size = v->vec()->size();
   15936             : 
   15937          55 :             T result = vec[0];
   15938             : 
   15939         269 :             for (std::size_t i = 1; i < vec_size; ++i)
   15940             :             {
   15941         214 :                const T v_i = vec[i];
   15942             : 
   15943         214 :                if (v_i > result)
   15944         194 :                   result = v_i;
   15945             :             }
   15946             : 
   15947          55 :             return result;
   15948             :          }
   15949             :       };
   15950             : 
   15951             :       template <typename T>
   15952             :       class vov_base_node : public expression_node<T>
   15953             :       {
   15954             :       public:
   15955             : 
   15956      264321 :          virtual ~vov_base_node()
   15957      264321 :          {}
   15958             : 
   15959           0 :          inline virtual operator_type operation() const
   15960             :          {
   15961           0 :             return details::e_default;
   15962             :          }
   15963             : 
   15964             :          virtual const T& v0() const = 0;
   15965             : 
   15966             :          virtual const T& v1() const = 0;
   15967             :       };
   15968             : 
   15969             :       template <typename T>
   15970             :       class cov_base_node : public expression_node<T>
   15971             :       {
   15972             :       public:
   15973             : 
   15974      240251 :          virtual ~cov_base_node()
   15975      240251 :          {}
   15976             : 
   15977           0 :          inline virtual operator_type operation() const
   15978             :          {
   15979           0 :             return details::e_default;
   15980             :          }
   15981             : 
   15982             :          virtual const T c() const = 0;
   15983             : 
   15984             :          virtual const T& v() const = 0;
   15985             :       };
   15986             : 
   15987             :       template <typename T>
   15988             :       class voc_base_node : public expression_node<T>
   15989             :       {
   15990             :       public:
   15991             : 
   15992      283561 :          virtual ~voc_base_node()
   15993      283561 :          {}
   15994             : 
   15995           0 :          inline virtual operator_type operation() const
   15996             :          {
   15997           0 :             return details::e_default;
   15998             :          }
   15999             : 
   16000             :          virtual const T c() const = 0;
   16001             : 
   16002             :          virtual const T& v() const = 0;
   16003             :       };
   16004             : 
   16005             :       template <typename T>
   16006             :       class vob_base_node : public expression_node<T>
   16007             :       {
   16008             :       public:
   16009             : 
   16010       33759 :          virtual ~vob_base_node()
   16011       33759 :          {}
   16012             : 
   16013             :          virtual const T& v() const = 0;
   16014             :       };
   16015             : 
   16016             :       template <typename T>
   16017             :       class bov_base_node : public expression_node<T>
   16018             :       {
   16019             :       public:
   16020             : 
   16021      352766 :          virtual ~bov_base_node()
   16022      352766 :          {}
   16023             : 
   16024             :          virtual const T& v() const = 0;
   16025             :       };
   16026             : 
   16027             :       template <typename T>
   16028             :       class cob_base_node : public expression_node<T>
   16029             :       {
   16030             :       public:
   16031             : 
   16032       89183 :          virtual ~cob_base_node()
   16033       89183 :          {}
   16034             : 
   16035           0 :          inline virtual operator_type operation() const
   16036             :          {
   16037           0 :             return details::e_default;
   16038             :          }
   16039             : 
   16040             :          virtual const T c() const = 0;
   16041             : 
   16042             :          virtual void set_c(const T) = 0;
   16043             : 
   16044             :          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
   16045             :       };
   16046             : 
   16047             :       template <typename T>
   16048             :       class boc_base_node : public expression_node<T>
   16049             :       {
   16050             :       public:
   16051             : 
   16052      143891 :          virtual ~boc_base_node()
   16053      143891 :          {}
   16054             : 
   16055           0 :          inline virtual operator_type operation() const
   16056             :          {
   16057           0 :             return details::e_default;
   16058             :          }
   16059             : 
   16060             :          virtual const T c() const = 0;
   16061             : 
   16062             :          virtual void set_c(const T) = 0;
   16063             : 
   16064             :          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
   16065             :       };
   16066             : 
   16067             :       template <typename T>
   16068             :       class uv_base_node : public expression_node<T>
   16069             :       {
   16070             :       public:
   16071             : 
   16072        7697 :          virtual ~uv_base_node()
   16073        7697 :          {}
   16074             : 
   16075           0 :          inline virtual operator_type operation() const
   16076             :          {
   16077           0 :             return details::e_default;
   16078             :          }
   16079             : 
   16080             :          virtual const T& v() const = 0;
   16081             :       };
   16082             : 
   16083             :       template <typename T>
   16084             :       class sos_base_node : public expression_node<T>
   16085             :       {
   16086             :       public:
   16087             : 
   16088       30392 :          virtual ~sos_base_node()
   16089       30392 :          {}
   16090             : 
   16091           0 :          inline virtual operator_type operation() const
   16092             :          {
   16093           0 :             return details::e_default;
   16094             :          }
   16095             :       };
   16096             : 
   16097             :       template <typename T>
   16098             :       class sosos_base_node : public expression_node<T>
   16099             :       {
   16100             :       public:
   16101             : 
   16102         300 :          virtual ~sosos_base_node()
   16103         300 :          {}
   16104             : 
   16105           0 :          inline virtual operator_type operation() const
   16106             :          {
   16107           0 :             return details::e_default;
   16108             :          }
   16109             :       };
   16110             : 
   16111             :       template <typename T>
   16112             :       class T0oT1oT2_base_node : public expression_node<T>
   16113             :       {
   16114             :       public:
   16115             : 
   16116      374939 :          virtual ~T0oT1oT2_base_node()
   16117      374939 :          {}
   16118             : 
   16119             :          virtual std::string type_id() const = 0;
   16120             :       };
   16121             : 
   16122             :       template <typename T>
   16123             :       class T0oT1oT2oT3_base_node : public expression_node<T>
   16124             :       {
   16125             :       public:
   16126             : 
   16127      103821 :          virtual ~T0oT1oT2oT3_base_node()
   16128      103821 :          {}
   16129             : 
   16130             :          virtual std::string type_id() const = 0;
   16131             :       };
   16132             : 
   16133             :       template <typename T, typename Operation>
   16134             :       class unary_variable_node exprtk_final : public uv_base_node<T>
   16135             :       {
   16136             :       public:
   16137             : 
   16138             :          typedef expression_node<T>* expression_ptr;
   16139             :          typedef Operation operation_t;
   16140             : 
   16141        7697 :          explicit unary_variable_node(const T& var)
   16142        7697 :          : v_(var)
   16143        7697 :          {}
   16144             : 
   16145    60005984 :          inline T value() const exprtk_override
   16146             :          {
   16147    60005984 :             return Operation::process(v_);
   16148             :          }
   16149             : 
   16150      194701 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16151             :          {
   16152      194701 :             return Operation::type();
   16153             :          }
   16154             : 
   16155        2081 :          inline operator_type operation() const exprtk_override
   16156             :          {
   16157        2081 :             return Operation::operation();
   16158             :          }
   16159             : 
   16160        2100 :          inline const T& v() const exprtk_override
   16161             :          {
   16162        2100 :             return v_;
   16163             :          }
   16164             : 
   16165             :       private:
   16166             : 
   16167             :          unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete;
   16168             :          unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete;
   16169             : 
   16170             :          const T& v_;
   16171             :       };
   16172             : 
   16173             :       template <typename T>
   16174             :       class uvouv_node exprtk_final : public expression_node<T>
   16175             :       {
   16176             :       public:
   16177             : 
   16178             :          // UOpr1(v0) Op UOpr2(v1)
   16179             :          typedef typename details::functor_t<T> functor_t;
   16180             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16181             :          typedef typename functor_t::ufunc_t    ufunc_t;
   16182             :          typedef expression_node<T>*            expression_ptr;
   16183             : 
   16184         610 :          explicit uvouv_node(const T& var0,const T& var1,
   16185             :                              ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
   16186         610 :          : v0_(var0)
   16187         610 :          , v1_(var1)
   16188         610 :          , u0_(uf0 )
   16189         610 :          , u1_(uf1 )
   16190         610 :          , f_ (bf  )
   16191         610 :          {}
   16192             : 
   16193         130 :          inline T value() const exprtk_override
   16194             :          {
   16195         130 :             return f_(u0_(v0_),u1_(v1_));
   16196             :          }
   16197             : 
   16198       20870 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16199             :          {
   16200       20870 :             return expression_node<T>::e_uvouv;
   16201             :          }
   16202             : 
   16203             :          inline const T& v0()
   16204             :          {
   16205             :             return v0_;
   16206             :          }
   16207             : 
   16208             :          inline const T& v1()
   16209             :          {
   16210             :             return v1_;
   16211             :          }
   16212             : 
   16213             :          inline ufunc_t u0()
   16214             :          {
   16215             :             return u0_;
   16216             :          }
   16217             : 
   16218             :          inline ufunc_t u1()
   16219             :          {
   16220             :             return u1_;
   16221             :          }
   16222             : 
   16223             :          inline ufunc_t f()
   16224             :          {
   16225             :             return f_;
   16226             :          }
   16227             : 
   16228             :       private:
   16229             : 
   16230             :          uvouv_node(const uvouv_node<T>&) exprtk_delete;
   16231             :          uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete;
   16232             : 
   16233             :          const T& v0_;
   16234             :          const T& v1_;
   16235             :          const ufunc_t u0_;
   16236             :          const ufunc_t u1_;
   16237             :          const bfunc_t f_;
   16238             :       };
   16239             : 
   16240             :       template <typename T, typename Operation>
   16241             :       class unary_branch_node exprtk_final : public expression_node<T>
   16242             :       {
   16243             :       public:
   16244             : 
   16245             :          typedef Operation                      operation_t;
   16246             :          typedef expression_node<T>*            expression_ptr;
   16247             :          typedef std::pair<expression_ptr,bool> branch_t;
   16248             : 
   16249       59908 :          explicit unary_branch_node(expression_ptr branch)
   16250       59908 :          {
   16251       59908 :             construct_branch_pair(branch_, branch);
   16252       59908 :          }
   16253             : 
   16254   190043658 :          inline T value() const exprtk_override
   16255             :          {
   16256   190043658 :             return Operation::process(branch_.first->value());
   16257             :          }
   16258             : 
   16259      736595 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16260             :          {
   16261      736595 :             return Operation::type();
   16262             :          }
   16263             : 
   16264      133473 :          inline bool valid() const exprtk_override
   16265             :          {
   16266      133473 :             return branch_.first && branch_.first->valid();
   16267             :          }
   16268             : 
   16269             :          inline operator_type operation()
   16270             :          {
   16271             :             return Operation::operation();
   16272             :          }
   16273             : 
   16274        1460 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   16275             :          {
   16276        1460 :             return branch_.first;
   16277             :          }
   16278             : 
   16279        1460 :          inline void release()
   16280             :          {
   16281        1460 :             branch_.second = false;
   16282        1460 :          }
   16283             : 
   16284       59908 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   16285             :          {
   16286       59908 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   16287       59908 :          }
   16288             : 
   16289      113734 :          std::size_t node_depth() const exprtk_override
   16290             :          {
   16291      113734 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   16292             :          }
   16293             : 
   16294             :       private:
   16295             : 
   16296             :          unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete;
   16297             :          unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete;
   16298             : 
   16299             :          branch_t branch_;
   16300             :       };
   16301             : 
   16302             :       template <typename T> struct is_const                { enum {result = 0}; };
   16303             :       template <typename T> struct is_const <const T>      { enum {result = 1}; };
   16304             :       template <typename T> struct is_const_ref            { enum {result = 0}; };
   16305             :       template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
   16306             :       template <typename T> struct is_ref                  { enum {result = 0}; };
   16307             :       template <typename T> struct is_ref<T&>              { enum {result = 1}; };
   16308             :       template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
   16309             : 
   16310             :       template <std::size_t State>
   16311         140 :       struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
   16312             : 
   16313             :       template <>
   16314          72 :       struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
   16315             : 
   16316             :       #define exprtk_crtype(Type)                          \
   16317             :       param_to_str<is_const_ref< Type >::result>::result() \
   16318             : 
   16319             :       template <typename T>
   16320             :       struct T0oT1oT2process
   16321             :       {
   16322             :          typedef typename details::functor_t<T> functor_t;
   16323             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16324             : 
   16325             :          struct mode0
   16326             :          {
   16327     5069229 :             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
   16328             :             {
   16329             :                // (T0 o0 T1) o1 T2
   16330     5069229 :                return bf1(bf0(t0,t1),t2);
   16331             :             }
   16332             : 
   16333             :             template <typename T0, typename T1, typename T2>
   16334      639372 :             static inline std::string id()
   16335             :             {
   16336      639372 :                static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
   16337             :                                                        exprtk_crtype(T1) + ")o(" +
   16338             :                                                        exprtk_crtype(T2) + ")"   ;
   16339      639372 :                return result;
   16340             :             }
   16341             :          };
   16342             : 
   16343             :          struct mode1
   16344             :          {
   16345       53370 :             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
   16346             :             {
   16347             :                // T0 o0 (T1 o1 T2)
   16348       53370 :                return bf0(t0,bf1(t1,t2));
   16349             :             }
   16350             : 
   16351             :             template <typename T0, typename T1, typename T2>
   16352      639255 :             static inline std::string id()
   16353             :             {
   16354      639255 :                static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
   16355             :                                                        exprtk_crtype(T1) + "o"   +
   16356             :                                                        exprtk_crtype(T2) + ")"   ;
   16357      639255 :                return result;
   16358             :             }
   16359             :          };
   16360             :       };
   16361             : 
   16362             :       template <typename T>
   16363             :       struct T0oT1oT20T3process
   16364             :       {
   16365             :          typedef typename details::functor_t<T> functor_t;
   16366             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16367             : 
   16368             :          struct mode0
   16369             :          {
   16370    11412878 :             static inline T process(const T& t0, const T& t1,
   16371             :                                     const T& t2, const T& t3,
   16372             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   16373             :             {
   16374             :                // (T0 o0 T1) o1 (T2 o2 T3)
   16375    11412878 :                return bf1(bf0(t0,t1),bf2(t2,t3));
   16376             :             }
   16377             : 
   16378             :             template <typename T0, typename T1, typename T2, typename T3>
   16379      962748 :             static inline std::string id()
   16380             :             {
   16381      962748 :                static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
   16382             :                                                        exprtk_crtype(T1) + ")o" +
   16383             :                                                  "(" + exprtk_crtype(T2) + "o"  +
   16384             :                                                        exprtk_crtype(T3) + ")"  ;
   16385      962748 :                return result;
   16386             :             }
   16387             :          };
   16388             : 
   16389             :          struct mode1
   16390             :          {
   16391           0 :             static inline T process(const T& t0, const T& t1,
   16392             :                                     const T& t2, const T& t3,
   16393             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   16394             :             {
   16395             :                // (T0 o0 (T1 o1 (T2 o2 T3))
   16396           0 :                return bf0(t0,bf1(t1,bf2(t2,t3)));
   16397             :             }
   16398             :             template <typename T0, typename T1, typename T2, typename T3>
   16399      958878 :             static inline std::string id()
   16400             :             {
   16401      958878 :                static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
   16402             :                                                        exprtk_crtype(T1) +  ")o("  +
   16403             :                                                        exprtk_crtype(T2) +  "o"    +
   16404             :                                                        exprtk_crtype(T3) +  "))"   ;
   16405      958878 :                return result;
   16406             :             }
   16407             :          };
   16408             : 
   16409             :          struct mode2
   16410             :          {
   16411           0 :             static inline T process(const T& t0, const T& t1,
   16412             :                                     const T& t2, const T& t3,
   16413             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   16414             :             {
   16415             :                // (T0 o0 ((T1 o1 T2) o2 T3)
   16416           0 :                return bf0(t0,bf2(bf1(t1,t2),t3));
   16417             :             }
   16418             : 
   16419             :             template <typename T0, typename T1, typename T2, typename T3>
   16420      852336 :             static inline std::string id()
   16421             :             {
   16422      852336 :                static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
   16423             :                                                        exprtk_crtype(T1) + "o"    +
   16424             :                                                        exprtk_crtype(T2) + ")o("  +
   16425             :                                                        exprtk_crtype(T3) + "))"   ;
   16426      852336 :                return result;
   16427             :             }
   16428             :          };
   16429             : 
   16430             :          struct mode3
   16431             :          {
   16432           0 :             static inline T process(const T& t0, const T& t1,
   16433             :                                     const T& t2, const T& t3,
   16434             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   16435             :             {
   16436             :                // (((T0 o0 T1) o1 T2) o2 T3)
   16437           0 :                return bf2(bf1(bf0(t0,t1),t2),t3);
   16438             :             }
   16439             : 
   16440             :             template <typename T0, typename T1, typename T2, typename T3>
   16441      958878 :             static inline std::string id()
   16442             :             {
   16443      958878 :                static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
   16444             :                                                         exprtk_crtype(T1) + ")o("  +
   16445             :                                                         exprtk_crtype(T2) + "))o(" +
   16446             :                                                         exprtk_crtype(T3) + ")";
   16447      958878 :                return result;
   16448             :             }
   16449             :          };
   16450             : 
   16451             :          struct mode4
   16452             :          {
   16453           0 :             static inline T process(const T& t0, const T& t1,
   16454             :                                     const T& t2, const T& t3,
   16455             :                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
   16456             :             {
   16457             :                // ((T0 o0 (T1 o1 T2)) o2 T3
   16458           0 :                return bf2(bf0(t0,bf1(t1,t2)),t3);
   16459             :             }
   16460             : 
   16461             :             template <typename T0, typename T1, typename T2, typename T3>
   16462      852336 :             static inline std::string id()
   16463             :             {
   16464      852336 :                static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
   16465             :                                                         exprtk_crtype(T1) + "o"    +
   16466             :                                                         exprtk_crtype(T2) + "))o(" +
   16467             :                                                         exprtk_crtype(T3) + ")"    ;
   16468      852336 :                return result;
   16469             :             }
   16470             :          };
   16471             :       };
   16472             : 
   16473             :       #undef exprtk_crtype
   16474             : 
   16475             :       template <typename T, typename T0, typename T1>
   16476             :       struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
   16477             :       template <typename T, typename T0, typename T1>
   16478             :       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
   16479             : 
   16480             :       #define synthesis_node_type_define(T0_, T1_, v_)                                                          \
   16481             :       template <typename T, typename T0, typename T1>                                                           \
   16482             :       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
   16483             :       template <typename T, typename T0, typename T1>                                                           \
   16484             :       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
   16485             : 
   16486             :       synthesis_node_type_define(const T0&, const T1&,  e_vov)
   16487             :       synthesis_node_type_define(const T0&, const T1 ,  e_voc)
   16488             :       synthesis_node_type_define(const T0 , const T1&,  e_cov)
   16489             :       synthesis_node_type_define(      T0&,       T1&, e_none)
   16490             :       synthesis_node_type_define(const T0 , const T1 , e_none)
   16491             :       synthesis_node_type_define(      T0&, const T1 , e_none)
   16492             :       synthesis_node_type_define(const T0 ,       T1&, e_none)
   16493             :       synthesis_node_type_define(const T0&,       T1&, e_none)
   16494             :       synthesis_node_type_define(      T0&, const T1&, e_none)
   16495             :       #undef synthesis_node_type_define
   16496             : 
   16497             :       template <typename T, typename T0, typename T1, typename T2>
   16498             :       struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
   16499             :       template <typename T, typename T0, typename T1, typename T2>
   16500             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
   16501             : 
   16502             :       #define synthesis_node_type_define(T0_, T1_, T2_, v_)                                                            \
   16503             :       template <typename T, typename T0, typename T1, typename T2>                                                     \
   16504             :       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
   16505             :       template <typename T, typename T0, typename T1, typename T2>                                                     \
   16506             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
   16507             : 
   16508             :       synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
   16509             :       synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
   16510             :       synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
   16511             :       synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
   16512             :       synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
   16513             :       synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
   16514             :       synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
   16515             :       synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
   16516             :       synthesis_node_type_define(      T0&,       T1&,       T2&, e_none )
   16517             :       #undef synthesis_node_type_define
   16518             : 
   16519             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   16520             :       struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
   16521             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   16522             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
   16523             : 
   16524             :       #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_)                                                              \
   16525             :       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
   16526             :       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
   16527             :       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
   16528             :       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
   16529             : 
   16530             :       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
   16531             :       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
   16532             :       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
   16533             :       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
   16534             :       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
   16535             :       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
   16536             :       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
   16537             :       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
   16538             :       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
   16539             :       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none   )
   16540             :       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none   )
   16541             :       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none   )
   16542             :       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none   )
   16543             :       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none   )
   16544             :       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none   )
   16545             :       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none   )
   16546             :       #undef synthesis_node_type_define
   16547             : 
   16548             :       template <typename T, typename T0, typename T1>
   16549             :       class T0oT1 exprtk_final : public expression_node<T>
   16550             :       {
   16551             :       public:
   16552             : 
   16553             :          typedef typename details::functor_t<T> functor_t;
   16554             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16555             :          typedef T value_type;
   16556             :          typedef T0oT1<T,T0,T1> node_type;
   16557             : 
   16558             :          T0oT1(T0 p0, T1 p1, const bfunc_t p2)
   16559             :          : t0_(p0)
   16560             :          , t1_(p1)
   16561             :          , f_ (p2)
   16562             :          {}
   16563             : 
   16564             :          inline typename expression_node<T>::node_type type() const exprtk_override
   16565             :          {
   16566             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
   16567             :             return result;
   16568             :          }
   16569             : 
   16570             :          inline operator_type operation() const exprtk_override
   16571             :          {
   16572             :             return e_default;
   16573             :          }
   16574             : 
   16575             :          inline T value() const exprtk_override
   16576             :          {
   16577             :             return f_(t0_,t1_);
   16578             :          }
   16579             : 
   16580             :          inline T0 t0() const
   16581             :          {
   16582             :             return t0_;
   16583             :          }
   16584             : 
   16585             :          inline T1 t1() const
   16586             :          {
   16587             :             return t1_;
   16588             :          }
   16589             : 
   16590             :          inline bfunc_t f() const
   16591             :          {
   16592             :             return f_;
   16593             :          }
   16594             : 
   16595             :          template <typename Allocator>
   16596             :          static inline expression_node<T>* allocate(Allocator& allocator,
   16597             :                                                     T0 p0, T1 p1,
   16598             :                                                     bfunc_t p2)
   16599             :          {
   16600             :             return allocator
   16601             :                      .template allocate_type<node_type, T0, T1, bfunc_t&>
   16602             :                         (p0, p1, p2);
   16603             :          }
   16604             : 
   16605             :       private:
   16606             : 
   16607             :          T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete;
   16608             :          T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); }
   16609             : 
   16610             :          T0 t0_;
   16611             :          T1 t1_;
   16612             :          const bfunc_t f_;
   16613             :       };
   16614             : 
   16615             :       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
   16616             :       class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T>
   16617             :       {
   16618             :       public:
   16619             : 
   16620             :          typedef typename details::functor_t<T> functor_t;
   16621             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16622             :          typedef T value_type;
   16623             :          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
   16624             :          typedef ProcessMode process_mode_t;
   16625             : 
   16626        5915 :          T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
   16627        5915 :          : t0_(p0)
   16628        5915 :          , t1_(p1)
   16629        5915 :          , t2_(p2)
   16630        5915 :          , f0_(p3)
   16631        5915 :          , f1_(p4)
   16632        5915 :          {}
   16633             : 
   16634       37360 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16635             :          {
   16636             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
   16637       37360 :             return result;
   16638             :          }
   16639             : 
   16640             :          inline operator_type operation()
   16641             :          {
   16642             :             return e_default;
   16643             :          }
   16644             : 
   16645     5122599 :          inline T value() const exprtk_override
   16646             :          {
   16647     5122599 :             return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
   16648             :          }
   16649             : 
   16650           0 :          inline T0 t0() const
   16651             :          {
   16652           0 :             return t0_;
   16653             :          }
   16654             : 
   16655           0 :          inline T1 t1() const
   16656             :          {
   16657           0 :             return t1_;
   16658             :          }
   16659             : 
   16660           0 :          inline T2 t2() const
   16661             :          {
   16662           0 :             return t2_;
   16663             :          }
   16664             : 
   16665           0 :          bfunc_t f0() const
   16666             :          {
   16667           0 :             return f0_;
   16668             :          }
   16669             : 
   16670           0 :          bfunc_t f1() const
   16671             :          {
   16672           0 :             return f1_;
   16673             :          }
   16674             : 
   16675         123 :          std::string type_id() const exprtk_override
   16676             :          {
   16677         123 :             return id();
   16678             :          }
   16679             : 
   16680     1278627 :          static inline std::string id()
   16681             :          {
   16682     1278627 :             return process_mode_t::template id<T0,T1,T2>();
   16683             :          }
   16684             : 
   16685             :          template <typename Allocator>
   16686        5915 :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
   16687             :          {
   16688             :             return allocator
   16689             :                       .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
   16690        5915 :                          (p0, p1, p2, p3, p4);
   16691             :          }
   16692             : 
   16693             :       private:
   16694             : 
   16695             :          T0oT1oT2(const node_type&) exprtk_delete;
   16696             :          node_type& operator=(const node_type&) exprtk_delete;
   16697             : 
   16698             :          T0 t0_;
   16699             :          T1 t1_;
   16700             :          T2 t2_;
   16701             :          const bfunc_t f0_;
   16702             :          const bfunc_t f1_;
   16703             :       };
   16704             : 
   16705             :       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
   16706             :       class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T>
   16707             :       {
   16708             :       public:
   16709             : 
   16710             :          typedef typename details::functor_t<T> functor_t;
   16711             :          typedef typename functor_t::bfunc_t    bfunc_t;
   16712             :          typedef T value_type;
   16713             :          typedef T0_ T0;
   16714             :          typedef T1_ T1;
   16715             :          typedef T2_ T2;
   16716             :          typedef T3_ T3;
   16717             :          typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
   16718             :          typedef ProcessMode process_mode_t;
   16719             : 
   16720        6537 :          T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
   16721        6537 :          : t0_(p0)
   16722        6537 :          , t1_(p1)
   16723        6537 :          , t2_(p2)
   16724        6537 :          , t3_(p3)
   16725        6537 :          , f0_(p4)
   16726        6537 :          , f1_(p5)
   16727        6537 :          , f2_(p6)
   16728        6537 :          {}
   16729             : 
   16730    11412878 :          inline T value() const exprtk_override
   16731             :          {
   16732    11412878 :             return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
   16733             :          }
   16734             : 
   16735             :          inline T0 t0() const
   16736             :          {
   16737             :             return t0_;
   16738             :          }
   16739             : 
   16740             :          inline T1 t1() const
   16741             :          {
   16742             :             return t1_;
   16743             :          }
   16744             : 
   16745             :          inline T2 t2() const
   16746             :          {
   16747             :             return t2_;
   16748             :          }
   16749             : 
   16750             :          inline T3 t3() const
   16751             :          {
   16752             :             return t3_;
   16753             :          }
   16754             : 
   16755             :          inline bfunc_t f0() const
   16756             :          {
   16757             :             return f0_;
   16758             :          }
   16759             : 
   16760             :          inline bfunc_t f1() const
   16761             :          {
   16762             :             return f1_;
   16763             :          }
   16764             : 
   16765             :          inline bfunc_t f2() const
   16766             :          {
   16767             :             return f2_;
   16768             :          }
   16769             : 
   16770        3870 :          inline std::string type_id() const exprtk_override
   16771             :          {
   16772        3870 :             return id();
   16773             :          }
   16774             : 
   16775     4585176 :          static inline std::string id()
   16776             :          {
   16777     4585176 :             return process_mode_t::template id<T0, T1, T2, T3>();
   16778             :          }
   16779             : 
   16780             :          template <typename Allocator>
   16781        6537 :          static inline expression_node<T>* allocate(Allocator& allocator,
   16782             :                                                     T0 p0, T1 p1, T2 p2, T3 p3,
   16783             :                                                     bfunc_t p4, bfunc_t p5, bfunc_t p6)
   16784             :          {
   16785             :             return allocator
   16786             :                       .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
   16787        6537 :                          (p0, p1, p2, p3, p4, p5, p6);
   16788             :          }
   16789             : 
   16790             :       private:
   16791             : 
   16792             :          T0oT1oT2oT3(const node_type&) exprtk_delete;
   16793             :          node_type& operator=(const node_type&) exprtk_delete;
   16794             : 
   16795             :          T0 t0_;
   16796             :          T1 t1_;
   16797             :          T2 t2_;
   16798             :          T3 t3_;
   16799             :          const bfunc_t f0_;
   16800             :          const bfunc_t f1_;
   16801             :          const bfunc_t f2_;
   16802             :       };
   16803             : 
   16804             :       template <typename T, typename T0, typename T1, typename T2>
   16805             :       class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T>
   16806             :       {
   16807             :       public:
   16808             : 
   16809             :          typedef typename details::functor_t<T> functor_t;
   16810             :          typedef typename functor_t::tfunc_t    tfunc_t;
   16811             :          typedef T value_type;
   16812             :          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
   16813             : 
   16814             :          T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
   16815             :          : t0_(p0)
   16816             :          , t1_(p1)
   16817             :          , t2_(p2)
   16818             :          , f_ (p3)
   16819             :          {}
   16820             : 
   16821             :          inline typename expression_node<T>::node_type type() const exprtk_override
   16822             :          {
   16823             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
   16824             :             return result;
   16825             :          }
   16826             : 
   16827             :          inline operator_type operation() const exprtk_override
   16828             :          {
   16829             :             return e_default;
   16830             :          }
   16831             : 
   16832             :          inline T value() const exprtk_override
   16833             :          {
   16834             :             return f_(t0_, t1_, t2_);
   16835             :          }
   16836             : 
   16837             :          inline T0 t0() const
   16838             :          {
   16839             :             return t0_;
   16840             :          }
   16841             : 
   16842             :          inline T1 t1() const
   16843             :          {
   16844             :             return t1_;
   16845             :          }
   16846             : 
   16847             :          inline T2 t2() const
   16848             :          {
   16849             :             return t2_;
   16850             :          }
   16851             : 
   16852             :          tfunc_t f() const
   16853             :          {
   16854             :             return f_;
   16855             :          }
   16856             : 
   16857             :          std::string type_id() const
   16858             :          {
   16859             :             return id();
   16860             :          }
   16861             : 
   16862             :          static inline std::string id()
   16863             :          {
   16864             :             return "sf3";
   16865             :          }
   16866             : 
   16867             :          template <typename Allocator>
   16868             :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
   16869             :          {
   16870             :             return allocator
   16871             :                      .template allocate_type<node_type, T0, T1, T2, tfunc_t>
   16872             :                         (p0, p1, p2, p3);
   16873             :          }
   16874             : 
   16875             :       private:
   16876             : 
   16877             :          T0oT1oT2_sf3(const node_type&) exprtk_delete;
   16878             :          node_type& operator=(const node_type&) exprtk_delete;
   16879             : 
   16880             :          T0 t0_;
   16881             :          T1 t1_;
   16882             :          T2 t2_;
   16883             :          const tfunc_t f_;
   16884             :       };
   16885             : 
   16886             :       template <typename T, typename T0, typename T1, typename T2>
   16887             :       class sf3ext_type_node : public T0oT1oT2_base_node<T>
   16888             :       {
   16889             :       public:
   16890             : 
   16891      369024 :          virtual ~sf3ext_type_node()
   16892      369024 :          {}
   16893             : 
   16894             :          virtual T0 t0() const = 0;
   16895             : 
   16896             :          virtual T1 t1() const = 0;
   16897             : 
   16898             :          virtual T2 t2() const = 0;
   16899             :       };
   16900             : 
   16901             :       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
   16902             :       class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2>
   16903             :       {
   16904             :       public:
   16905             : 
   16906             :          typedef T value_type;
   16907             :          typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type;
   16908             : 
   16909      369024 :          T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
   16910      369024 :          : t0_(p0)
   16911      369024 :          , t1_(p1)
   16912      369024 :          , t2_(p2)
   16913      369024 :          {}
   16914             : 
   16915    12038432 :          inline typename expression_node<T>::node_type type() const exprtk_override
   16916             :          {
   16917             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
   16918    12038432 :             return result;
   16919             :          }
   16920             : 
   16921             :          inline operator_type operation()
   16922             :          {
   16923             :             return e_default;
   16924             :          }
   16925             : 
   16926   120067082 :          inline T value() const exprtk_override
   16927             :          {
   16928   120067082 :             return SF3Operation::process(t0_, t1_, t2_);
   16929             :          }
   16930             : 
   16931      181199 :          T0 t0() const exprtk_override
   16932             :          {
   16933      181199 :             return t0_;
   16934             :          }
   16935             : 
   16936      181199 :          T1 t1() const exprtk_override
   16937             :          {
   16938      181199 :             return t1_;
   16939             :          }
   16940             : 
   16941      181199 :          T2 t2() const exprtk_override
   16942             :          {
   16943      181199 :             return t2_;
   16944             :          }
   16945             : 
   16946      527233 :          std::string type_id() const exprtk_override
   16947             :          {
   16948      527233 :             return id();
   16949             :          }
   16950             : 
   16951      527233 :          static inline std::string id()
   16952             :          {
   16953      527233 :             return SF3Operation::id();
   16954             :          }
   16955             : 
   16956             :          template <typename Allocator>
   16957      369024 :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
   16958             :          {
   16959             :             return allocator
   16960             :                      .template allocate_type<node_type, T0, T1, T2>
   16961      369024 :                         (p0, p1, p2);
   16962             :          }
   16963             : 
   16964             :       private:
   16965             : 
   16966             :          T0oT1oT2_sf3ext(const node_type&) exprtk_delete;
   16967             :          node_type& operator=(const node_type&) exprtk_delete;
   16968             : 
   16969             :          T0 t0_;
   16970             :          T1 t1_;
   16971             :          T2 t2_;
   16972             :       };
   16973             : 
   16974             :       template <typename T>
   16975      838183 :       inline bool is_sf3ext_node(const expression_node<T>* n)
   16976             :       {
   16977      838183 :          switch (n->type())
   16978             :          {
   16979       99912 :             case expression_node<T>::e_vovov : return true;
   16980       82670 :             case expression_node<T>::e_vovoc : return true;
   16981       80666 :             case expression_node<T>::e_vocov : return true;
   16982       84620 :             case expression_node<T>::e_covov : return true;
   16983       14530 :             case expression_node<T>::e_covoc : return true;
   16984      475785 :             default                          : return false;
   16985             :          }
   16986             :       }
   16987             : 
   16988             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   16989             :       class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T>
   16990             :       {
   16991             :       public:
   16992             : 
   16993             :          typedef typename details::functor_t<T> functor_t;
   16994             :          typedef typename functor_t::qfunc_t    qfunc_t;
   16995             :          typedef T value_type;
   16996             :          typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type;
   16997             : 
   16998             :          T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
   16999             :          : t0_(p0)
   17000             :          , t1_(p1)
   17001             :          , t2_(p2)
   17002             :          , t3_(p3)
   17003             :          , f_ (p4)
   17004             :          {}
   17005             : 
   17006             :          inline typename expression_node<T>::node_type type() const exprtk_override
   17007             :          {
   17008             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
   17009             :             return result;
   17010             :          }
   17011             : 
   17012             :          inline operator_type operation() const exprtk_override
   17013             :          {
   17014             :             return e_default;
   17015             :          }
   17016             : 
   17017             :          inline T value() const exprtk_override
   17018             :          {
   17019             :             return f_(t0_, t1_, t2_, t3_);
   17020             :          }
   17021             : 
   17022             :          inline T0 t0() const
   17023             :          {
   17024             :             return t0_;
   17025             :          }
   17026             : 
   17027             :          inline T1 t1() const
   17028             :          {
   17029             :             return t1_;
   17030             :          }
   17031             : 
   17032             :          inline T2 t2() const
   17033             :          {
   17034             :             return t2_;
   17035             :          }
   17036             : 
   17037             :          inline T3 t3() const
   17038             :          {
   17039             :             return t3_;
   17040             :          }
   17041             : 
   17042             :          qfunc_t f() const
   17043             :          {
   17044             :             return f_;
   17045             :          }
   17046             : 
   17047             :          std::string type_id() const
   17048             :          {
   17049             :             return id();
   17050             :          }
   17051             : 
   17052             :          static inline std::string id()
   17053             :          {
   17054             :             return "sf4";
   17055             :          }
   17056             : 
   17057             :          template <typename Allocator>
   17058             :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
   17059             :          {
   17060             :             return allocator
   17061             :                      .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
   17062             :                         (p0, p1, p2, p3, p4);
   17063             :          }
   17064             : 
   17065             :       private:
   17066             : 
   17067             :          T0oT1oT2oT3_sf4(const node_type&) exprtk_delete;
   17068             :          node_type& operator=(const node_type&) exprtk_delete;
   17069             : 
   17070             :          T0 t0_;
   17071             :          T1 t1_;
   17072             :          T2 t2_;
   17073             :          T3 t3_;
   17074             :          const qfunc_t f_;
   17075             :       };
   17076             : 
   17077             :       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
   17078             :       class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T>
   17079             :       {
   17080             :       public:
   17081             : 
   17082             :          typedef T value_type;
   17083             :          typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type;
   17084             : 
   17085       97284 :          T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
   17086       97284 :          : t0_(p0)
   17087       97284 :          , t1_(p1)
   17088       97284 :          , t2_(p2)
   17089       97284 :          , t3_(p3)
   17090       97284 :          {}
   17091             : 
   17092     3271533 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17093             :          {
   17094             :             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
   17095     3271533 :             return result;
   17096             :          }
   17097             : 
   17098       97271 :          inline T value() const exprtk_override
   17099             :          {
   17100       97271 :             return SF4Operation::process(t0_, t1_, t2_, t3_);
   17101             :          }
   17102             : 
   17103             :          inline T0 t0() const
   17104             :          {
   17105             :             return t0_;
   17106             :          }
   17107             : 
   17108             :          inline T1 t1() const
   17109             :          {
   17110             :             return t1_;
   17111             :          }
   17112             : 
   17113             :          inline T2 t2() const
   17114             :          {
   17115             :             return t2_;
   17116             :          }
   17117             : 
   17118             :          inline T3 t3() const
   17119             :          {
   17120             :             return t3_;
   17121             :          }
   17122             : 
   17123       84472 :          std::string type_id() const exprtk_override
   17124             :          {
   17125       84472 :             return id();
   17126             :          }
   17127             : 
   17128       84472 :          static inline std::string id()
   17129             :          {
   17130       84472 :             return SF4Operation::id();
   17131             :          }
   17132             : 
   17133             :          template <typename Allocator>
   17134       97284 :          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
   17135             :          {
   17136             :             return allocator
   17137             :                      .template allocate_type<node_type, T0, T1, T2, T3>
   17138       97284 :                         (p0, p1, p2, p3);
   17139             :          }
   17140             : 
   17141             :       private:
   17142             : 
   17143             :          T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete;
   17144             :          node_type& operator=(const node_type&) exprtk_delete;
   17145             : 
   17146             :          T0 t0_;
   17147             :          T1 t1_;
   17148             :          T2 t2_;
   17149             :          T3 t3_;
   17150             :       };
   17151             : 
   17152             :       template <typename T>
   17153             :       inline bool is_sf4ext_node(const expression_node<T>* n)
   17154             :       {
   17155             :          switch (n->type())
   17156             :          {
   17157             :             case expression_node<T>::e_vovovov : return true;
   17158             :             case expression_node<T>::e_vovovoc : return true;
   17159             :             case expression_node<T>::e_vovocov : return true;
   17160             :             case expression_node<T>::e_vocovov : return true;
   17161             :             case expression_node<T>::e_covovov : return true;
   17162             :             case expression_node<T>::e_covocov : return true;
   17163             :             case expression_node<T>::e_vocovoc : return true;
   17164             :             case expression_node<T>::e_covovoc : return true;
   17165             :             case expression_node<T>::e_vococov : return true;
   17166             :             default                            : return false;
   17167             :          }
   17168             :       }
   17169             : 
   17170             :       template <typename T, typename T0, typename T1>
   17171             :       struct T0oT1_define
   17172             :       {
   17173             :          typedef details::T0oT1<T, T0, T1> type0;
   17174             :       };
   17175             : 
   17176             :       template <typename T, typename T0, typename T1, typename T2>
   17177             :       struct T0oT1oT2_define
   17178             :       {
   17179             :          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
   17180             :          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
   17181             :          typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
   17182             :          typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
   17183             :       };
   17184             : 
   17185             :       template <typename T, typename T0, typename T1, typename T2, typename T3>
   17186             :       struct T0oT1oT2oT3_define
   17187             :       {
   17188             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
   17189             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
   17190             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
   17191             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
   17192             :          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
   17193             :          typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
   17194             :       };
   17195             : 
   17196             :       template <typename T, typename Operation>
   17197             :       class vov_node exprtk_final : public vov_base_node<T>
   17198             :       {
   17199             :       public:
   17200             : 
   17201             :          typedef expression_node<T>* expression_ptr;
   17202             :          typedef Operation operation_t;
   17203             : 
   17204             :          // variable op variable node
   17205      264321 :          explicit vov_node(const T& var0, const T& var1)
   17206      264321 :          : v0_(var0)
   17207      264321 :          , v1_(var1)
   17208      264321 :          {}
   17209             : 
   17210    10560951 :          inline T value() const exprtk_override
   17211             :          {
   17212    10560951 :             return Operation::process(v0_,v1_);
   17213             :          }
   17214             : 
   17215     5309818 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17216             :          {
   17217     5309818 :             return Operation::type();
   17218             :          }
   17219             : 
   17220      217063 :          inline operator_type operation() const exprtk_override
   17221             :          {
   17222      217063 :             return Operation::operation();
   17223             :          }
   17224             : 
   17225      217063 :          inline const T& v0() const exprtk_override
   17226             :          {
   17227      217063 :             return v0_;
   17228             :          }
   17229             : 
   17230      217063 :          inline const T& v1() const exprtk_override
   17231             :          {
   17232      217063 :             return v1_;
   17233             :          }
   17234             : 
   17235             :       protected:
   17236             : 
   17237             :          const T& v0_;
   17238             :          const T& v1_;
   17239             : 
   17240             :       private:
   17241             : 
   17242             :          vov_node(const vov_node<T,Operation>&) exprtk_delete;
   17243             :          vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete;
   17244             :       };
   17245             : 
   17246             :       template <typename T, typename Operation>
   17247             :       class cov_node exprtk_final : public cov_base_node<T>
   17248             :       {
   17249             :       public:
   17250             : 
   17251             :          typedef expression_node<T>* expression_ptr;
   17252             :          typedef Operation operation_t;
   17253             : 
   17254             :          // constant op variable node
   17255      240251 :          explicit cov_node(const T& const_var, const T& var)
   17256      240251 :          : c_(const_var)
   17257      240251 :          , v_(var)
   17258      240251 :          {}
   17259             : 
   17260    40058909 :          inline T value() const exprtk_override
   17261             :          {
   17262    40058909 :             return Operation::process(c_,v_);
   17263             :          }
   17264             : 
   17265     5059913 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17266             :          {
   17267     5059913 :             return Operation::type();
   17268             :          }
   17269             : 
   17270      181920 :          inline operator_type operation() const exprtk_override
   17271             :          {
   17272      181920 :             return Operation::operation();
   17273             :          }
   17274             : 
   17275      181920 :          inline const T c() const exprtk_override
   17276             :          {
   17277      181920 :             return c_;
   17278             :          }
   17279             : 
   17280      181920 :          inline const T& v() const exprtk_override
   17281             :          {
   17282      181920 :             return v_;
   17283             :          }
   17284             : 
   17285             :       protected:
   17286             : 
   17287             :          const T  c_;
   17288             :          const T& v_;
   17289             : 
   17290             :       private:
   17291             : 
   17292             :          cov_node(const cov_node<T,Operation>&) exprtk_delete;
   17293             :          cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete;
   17294             :       };
   17295             : 
   17296             :       template <typename T, typename Operation>
   17297             :       class voc_node exprtk_final : public voc_base_node<T>
   17298             :       {
   17299             :       public:
   17300             : 
   17301             :          typedef expression_node<T>* expression_ptr;
   17302             :          typedef Operation operation_t;
   17303             : 
   17304             :          // variable op constant node
   17305      283561 :          explicit voc_node(const T& var, const T& const_var)
   17306      283561 :          : v_(var)
   17307      283561 :          , c_(const_var)
   17308      283561 :          {}
   17309             : 
   17310   245874117 :          inline T value() const exprtk_override
   17311             :          {
   17312   245874117 :             return Operation::process(v_,c_);
   17313             :          }
   17314             : 
   17315      157465 :          inline operator_type operation() const exprtk_override
   17316             :          {
   17317      157465 :             return Operation::operation();
   17318             :          }
   17319             : 
   17320      157465 :          inline const T c() const exprtk_override
   17321             :          {
   17322      157465 :             return c_;
   17323             :          }
   17324             : 
   17325      157465 :          inline const T& v() const exprtk_override
   17326             :          {
   17327      157465 :             return v_;
   17328             :          }
   17329             : 
   17330             :       protected:
   17331             : 
   17332             :          const T& v_;
   17333             :          const T  c_;
   17334             : 
   17335             :       private:
   17336             : 
   17337             :          voc_node(const voc_node<T,Operation>&) exprtk_delete;
   17338             :          voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete;
   17339             :       };
   17340             : 
   17341             :       template <typename T, typename Operation>
   17342             :       class vob_node exprtk_final : public vob_base_node<T>
   17343             :       {
   17344             :       public:
   17345             : 
   17346             :          typedef expression_node<T>* expression_ptr;
   17347             :          typedef std::pair<expression_ptr,bool> branch_t;
   17348             :          typedef Operation operation_t;
   17349             : 
   17350             :          // variable op binary node
   17351       33759 :          explicit vob_node(const T& var, const expression_ptr branch)
   17352       33759 :          : v_(var)
   17353             :          {
   17354       33759 :             construct_branch_pair(branch_, branch);
   17355       33759 :             assert(valid());
   17356       33759 :          }
   17357             : 
   17358       26104 :          inline T value() const exprtk_override
   17359             :          {
   17360       26104 :             return Operation::process(v_,branch_.first->value());
   17361             :          }
   17362             : 
   17363           0 :          inline const T& v() const exprtk_override
   17364             :          {
   17365           0 :             return v_;
   17366             :          }
   17367             : 
   17368      150568 :          inline bool valid() const exprtk_override
   17369             :          {
   17370      150568 :             return branch_.first && branch_.first->valid();
   17371             :          }
   17372             : 
   17373           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   17374             :          {
   17375           0 :             return branch_.first;
   17376             :          }
   17377             : 
   17378       33759 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   17379             :          {
   17380       33759 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
   17381       33759 :          }
   17382             : 
   17383      135806 :          std::size_t node_depth() const exprtk_override
   17384             :          {
   17385      135806 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   17386             :          }
   17387             : 
   17388             :       private:
   17389             : 
   17390             :          vob_node(const vob_node<T,Operation>&) exprtk_delete;
   17391             :          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete;
   17392             : 
   17393             :          const T& v_;
   17394             :          branch_t branch_;
   17395             :       };
   17396             : 
   17397             :       template <typename T, typename Operation>
   17398             :       class bov_node exprtk_final : public bov_base_node<T>
   17399             :       {
   17400             :       public:
   17401             : 
   17402             :          typedef expression_node<T>* expression_ptr;
   17403             :          typedef std::pair<expression_ptr,bool> branch_t;
   17404             :          typedef Operation operation_t;
   17405             : 
   17406             :          // binary node op variable node
   17407      352766 :          explicit bov_node(const expression_ptr branch, const T& var)
   17408      352766 :          : v_(var)
   17409             :          {
   17410      352766 :             construct_branch_pair(branch_, branch);
   17411      352766 :             assert(valid());
   17412      352766 :          }
   17413             : 
   17414     5042958 :          inline T value() const exprtk_override
   17415             :          {
   17416     5042958 :             return Operation::process(branch_.first->value(),v_);
   17417             :          }
   17418             : 
   17419           0 :          inline const T& v() const exprtk_override
   17420             :          {
   17421           0 :             return v_;
   17422             :          }
   17423             : 
   17424    16169011 :          inline bool valid() const exprtk_override
   17425             :          {
   17426    16169011 :             return branch_.first && branch_.first->valid();
   17427             :          }
   17428             : 
   17429           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   17430             :          {
   17431           0 :             return branch_.first;
   17432             :          }
   17433             : 
   17434      352766 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   17435             :          {
   17436      352766 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
   17437      352766 :          }
   17438             : 
   17439      893998 :          std::size_t node_depth() const exprtk_override
   17440             :          {
   17441      893998 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   17442             :          }
   17443             : 
   17444             :       private:
   17445             : 
   17446             :          bov_node(const bov_node<T,Operation>&) exprtk_delete;
   17447             :          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete;
   17448             : 
   17449             :          const T& v_;
   17450             :          branch_t branch_;
   17451             :       };
   17452             : 
   17453             :       template <typename T, typename Operation>
   17454             :       class cob_node exprtk_final : public cob_base_node<T>
   17455             :       {
   17456             :       public:
   17457             : 
   17458             :          typedef expression_node<T>* expression_ptr;
   17459             :          typedef std::pair<expression_ptr,bool> branch_t;
   17460             :          typedef Operation operation_t;
   17461             : 
   17462             :          // constant op variable node
   17463       89183 :          explicit cob_node(const T const_var, const expression_ptr branch)
   17464       89183 :          : c_(const_var)
   17465             :          {
   17466       89183 :             construct_branch_pair(branch_, branch);
   17467       89183 :             assert(valid());
   17468       89183 :          }
   17469             : 
   17470    10225783 :          inline T value() const exprtk_override
   17471             :          {
   17472    10225783 :             return Operation::process(c_,branch_.first->value());
   17473             :          }
   17474             : 
   17475       20945 :          inline operator_type operation() const exprtk_override
   17476             :          {
   17477       20945 :             return Operation::operation();
   17478             :          }
   17479             : 
   17480        5915 :          inline const T c() const exprtk_override
   17481             :          {
   17482        5915 :             return c_;
   17483             :          }
   17484             : 
   17485        4980 :          inline void set_c(const T new_c) exprtk_override
   17486             :          {
   17487        4980 :             (*const_cast<T*>(&c_)) = new_c;
   17488        4980 :          }
   17489             : 
   17490      655791 :          inline bool valid() const exprtk_override
   17491             :          {
   17492      655791 :             return branch_.first && branch_.first->valid();
   17493             :          }
   17494             : 
   17495           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   17496             :          {
   17497           0 :             return branch_.first;
   17498             :          }
   17499             : 
   17500         935 :          inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
   17501             :          {
   17502         935 :             branch_.second = false;
   17503         935 :             return branch_.first;
   17504             :          }
   17505             : 
   17506       89183 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   17507             :          {
   17508       89183 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
   17509       89183 :          }
   17510             : 
   17511      296674 :          std::size_t node_depth() const exprtk_override
   17512             :          {
   17513      296674 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   17514             :          }
   17515             : 
   17516             :       private:
   17517             : 
   17518             :          cob_node(const cob_node<T,Operation>&) exprtk_delete;
   17519             :          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete;
   17520             : 
   17521             :          const T  c_;
   17522             :          branch_t branch_;
   17523             :       };
   17524             : 
   17525             :       template <typename T, typename Operation>
   17526             :       class boc_node exprtk_final : public boc_base_node<T>
   17527             :       {
   17528             :       public:
   17529             : 
   17530             :          typedef expression_node<T>* expression_ptr;
   17531             :          typedef std::pair<expression_ptr,bool> branch_t;
   17532             :          typedef Operation operation_t;
   17533             : 
   17534             :          // binary node op constant node
   17535      143891 :          explicit boc_node(const expression_ptr branch, const T const_var)
   17536      143891 :          : c_(const_var)
   17537             :          {
   17538      143891 :             construct_branch_pair(branch_, branch);
   17539      143891 :             assert(valid());
   17540      143891 :          }
   17541             : 
   17542      129755 :          inline T value() const exprtk_override
   17543             :          {
   17544      129755 :             return Operation::process(branch_.first->value(),c_);
   17545             :          }
   17546             : 
   17547       57606 :          inline operator_type operation() const exprtk_override
   17548             :          {
   17549       57606 :             return Operation::operation();
   17550             :          }
   17551             : 
   17552       21382 :          inline const T c() const exprtk_override
   17553             :          {
   17554       21382 :             return c_;
   17555             :          }
   17556             : 
   17557       18723 :          inline void set_c(const T new_c) exprtk_override
   17558             :          {
   17559       18723 :             (*const_cast<T*>(&c_)) = new_c;
   17560       18723 :          }
   17561             : 
   17562      633043 :          inline bool valid() const exprtk_override
   17563             :          {
   17564      633043 :             return branch_.first && branch_.first->valid();
   17565             :          }
   17566             : 
   17567           0 :          inline expression_node<T>* branch(const std::size_t&) const exprtk_override
   17568             :          {
   17569           0 :             return branch_.first;
   17570             :          }
   17571             : 
   17572        2659 :          inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
   17573             :          {
   17574        2659 :             branch_.second = false;
   17575        2659 :             return branch_.first;
   17576             :          }
   17577             : 
   17578      143891 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   17579             :          {
   17580      143891 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
   17581      143891 :          }
   17582             : 
   17583      455054 :          std::size_t node_depth() const exprtk_override
   17584             :          {
   17585      455054 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   17586             :          }
   17587             : 
   17588             :       private:
   17589             : 
   17590             :          boc_node(const boc_node<T,Operation>&) exprtk_delete;
   17591             :          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete;
   17592             : 
   17593             :          const T  c_;
   17594             :          branch_t branch_;
   17595             :       };
   17596             : 
   17597             :       #ifndef exprtk_disable_string_capabilities
   17598             :       template <typename T, typename SType0, typename SType1, typename Operation>
   17599             :       class sos_node exprtk_final : public sos_base_node<T>
   17600             :       {
   17601             :       public:
   17602             : 
   17603             :          typedef expression_node<T>* expression_ptr;
   17604             :          typedef Operation operation_t;
   17605             : 
   17606             :          // string op string node
   17607       20042 :          explicit sos_node(SType0 p0, SType1 p1)
   17608       20042 :          : s0_(p0)
   17609       20042 :          , s1_(p1)
   17610       20042 :          {}
   17611             : 
   17612       20041 :          inline T value() const exprtk_override
   17613             :          {
   17614       20041 :             return Operation::process(s0_,s1_);
   17615             :          }
   17616             : 
   17617      221104 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17618             :          {
   17619      221104 :             return Operation::type();
   17620             :          }
   17621             : 
   17622           0 :          inline operator_type operation() const exprtk_override
   17623             :          {
   17624           0 :             return Operation::operation();
   17625             :          }
   17626             : 
   17627             :          inline std::string& s0()
   17628             :          {
   17629             :             return s0_;
   17630             :          }
   17631             : 
   17632             :          inline std::string& s1()
   17633             :          {
   17634             :             return s1_;
   17635             :          }
   17636             : 
   17637             :       protected:
   17638             : 
   17639             :          SType0 s0_;
   17640             :          SType1 s1_;
   17641             : 
   17642             :       private:
   17643             : 
   17644             :          sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
   17645             :          sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
   17646             :       };
   17647             : 
   17648             :       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
   17649             :       class str_xrox_node exprtk_final : public sos_base_node<T>
   17650             :       {
   17651             :       public:
   17652             : 
   17653             :          typedef expression_node<T>* expression_ptr;
   17654             :          typedef Operation operation_t;
   17655             :          typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type;
   17656             : 
   17657             :          // string-range op string node
   17658        3550 :          explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
   17659        3550 :          : s0_ (p0 )
   17660        3550 :          , s1_ (p1 )
   17661        3550 :          , rp0_(rp0)
   17662        3550 :          {}
   17663             : 
   17664        7100 :         ~str_xrox_node()
   17665             :          {
   17666        3550 :             rp0_.free();
   17667        7100 :          }
   17668             : 
   17669        3550 :          inline T value() const exprtk_override
   17670             :          {
   17671        3550 :             std::size_t r0 = 0;
   17672        3550 :             std::size_t r1 = 0;
   17673             : 
   17674        3550 :             if (rp0_(r0, r1, s0_.size()))
   17675        3550 :                return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
   17676             :             else
   17677           0 :                return T(0);
   17678             :          }
   17679             : 
   17680       17750 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17681             :          {
   17682       17750 :             return Operation::type();
   17683             :          }
   17684             : 
   17685           0 :          inline operator_type operation() const exprtk_override
   17686             :          {
   17687           0 :             return Operation::operation();
   17688             :          }
   17689             : 
   17690             :          inline std::string& s0()
   17691             :          {
   17692             :             return s0_;
   17693             :          }
   17694             : 
   17695             :          inline std::string& s1()
   17696             :          {
   17697             :             return s1_;
   17698             :          }
   17699             : 
   17700             :       protected:
   17701             : 
   17702             :          SType0    s0_;
   17703             :          SType1    s1_;
   17704             :          RangePack rp0_;
   17705             : 
   17706             :       private:
   17707             : 
   17708             :          str_xrox_node(const node_type&) exprtk_delete;
   17709             :          node_type& operator=(const node_type&) exprtk_delete;
   17710             :       };
   17711             : 
   17712             :       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
   17713             :       class str_xoxr_node exprtk_final : public sos_base_node<T>
   17714             :       {
   17715             :       public:
   17716             : 
   17717             :          typedef expression_node<T>* expression_ptr;
   17718             :          typedef Operation operation_t;
   17719             :          typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type;
   17720             : 
   17721             :          // string op string range node
   17722        3450 :          explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
   17723        3450 :          : s0_ (p0 )
   17724        3450 :          , s1_ (p1 )
   17725        3450 :          , rp1_(rp1)
   17726        3450 :          {}
   17727             : 
   17728        6900 :         ~str_xoxr_node()
   17729             :          {
   17730        3450 :             rp1_.free();
   17731        6900 :          }
   17732             : 
   17733        3450 :          inline T value() const exprtk_override
   17734             :          {
   17735        3450 :             std::size_t r0 = 0;
   17736        3450 :             std::size_t r1 = 0;
   17737             : 
   17738        3450 :             if (rp1_(r0, r1, s1_.size()))
   17739             :             {
   17740             :                return Operation::process
   17741        3450 :                       (
   17742        3450 :                          s0_,
   17743        3450 :                          s1_.substr(r0, (r1 - r0) + 1)
   17744        3450 :                       );
   17745             :             }
   17746             :             else
   17747           0 :                return T(0);
   17748             :          }
   17749             : 
   17750       17250 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17751             :          {
   17752       17250 :             return Operation::type();
   17753             :          }
   17754             : 
   17755           0 :          inline operator_type operation() const exprtk_override
   17756             :          {
   17757           0 :             return Operation::operation();
   17758             :          }
   17759             : 
   17760             :          inline std::string& s0()
   17761             :          {
   17762             :             return s0_;
   17763             :          }
   17764             : 
   17765             :          inline std::string& s1()
   17766             :          {
   17767             :             return s1_;
   17768             :          }
   17769             : 
   17770             :       protected:
   17771             : 
   17772             :          SType0    s0_;
   17773             :          SType1    s1_;
   17774             :          RangePack rp1_;
   17775             : 
   17776             :       private:
   17777             : 
   17778             :          str_xoxr_node(const node_type&) exprtk_delete;
   17779             :          node_type& operator=(const node_type&) exprtk_delete;
   17780             :       };
   17781             : 
   17782             :       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
   17783             :       class str_xroxr_node exprtk_final : public sos_base_node<T>
   17784             :       {
   17785             :       public:
   17786             : 
   17787             :          typedef expression_node<T>* expression_ptr;
   17788             :          typedef Operation operation_t;
   17789             :          typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type;
   17790             : 
   17791             :          // string-range op string-range node
   17792        3350 :          explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
   17793        3350 :          : s0_ (p0 )
   17794        3350 :          , s1_ (p1 )
   17795        3350 :          , rp0_(rp0)
   17796        3350 :          , rp1_(rp1)
   17797        3350 :          {}
   17798             : 
   17799        6700 :         ~str_xroxr_node()
   17800             :          {
   17801        3350 :             rp0_.free();
   17802        3350 :             rp1_.free();
   17803       10050 :          }
   17804             : 
   17805        3350 :          inline T value() const exprtk_override
   17806             :          {
   17807        3350 :             std::size_t r0_0 = 0;
   17808        3350 :             std::size_t r0_1 = 0;
   17809        3350 :             std::size_t r1_0 = 0;
   17810        3350 :             std::size_t r1_1 = 0;
   17811             : 
   17812        3350 :             if (
   17813        6700 :                  rp0_(r0_0, r1_0, s0_.size()) &&
   17814        6700 :                  rp1_(r0_1, r1_1, s1_.size())
   17815             :                )
   17816             :             {
   17817             :                return Operation::process
   17818        6700 :                       (
   17819        3350 :                          s0_.substr(r0_0, (r1_0 - r0_0) + 1),
   17820        3350 :                          s1_.substr(r0_1, (r1_1 - r0_1) + 1)
   17821        3350 :                       );
   17822             :             }
   17823             :             else
   17824           0 :                return T(0);
   17825             :          }
   17826             : 
   17827       16750 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17828             :          {
   17829       16750 :             return Operation::type();
   17830             :          }
   17831             : 
   17832           0 :          inline operator_type operation() const exprtk_override
   17833             :          {
   17834           0 :             return Operation::operation();
   17835             :          }
   17836             : 
   17837             :          inline std::string& s0()
   17838             :          {
   17839             :             return s0_;
   17840             :          }
   17841             : 
   17842             :          inline std::string& s1()
   17843             :          {
   17844             :             return s1_;
   17845             :          }
   17846             : 
   17847             :       protected:
   17848             : 
   17849             :          SType0    s0_;
   17850             :          SType1    s1_;
   17851             :          RangePack rp0_;
   17852             :          RangePack rp1_;
   17853             : 
   17854             :       private:
   17855             : 
   17856             :          str_xroxr_node(const node_type&) exprtk_delete;
   17857             :          node_type& operator=(const node_type&) exprtk_delete;
   17858             :       };
   17859             : 
   17860             :       template <typename T, typename Operation>
   17861             :       class str_sogens_node exprtk_final : public binary_node<T>
   17862             :       {
   17863             :       public:
   17864             : 
   17865             :          typedef expression_node <T>* expression_ptr;
   17866             :          typedef string_base_node<T>* str_base_ptr;
   17867             :          typedef range_pack      <T>  range_t;
   17868             :          typedef range_t*             range_ptr;
   17869             :          typedef range_interface <T>  irange_t;
   17870             :          typedef irange_t*            irange_ptr;
   17871             : 
   17872             :          using binary_node<T>::branch;
   17873             : 
   17874        4846 :          str_sogens_node(const operator_type& opr,
   17875             :                          expression_ptr branch0,
   17876             :                          expression_ptr branch1)
   17877             :          : binary_node<T>(opr, branch0, branch1)
   17878        4846 :          , str0_base_ptr_ (0)
   17879        4846 :          , str1_base_ptr_ (0)
   17880        4846 :          , str0_range_ptr_(0)
   17881        4846 :          , str1_range_ptr_(0)
   17882        4846 :          , initialised_   (false)
   17883             :          {
   17884        4846 :             if (is_generally_string_node(branch(0)))
   17885             :             {
   17886        4846 :                str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
   17887             : 
   17888        4846 :                if (0 == str0_base_ptr_)
   17889           0 :                   return;
   17890             : 
   17891        4846 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
   17892             : 
   17893        4846 :                if (0 == range)
   17894           0 :                   return;
   17895             : 
   17896        4846 :                str0_range_ptr_ = &(range->range_ref());
   17897             :             }
   17898             : 
   17899        4846 :             if (is_generally_string_node(branch(1)))
   17900             :             {
   17901        4846 :                str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
   17902             : 
   17903        4846 :                if (0 == str1_base_ptr_)
   17904           0 :                   return;
   17905             : 
   17906        4846 :                irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
   17907             : 
   17908        4846 :                if (0 == range)
   17909           0 :                   return;
   17910             : 
   17911        4846 :                str1_range_ptr_ = &(range->range_ref());
   17912             :             }
   17913             : 
   17914        4846 :             initialised_ =
   17915        9692 :                str0_base_ptr_  &&
   17916        4846 :                str1_base_ptr_  &&
   17917       14538 :                str0_range_ptr_ &&
   17918        4846 :                str1_range_ptr_;
   17919             : 
   17920        4846 :             assert(valid());
   17921           0 :          }
   17922             : 
   17923        4846 :          inline T value() const exprtk_override
   17924             :          {
   17925        4846 :             branch(0)->value();
   17926        4846 :             branch(1)->value();
   17927             : 
   17928        4846 :             std::size_t str0_r0 = 0;
   17929        4846 :             std::size_t str0_r1 = 0;
   17930             : 
   17931        4846 :             std::size_t str1_r0 = 0;
   17932        4846 :             std::size_t str1_r1 = 0;
   17933             : 
   17934        4846 :             const range_t& range0 = (*str0_range_ptr_);
   17935        4846 :             const range_t& range1 = (*str1_range_ptr_);
   17936             : 
   17937        4846 :             if (
   17938        9692 :                  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
   17939        9692 :                  range1(str1_r0, str1_r1, str1_base_ptr_->size())
   17940             :                )
   17941             :             {
   17942             :                return Operation::process
   17943       14538 :                       (
   17944        4846 :                          str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)),
   17945        4846 :                          str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0))
   17946        4846 :                       );
   17947             :             }
   17948             : 
   17949           0 :             return std::numeric_limits<T>::quiet_NaN();
   17950             :          }
   17951             : 
   17952       24830 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17953             :          {
   17954       24830 :             return Operation::type();
   17955             :          }
   17956             : 
   17957        7392 :          inline bool valid() const exprtk_override
   17958             :          {
   17959        7392 :             return initialised_;
   17960             :          }
   17961             : 
   17962             :       private:
   17963             : 
   17964             :          str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete;
   17965             :          str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete;
   17966             : 
   17967             :          str_base_ptr str0_base_ptr_;
   17968             :          str_base_ptr str1_base_ptr_;
   17969             :          range_ptr    str0_range_ptr_;
   17970             :          range_ptr    str1_range_ptr_;
   17971             :          bool         initialised_;
   17972             :       };
   17973             : 
   17974             :       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
   17975             :       class sosos_node exprtk_final : public sosos_base_node<T>
   17976             :       {
   17977             :       public:
   17978             : 
   17979             :          typedef expression_node<T>* expression_ptr;
   17980             :          typedef Operation operation_t;
   17981             :          typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type;
   17982             : 
   17983             :          // string op string op string node
   17984         300 :          explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
   17985         300 :          : s0_(p0)
   17986         300 :          , s1_(p1)
   17987         300 :          , s2_(p2)
   17988         300 :          {}
   17989             : 
   17990         300 :          inline T value() const exprtk_override
   17991             :          {
   17992         300 :             return Operation::process(s0_, s1_, s2_);
   17993             :          }
   17994             : 
   17995        1500 :          inline typename expression_node<T>::node_type type() const exprtk_override
   17996             :          {
   17997        1500 :             return Operation::type();
   17998             :          }
   17999             : 
   18000           0 :          inline operator_type operation() const exprtk_override
   18001             :          {
   18002           0 :             return Operation::operation();
   18003             :          }
   18004             : 
   18005             :          inline std::string& s0()
   18006             :          {
   18007             :             return s0_;
   18008             :          }
   18009             : 
   18010             :          inline std::string& s1()
   18011             :          {
   18012             :             return s1_;
   18013             :          }
   18014             : 
   18015             :          inline std::string& s2()
   18016             :          {
   18017             :             return s2_;
   18018             :          }
   18019             : 
   18020             :       protected:
   18021             : 
   18022             :          SType0 s0_;
   18023             :          SType1 s1_;
   18024             :          SType2 s2_;
   18025             : 
   18026             :       private:
   18027             : 
   18028             :          sosos_node(const node_type&) exprtk_delete;
   18029             :          node_type& operator=(const node_type&) exprtk_delete;
   18030             :       };
   18031             :       #endif
   18032             : 
   18033             :       template <typename T, typename PowOp>
   18034             :       class ipow_node exprtk_final: public expression_node<T>
   18035             :       {
   18036             :       public:
   18037             : 
   18038             :          typedef expression_node<T>* expression_ptr;
   18039             :          typedef PowOp operation_t;
   18040             : 
   18041       59062 :          explicit ipow_node(const T& v)
   18042       59062 :          : v_(v)
   18043       59062 :          {}
   18044             : 
   18045       59062 :          inline T value() const exprtk_override
   18046             :          {
   18047       59062 :             return PowOp::result(v_);
   18048             :          }
   18049             : 
   18050     1665218 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18051             :          {
   18052     1665218 :             return expression_node<T>::e_ipow;
   18053             :          }
   18054             : 
   18055             :       private:
   18056             : 
   18057             :          ipow_node(const ipow_node<T,PowOp>&) exprtk_delete;
   18058             :          ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete;
   18059             : 
   18060             :          const T& v_;
   18061             :       };
   18062             : 
   18063             :       template <typename T, typename PowOp>
   18064             :       class bipow_node exprtk_final : public expression_node<T>
   18065             :       {
   18066             :       public:
   18067             : 
   18068             :          typedef expression_node<T>* expression_ptr;
   18069             :          typedef std::pair<expression_ptr, bool> branch_t;
   18070             :          typedef PowOp operation_t;
   18071             : 
   18072           1 :          explicit bipow_node(expression_ptr branch)
   18073           1 :          {
   18074           1 :             construct_branch_pair(branch_, branch);
   18075           1 :             assert(valid());
   18076           1 :          }
   18077             : 
   18078           1 :          inline T value() const exprtk_override
   18079             :          {
   18080           1 :             return PowOp::result(branch_.first->value());
   18081             :          }
   18082             : 
   18083          13 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18084             :          {
   18085          13 :             return expression_node<T>::e_ipow;
   18086             :          }
   18087             : 
   18088           3 :          inline bool valid() const exprtk_override
   18089             :          {
   18090           3 :             return branch_.first && branch_.first->valid();
   18091             :          }
   18092             : 
   18093           1 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18094             :          {
   18095           1 :             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
   18096           1 :          }
   18097             : 
   18098           3 :          std::size_t node_depth() const exprtk_override
   18099             :          {
   18100           3 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18101             :          }
   18102             : 
   18103             :       private:
   18104             : 
   18105             :          bipow_node(const bipow_node<T,PowOp>&) exprtk_delete;
   18106             :          bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete;
   18107             : 
   18108             :          branch_t branch_;
   18109             :       };
   18110             : 
   18111             :       template <typename T, typename PowOp>
   18112             :       class ipowinv_node exprtk_final : public expression_node<T>
   18113             :       {
   18114             :       public:
   18115             : 
   18116             :          typedef expression_node<T>* expression_ptr;
   18117             :          typedef PowOp operation_t;
   18118             : 
   18119        3050 :          explicit ipowinv_node(const T& v)
   18120        3050 :          : v_(v)
   18121        3050 :          {}
   18122             : 
   18123        3050 :          inline T value() const exprtk_override
   18124             :          {
   18125        3050 :             return (T(1) / PowOp::result(v_));
   18126             :          }
   18127             : 
   18128       39700 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18129             :          {
   18130       39700 :             return expression_node<T>::e_ipowinv;
   18131             :          }
   18132             : 
   18133             :       private:
   18134             : 
   18135             :          ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete;
   18136             :          ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete;
   18137             : 
   18138             :          const T& v_;
   18139             :       };
   18140             : 
   18141             :       template <typename T, typename PowOp>
   18142             :       class bipowinv_node exprtk_final : public expression_node<T>
   18143             :       {
   18144             :       public:
   18145             : 
   18146             :          typedef expression_node<T>* expression_ptr;
   18147             :          typedef std::pair<expression_ptr, bool> branch_t;
   18148             :          typedef PowOp operation_t;
   18149             : 
   18150           0 :          explicit bipowinv_node(expression_ptr branch)
   18151           0 :          {
   18152           0 :             construct_branch_pair(branch_, branch);
   18153           0 :             assert(valid());
   18154           0 :          }
   18155             : 
   18156           0 :          inline T value() const exprtk_override
   18157             :          {
   18158           0 :             return (T(1) / PowOp::result(branch_.first->value()));
   18159             :          }
   18160             : 
   18161           0 :          inline typename expression_node<T>::node_type type() const exprtk_override
   18162             :          {
   18163           0 :             return expression_node<T>::e_ipowinv;
   18164             :          }
   18165             : 
   18166           0 :          inline bool valid() const exprtk_override
   18167             :          {
   18168           0 :             return branch_.first && branch_.first->valid();
   18169             :          }
   18170             : 
   18171           0 :          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
   18172             :          {
   18173           0 :             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
   18174           0 :          }
   18175             : 
   18176           0 :          std::size_t node_depth() const exprtk_override
   18177             :          {
   18178           0 :             return expression_node<T>::ndb_t::compute_node_depth(branch_);
   18179             :          }
   18180             : 
   18181             :       private:
   18182             : 
   18183             :          bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete;
   18184             :          bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete;
   18185             : 
   18186             :          branch_t branch_;
   18187             :       };
   18188             : 
   18189             :       template <typename T>
   18190     2056379 :       inline bool is_vov_node(const expression_node<T>* node)
   18191             :       {
   18192     2056379 :          return (0 != dynamic_cast<const vov_base_node<T>*>(node));
   18193             :       }
   18194             : 
   18195             :       template <typename T>
   18196     1801215 :       inline bool is_cov_node(const expression_node<T>* node)
   18197             :       {
   18198     1801215 :          return (0 != dynamic_cast<const cov_base_node<T>*>(node));
   18199             :       }
   18200             : 
   18201             :       template <typename T>
   18202     1568251 :       inline bool is_voc_node(const expression_node<T>* node)
   18203             :       {
   18204     1568251 :          return (0 != dynamic_cast<const voc_base_node<T>*>(node));
   18205             :       }
   18206             : 
   18207             :       template <typename T>
   18208      703762 :       inline bool is_cob_node(const expression_node<T>* node)
   18209             :       {
   18210      703762 :          return (0 != dynamic_cast<const cob_base_node<T>*>(node));
   18211             :       }
   18212             : 
   18213             :       template <typename T>
   18214      759143 :       inline bool is_boc_node(const expression_node<T>* node)
   18215             :       {
   18216      759143 :          return (0 != dynamic_cast<const boc_base_node<T>*>(node));
   18217             :       }
   18218             : 
   18219             :       template <typename T>
   18220     1377878 :       inline bool is_t0ot1ot2_node(const expression_node<T>* node)
   18221             :       {
   18222     1377878 :          return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
   18223             :       }
   18224             : 
   18225             :       template <typename T>
   18226     1031721 :       inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
   18227             :       {
   18228     1031721 :          return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
   18229             :       }
   18230             : 
   18231             :       template <typename T>
   18232     1620699 :       inline bool is_uv_node(const expression_node<T>* node)
   18233             :       {
   18234     1620699 :          return (0 != dynamic_cast<const uv_base_node<T>*>(node));
   18235             :       }
   18236             : 
   18237             :       template <typename T>
   18238     7499445 :       inline bool is_string_node(const expression_node<T>* node)
   18239             :       {
   18240     7499445 :          return node && (expression_node<T>::e_stringvar == node->type());
   18241             :       }
   18242             : 
   18243             :       template <typename T>
   18244     1477984 :       inline bool is_string_range_node(const expression_node<T>* node)
   18245             :       {
   18246     1477984 :          return node && (expression_node<T>::e_stringvarrng == node->type());
   18247             :       }
   18248             : 
   18249             :       template <typename T>
   18250     1468279 :       inline bool is_const_string_node(const expression_node<T>* node)
   18251             :       {
   18252     1468279 :          return node && (expression_node<T>::e_stringconst == node->type());
   18253             :       }
   18254             : 
   18255             :       template <typename T>
   18256     1467268 :       inline bool is_const_string_range_node(const expression_node<T>* node)
   18257             :       {
   18258     1467268 :          return node && (expression_node<T>::e_cstringvarrng == node->type());
   18259             :       }
   18260             : 
   18261             :       template <typename T>
   18262       89136 :       inline bool is_string_assignment_node(const expression_node<T>* node)
   18263             :       {
   18264       89136 :          return node && (expression_node<T>::e_strass == node->type());
   18265             :       }
   18266             : 
   18267             :       template <typename T>
   18268       87536 :       inline bool is_string_concat_node(const expression_node<T>* node)
   18269             :       {
   18270       87536 :          return node && (expression_node<T>::e_strconcat == node->type());
   18271             :       }
   18272             : 
   18273             :       template <typename T>
   18274       84880 :       inline bool is_string_function_node(const expression_node<T>* node)
   18275             :       {
   18276       84880 :          return node && (expression_node<T>::e_strfunction == node->type());
   18277             :       }
   18278             : 
   18279             :       template <typename T>
   18280       84850 :       inline bool is_string_condition_node(const expression_node<T>* node)
   18281             :       {
   18282       84850 :          return node && (expression_node<T>::e_strcondition == node->type());
   18283             :       }
   18284             : 
   18285             :       template <typename T>
   18286       83750 :       inline bool is_string_ccondition_node(const expression_node<T>* node)
   18287             :       {
   18288       83750 :          return node && (expression_node<T>::e_strccondition == node->type());
   18289             :       }
   18290             : 
   18291             :       template <typename T>
   18292       83750 :       inline bool is_string_vararg_node(const expression_node<T>* node)
   18293             :       {
   18294       83750 :          return node && (expression_node<T>::e_stringvararg == node->type());
   18295             :       }
   18296             : 
   18297             :       template <typename T>
   18298       88836 :       inline bool is_genricstring_range_node(const expression_node<T>* node)
   18299             :       {
   18300       88836 :          return node && (expression_node<T>::e_strgenrange == node->type());
   18301             :       }
   18302             : 
   18303             :       template <typename T>
   18304    27233512 :       inline bool is_generally_string_node(const expression_node<T>* node)
   18305             :       {
   18306    27233512 :          if (node)
   18307             :          {
   18308    27232070 :             switch (node->type())
   18309             :             {
   18310      558113 :                case expression_node<T>::e_stringvar     :
   18311             :                case expression_node<T>::e_stringconst   :
   18312             :                case expression_node<T>::e_stringvarrng  :
   18313             :                case expression_node<T>::e_cstringvarrng :
   18314             :                case expression_node<T>::e_strgenrange   :
   18315             :                case expression_node<T>::e_strass        :
   18316             :                case expression_node<T>::e_strconcat     :
   18317             :                case expression_node<T>::e_strfunction   :
   18318             :                case expression_node<T>::e_strcondition  :
   18319             :                case expression_node<T>::e_strccondition :
   18320      558113 :                case expression_node<T>::e_stringvararg  : return true;
   18321    26673957 :                default                                  : return false;
   18322             :             }
   18323             :          }
   18324             : 
   18325        1442 :          return false;
   18326             :       }
   18327             : 
   18328             :       class node_allocator
   18329             :       {
   18330             :       public:
   18331             : 
   18332             :          template <typename ResultNode, typename OpType, typename ExprNode>
   18333       97415 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
   18334             :          {
   18335             :             expression_node<typename ResultNode::value_type>* result =
   18336       97415 :                allocate<ResultNode>(operation, branch[0]);
   18337       97415 :             result->node_depth();
   18338       97415 :             return result;
   18339             :          }
   18340             : 
   18341             :          template <typename ResultNode, typename OpType, typename ExprNode>
   18342      494314 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
   18343             :          {
   18344             :             expression_node<typename ResultNode::value_type>* result =
   18345      494314 :                allocate<ResultNode>(operation, branch[0], branch[1]);
   18346      494314 :             result->node_depth();
   18347      494314 :             return result;
   18348             :          }
   18349             : 
   18350             :          template <typename ResultNode, typename OpType, typename ExprNode>
   18351         836 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
   18352             :          {
   18353             :             expression_node<typename ResultNode::value_type>* result =
   18354         836 :                allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
   18355         836 :             result->node_depth();
   18356         836 :             return result;
   18357             :          }
   18358             : 
   18359             :          template <typename ResultNode, typename OpType, typename ExprNode>
   18360         815 :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
   18361             :          {
   18362             :             expression_node<typename ResultNode::value_type>* result =
   18363         815 :                allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
   18364         815 :             result->node_depth();
   18365         815 :             return result;
   18366             :          }
   18367             : 
   18368             :          template <typename ResultNode, typename OpType, typename ExprNode>
   18369             :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
   18370             :          {
   18371             :             expression_node<typename ResultNode::value_type>* result =
   18372             :                allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
   18373             :             result->node_depth();
   18374             :             return result;
   18375             :          }
   18376             : 
   18377             :          template <typename ResultNode, typename OpType, typename ExprNode>
   18378             :          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
   18379             :          {
   18380             :             expression_node<typename ResultNode::value_type>* result =
   18381             :                allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
   18382             :             result->node_depth();
   18383             :             return result;
   18384             :          }
   18385             : 
   18386             :          template <typename node_type>
   18387         785 :          inline expression_node<typename node_type::value_type>* allocate() const
   18388             :          {
   18389         785 :             return (new node_type());
   18390             :          }
   18391             : 
   18392             :          template <typename node_type,
   18393             :                    typename Type,
   18394             :                    typename Allocator,
   18395             :                    template <typename, typename> class Sequence>
   18396       51318 :          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
   18397             :          {
   18398             :             expression_node<typename node_type::value_type>*
   18399       51318 :             result = (new node_type(seq));
   18400       51318 :             result->node_depth();
   18401       51318 :             return result;
   18402             :          }
   18403             : 
   18404             :          template <typename node_type, typename T1>
   18405     2401909 :          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
   18406             :          {
   18407             :             expression_node<typename node_type::value_type>*
   18408     2401909 :             result = (new node_type(t1));
   18409     2401909 :             result->node_depth();
   18410     2401909 :             return result;
   18411             :          }
   18412             : 
   18413             :          template <typename node_type, typename T1>
   18414        5150 :          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
   18415             :          {
   18416             :             expression_node<typename node_type::value_type>*
   18417        5150 :             result = (new node_type(t1));
   18418        5150 :             result->node_depth();
   18419        5150 :             return result;
   18420             :          }
   18421             : 
   18422             :          template <typename node_type,
   18423             :                    typename T1, typename T2>
   18424      509141 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
   18425             :          {
   18426             :             expression_node<typename node_type::value_type>*
   18427      509141 :             result = (new node_type(t1, t2));
   18428      509141 :             result->node_depth();
   18429      509141 :             return result;
   18430             :          }
   18431             : 
   18432             :          template <typename node_type,
   18433             :                    typename T1, typename T2>
   18434      734635 :          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
   18435             :          {
   18436             :             expression_node<typename node_type::value_type>*
   18437      734635 :             result = (new node_type(t1, t2));
   18438      734635 :             result->node_depth();
   18439      734635 :             return result;
   18440             :          }
   18441             : 
   18442             :          template <typename node_type,
   18443             :                    typename T1, typename T2>
   18444      317515 :          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
   18445             :          {
   18446             :             expression_node<typename node_type::value_type>*
   18447      317515 :             result = (new node_type(t1, t2));
   18448      317515 :             result->node_depth();
   18449      317515 :             return result;
   18450             :          }
   18451             : 
   18452             :          template <typename node_type,
   18453             :                    typename T1, typename T2>
   18454      286578 :          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
   18455             :          {
   18456             :             expression_node<typename node_type::value_type>*
   18457      286578 :             result = (new node_type(t1, t2));
   18458      286578 :             result->node_depth();
   18459      286578 :             return result;
   18460             :          }
   18461             : 
   18462             :          template <typename node_type,
   18463             :                    typename T1, typename T2>
   18464      121264 :          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
   18465             :          {
   18466             :             expression_node<typename node_type::value_type>*
   18467      121264 :             result = (new node_type(t1, t2));
   18468      121264 :             result->node_depth();
   18469      121264 :             return result;
   18470             :          }
   18471             : 
   18472             :          template <typename node_type,
   18473             :                    typename T1, typename T2, typename T3>
   18474       11846 :          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
   18475             :          {
   18476             :             expression_node<typename node_type::value_type>*
   18477       11846 :             result = (new node_type(t1, t2, t3));
   18478       11846 :             result->node_depth();
   18479       11846 :             return result;
   18480             :          }
   18481             : 
   18482             :          template <typename node_type,
   18483             :                    typename T1, typename T2, typename T3, typename T4>
   18484        3350 :          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
   18485             :          {
   18486             :             expression_node<typename node_type::value_type>*
   18487        3350 :             result = (new node_type(t1, t2, t3, t4));
   18488        3350 :             result->node_depth();
   18489        3350 :             return result;
   18490             :          }
   18491             : 
   18492             :          template <typename node_type,
   18493             :                    typename T1, typename T2, typename T3>
   18494       23916 :          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
   18495             :          {
   18496             :             expression_node<typename node_type::value_type>*
   18497       23916 :             result = (new node_type(t1, t2, t3));
   18498       23916 :             result->node_depth();
   18499       23916 :             return result;
   18500             :          }
   18501             : 
   18502             :          template <typename node_type,
   18503             :                    typename T1, typename T2, typename T3, typename T4>
   18504        1510 :          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
   18505             :          {
   18506             :             expression_node<typename node_type::value_type>*
   18507        1510 :             result = (new node_type(t1, t2, t3, t4));
   18508        1510 :             result->node_depth();
   18509        1510 :             return result;
   18510             :          }
   18511             : 
   18512             :          template <typename node_type,
   18513             :                    typename T1, typename T2, typename T3, typename T4, typename T5>
   18514         610 :          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
   18515             :          {
   18516             :             expression_node<typename node_type::value_type>*
   18517         610 :             result = (new node_type(t1, t2, t3, t4, t5));
   18518         610 :             result->node_depth();
   18519         610 :             return result;
   18520             :          }
   18521             : 
   18522             :          template <typename node_type,
   18523             :                    typename T1, typename T2, typename T3>
   18524      507464 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18525             :                                                                           const T3& t3) const
   18526             :          {
   18527             :             expression_node<typename node_type::value_type>*
   18528      507464 :             result = (new node_type(t1, t2, t3));
   18529      507464 :             result->node_depth();
   18530      507464 :             return result;
   18531             :          }
   18532             : 
   18533             :          template <typename node_type,
   18534             :                    typename T1, typename T2,
   18535             :                    typename T3, typename T4>
   18536       23145 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18537             :                                                                           const T3& t3, const T4& t4) const
   18538             :          {
   18539             :             expression_node<typename node_type::value_type>*
   18540       23145 :             result = (new node_type(t1, t2, t3, t4));
   18541       23145 :             result->node_depth();
   18542       23145 :             return result;
   18543             :          }
   18544             : 
   18545             :          template <typename node_type,
   18546             :                    typename T1, typename T2,
   18547             :                    typename T3, typename T4, typename T5>
   18548         815 :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18549             :                                                                           const T3& t3, const T4& t4,
   18550             :                                                                           const T5& t5) const
   18551             :          {
   18552             :             expression_node<typename node_type::value_type>*
   18553         815 :             result = (new node_type(t1, t2, t3, t4, t5));
   18554         815 :             result->node_depth();
   18555         815 :             return result;
   18556             :          }
   18557             : 
   18558             :          template <typename node_type,
   18559             :                    typename T1, typename T2,
   18560             :                    typename T3, typename T4, typename T5, typename T6>
   18561             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18562             :                                                                           const T3& t3, const T4& t4,
   18563             :                                                                           const T5& t5, const T6& t6) const
   18564             :          {
   18565             :             expression_node<typename node_type::value_type>*
   18566             :             result = (new node_type(t1, t2, t3, t4, t5, t6));
   18567             :             result->node_depth();
   18568             :             return result;
   18569             :          }
   18570             : 
   18571             :          template <typename node_type,
   18572             :                    typename T1, typename T2,
   18573             :                    typename T3, typename T4,
   18574             :                    typename T5, typename T6, typename T7>
   18575             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18576             :                                                                           const T3& t3, const T4& t4,
   18577             :                                                                           const T5& t5, const T6& t6,
   18578             :                                                                           const T7& t7) const
   18579             :          {
   18580             :             expression_node<typename node_type::value_type>*
   18581             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
   18582             :             result->node_depth();
   18583             :             return result;
   18584             :          }
   18585             : 
   18586             :          template <typename node_type,
   18587             :                    typename T1, typename T2,
   18588             :                    typename T3, typename T4,
   18589             :                    typename T5, typename T6,
   18590             :                    typename T7, typename T8>
   18591             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18592             :                                                                           const T3& t3, const T4& t4,
   18593             :                                                                           const T5& t5, const T6& t6,
   18594             :                                                                           const T7& t7, const T8& t8) const
   18595             :          {
   18596             :             expression_node<typename node_type::value_type>*
   18597             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
   18598             :             result->node_depth();
   18599             :             return result;
   18600             :          }
   18601             : 
   18602             :          template <typename node_type,
   18603             :                    typename T1, typename T2,
   18604             :                    typename T3, typename T4,
   18605             :                    typename T5, typename T6,
   18606             :                    typename T7, typename T8, typename T9>
   18607             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
   18608             :                                                                           const T3& t3, const T4& t4,
   18609             :                                                                           const T5& t5, const T6& t6,
   18610             :                                                                           const T7& t7, const T8& t8,
   18611             :                                                                           const T9& t9) const
   18612             :          {
   18613             :             expression_node<typename node_type::value_type>*
   18614             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
   18615             :             result->node_depth();
   18616             :             return result;
   18617             :          }
   18618             : 
   18619             :          template <typename node_type,
   18620             :                    typename T1, typename T2,
   18621             :                    typename T3, typename T4,
   18622             :                    typename T5, typename T6,
   18623             :                    typename T7, typename T8,
   18624             :                    typename T9, typename T10>
   18625             :          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
   18626             :                                                                           const T3& t3, const  T4&  t4,
   18627             :                                                                           const T5& t5, const  T6&  t6,
   18628             :                                                                           const T7& t7, const  T8&  t8,
   18629             :                                                                           const T9& t9, const T10& t10) const
   18630             :          {
   18631             :             expression_node<typename node_type::value_type>*
   18632             :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
   18633             :             result->node_depth();
   18634             :             return result;
   18635             :          }
   18636             : 
   18637             :          template <typename node_type,
   18638             :                    typename T1, typename T2, typename T3>
   18639      369324 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
   18640             :          {
   18641             :             expression_node<typename node_type::value_type>*
   18642      369324 :             result = (new node_type(t1, t2, t3));
   18643      369324 :             result->node_depth();
   18644      369324 :             return result;
   18645             :          }
   18646             : 
   18647             :          template <typename node_type,
   18648             :                    typename T1, typename T2,
   18649             :                    typename T3, typename T4>
   18650       97284 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   18651             :                                                                                T3 t3, T4 t4) const
   18652             :          {
   18653             :             expression_node<typename node_type::value_type>*
   18654       97284 :             result = (new node_type(t1, t2, t3, t4));
   18655       97284 :             result->node_depth();
   18656       97284 :             return result;
   18657             :          }
   18658             : 
   18659             :          template <typename node_type,
   18660             :                    typename T1, typename T2,
   18661             :                    typename T3, typename T4,
   18662             :                    typename T5>
   18663        5915 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   18664             :                                                                                T3 t3, T4 t4,
   18665             :                                                                                T5 t5) const
   18666             :          {
   18667             :             expression_node<typename node_type::value_type>*
   18668        5915 :             result = (new node_type(t1, t2, t3, t4, t5));
   18669        5915 :             result->node_depth();
   18670        5915 :             return result;
   18671             :          }
   18672             : 
   18673             :          template <typename node_type,
   18674             :                    typename T1, typename T2,
   18675             :                    typename T3, typename T4,
   18676             :                    typename T5, typename T6>
   18677             :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   18678             :                                                                                T3 t3, T4 t4,
   18679             :                                                                                T5 t5, T6 t6) const
   18680             :          {
   18681             :             expression_node<typename node_type::value_type>*
   18682             :             result = (new node_type(t1, t2, t3, t4, t5, t6));
   18683             :             result->node_depth();
   18684             :             return result;
   18685             :          }
   18686             : 
   18687             :          template <typename node_type,
   18688             :                    typename T1, typename T2,
   18689             :                    typename T3, typename T4,
   18690             :                    typename T5, typename T6, typename T7>
   18691        6537 :          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
   18692             :                                                                                T3 t3, T4 t4,
   18693             :                                                                                T5 t5, T6 t6,
   18694             :                                                                                T7 t7) const
   18695             :          {
   18696             :             expression_node<typename node_type::value_type>*
   18697        6537 :             result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
   18698        6537 :             result->node_depth();
   18699        6537 :             return result;
   18700             :          }
   18701             : 
   18702             :          template <typename T>
   18703           1 :          void inline free(expression_node<T>*& e) const
   18704             :          {
   18705             :             exprtk_debug(("node_allocator::free() - deleting expression_node "
   18706             :                           "type: %03d addr: %p\n",
   18707             :                           static_cast<int>(e->type()),
   18708             :                           reinterpret_cast<void*>(e)));
   18709           1 :             delete e;
   18710           1 :             e = 0;
   18711           1 :          }
   18712             :       };
   18713             : 
   18714      106542 :       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
   18715             :       {
   18716             :          #define register_op(Symbol, Type, Args)                                             \
   18717             :          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
   18718             : 
   18719      213084 :          register_op("abs"       , e_abs     , 1)
   18720      213084 :          register_op("acos"      , e_acos    , 1)
   18721      213084 :          register_op("acosh"     , e_acosh   , 1)
   18722      213084 :          register_op("asin"      , e_asin    , 1)
   18723      213084 :          register_op("asinh"     , e_asinh   , 1)
   18724      213084 :          register_op("atan"      , e_atan    , 1)
   18725      213084 :          register_op("atanh"     , e_atanh   , 1)
   18726      213084 :          register_op("ceil"      , e_ceil    , 1)
   18727      213084 :          register_op("cos"       , e_cos     , 1)
   18728      213084 :          register_op("cosh"      , e_cosh    , 1)
   18729      213084 :          register_op("exp"       , e_exp     , 1)
   18730      213084 :          register_op("expm1"     , e_expm1   , 1)
   18731      213084 :          register_op("floor"     , e_floor   , 1)
   18732      213084 :          register_op("log"       , e_log     , 1)
   18733      213084 :          register_op("log10"     , e_log10   , 1)
   18734      213084 :          register_op("log2"      , e_log2    , 1)
   18735      213084 :          register_op("log1p"     , e_log1p   , 1)
   18736      213084 :          register_op("round"     , e_round   , 1)
   18737      213084 :          register_op("sin"       , e_sin     , 1)
   18738      213084 :          register_op("sinc"      , e_sinc    , 1)
   18739      213084 :          register_op("sinh"      , e_sinh    , 1)
   18740      213084 :          register_op("sec"       , e_sec     , 1)
   18741      213084 :          register_op("csc"       , e_csc     , 1)
   18742      213084 :          register_op("sqrt"      , e_sqrt    , 1)
   18743      213084 :          register_op("tan"       , e_tan     , 1)
   18744      213084 :          register_op("tanh"      , e_tanh    , 1)
   18745      213084 :          register_op("cot"       , e_cot     , 1)
   18746      213084 :          register_op("rad2deg"   , e_r2d     , 1)
   18747      213084 :          register_op("deg2rad"   , e_d2r     , 1)
   18748      213084 :          register_op("deg2grad"  , e_d2g     , 1)
   18749      213084 :          register_op("grad2deg"  , e_g2d     , 1)
   18750      213084 :          register_op("sgn"       , e_sgn     , 1)
   18751      213084 :          register_op("not"       , e_notl    , 1)
   18752      213084 :          register_op("erf"       , e_erf     , 1)
   18753      213084 :          register_op("erfc"      , e_erfc    , 1)
   18754      213084 :          register_op("ncdf"      , e_ncdf    , 1)
   18755      213084 :          register_op("frac"      , e_frac    , 1)
   18756      213084 :          register_op("trunc"     , e_trunc   , 1)
   18757      213084 :          register_op("atan2"     , e_atan2   , 2)
   18758      213084 :          register_op("mod"       , e_mod     , 2)
   18759      213084 :          register_op("logn"      , e_logn    , 2)
   18760      213084 :          register_op("pow"       , e_pow     , 2)
   18761      213084 :          register_op("root"      , e_root    , 2)
   18762      213084 :          register_op("roundn"    , e_roundn  , 2)
   18763      213084 :          register_op("equal"     , e_equal   , 2)
   18764      213084 :          register_op("not_equal" , e_nequal  , 2)
   18765      213084 :          register_op("hypot"     , e_hypot   , 2)
   18766      213084 :          register_op("shr"       , e_shr     , 2)
   18767      213084 :          register_op("shl"       , e_shl     , 2)
   18768      213084 :          register_op("clamp"     , e_clamp   , 3)
   18769      213084 :          register_op("iclamp"    , e_iclamp  , 3)
   18770      213084 :          register_op("inrange"   , e_inrange , 3)
   18771             :          #undef register_op
   18772      106542 :       }
   18773             : 
   18774             :    } // namespace details
   18775             : 
   18776             :    class function_traits
   18777             :    {
   18778             :    public:
   18779             : 
   18780      132038 :       function_traits()
   18781      132038 :       : allow_zero_parameters_(false)
   18782      132038 :       , has_side_effects_(true)
   18783      132038 :       , min_num_args_(0)
   18784      132038 :       , max_num_args_(std::numeric_limits<std::size_t>::max())
   18785      132038 :       {}
   18786             : 
   18787          79 :       inline bool& allow_zero_parameters()
   18788             :       {
   18789          79 :          return allow_zero_parameters_;
   18790             :       }
   18791             : 
   18792      133478 :       inline bool& has_side_effects()
   18793             :       {
   18794      133478 :          return has_side_effects_;
   18795             :       }
   18796             : 
   18797         115 :       std::size_t& min_num_args()
   18798             :       {
   18799         115 :          return min_num_args_;
   18800             :       }
   18801             : 
   18802          51 :       std::size_t& max_num_args()
   18803             :       {
   18804          51 :          return max_num_args_;
   18805             :       }
   18806             : 
   18807             :    private:
   18808             : 
   18809             :       bool allow_zero_parameters_;
   18810             :       bool has_side_effects_;
   18811             :       std::size_t min_num_args_;
   18812             :       std::size_t max_num_args_;
   18813             :    };
   18814             : 
   18815             :    template <typename FunctionType>
   18816          62 :    void enable_zero_parameters(FunctionType& func)
   18817             :    {
   18818          62 :       func.allow_zero_parameters() = true;
   18819             : 
   18820          62 :       if (0 != func.min_num_args())
   18821             :       {
   18822           0 :          func.min_num_args() = 0;
   18823             :       }
   18824          62 :    }
   18825             : 
   18826             :    template <typename FunctionType>
   18827             :    void disable_zero_parameters(FunctionType& func)
   18828             :    {
   18829             :       func.allow_zero_parameters() = false;
   18830             :    }
   18831             : 
   18832             :    template <typename FunctionType>
   18833             :    void enable_has_side_effects(FunctionType& func)
   18834             :    {
   18835             :       func.has_side_effects() = true;
   18836             :    }
   18837             : 
   18838             :    template <typename FunctionType>
   18839      128736 :    void disable_has_side_effects(FunctionType& func)
   18840             :    {
   18841      128736 :       func.has_side_effects() = false;
   18842      128736 :    }
   18843             : 
   18844             :    template <typename FunctionType>
   18845           2 :    void set_min_num_args(FunctionType& func, const std::size_t& num_args)
   18846             :    {
   18847           2 :       func.min_num_args() = num_args;
   18848             : 
   18849           2 :       if ((0 != func.min_num_args()) && func.allow_zero_parameters())
   18850           0 :          func.allow_zero_parameters() = false;
   18851           2 :    }
   18852             : 
   18853             :    template <typename FunctionType>
   18854           2 :    void set_max_num_args(FunctionType& func, const std::size_t& num_args)
   18855             :    {
   18856           2 :       func.max_num_args() = num_args;
   18857           2 :    }
   18858             : 
   18859             :    template <typename T>
   18860             :    class ifunction : public function_traits
   18861             :    {
   18862             :    public:
   18863             : 
   18864      131097 :       explicit ifunction(const std::size_t& pc)
   18865      131097 :       : param_count(pc)
   18866      131097 :       {}
   18867             : 
   18868      131097 :       virtual ~ifunction()
   18869      131097 :       {}
   18870             : 
   18871             :       #define empty_method_body(N)                   \
   18872             :       {                                              \
   18873             :          exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \
   18874             :          return std::numeric_limits<T>::quiet_NaN(); \
   18875             :       }                                              \
   18876             : 
   18877           0 :       inline virtual T operator() ()
   18878           0 :       empty_method_body(0)
   18879             : 
   18880           0 :       inline virtual T operator() (const T&)
   18881           0 :       empty_method_body(1)
   18882             : 
   18883           0 :       inline virtual T operator() (const T&,const T&)
   18884           0 :       empty_method_body(2)
   18885             : 
   18886           0 :       inline virtual T operator() (const T&, const T&, const T&)
   18887           0 :       empty_method_body(3)
   18888             : 
   18889           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&)
   18890           0 :       empty_method_body(4)
   18891             : 
   18892           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
   18893           0 :       empty_method_body(5)
   18894             : 
   18895           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
   18896           0 :       empty_method_body(6)
   18897             : 
   18898           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18899           0 :       empty_method_body(7)
   18900             : 
   18901           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18902           0 :       empty_method_body(8)
   18903             : 
   18904           0 :       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18905           0 :       empty_method_body(9)
   18906             : 
   18907           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&)
   18908           0 :       empty_method_body(10)
   18909             : 
   18910           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&,
   18911             :                                    const T&)
   18912           0 :       empty_method_body(11)
   18913             : 
   18914           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&,
   18915             :                                    const T&, const T&)
   18916           0 :       empty_method_body(12)
   18917             : 
   18918           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&,
   18919             :                                    const T&, const T&, const T&)
   18920           0 :       empty_method_body(13)
   18921             : 
   18922           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&,
   18923             :                                    const T&, const T&, const T&, const T&)
   18924           0 :       empty_method_body(14)
   18925             : 
   18926           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&,
   18927             :                                    const T&, const T&, const T&, const T&, const T&)
   18928           0 :       empty_method_body(15)
   18929             : 
   18930           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&,
   18931             :                                    const T&, const T&, const T&, const T&, const T&, const T&)
   18932           0 :       empty_method_body(16)
   18933             : 
   18934           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&,
   18935             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18936           0 :       empty_method_body(17)
   18937             : 
   18938           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&,
   18939             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18940           0 :       empty_method_body(18)
   18941             : 
   18942           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&,
   18943             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18944           0 :       empty_method_body(19)
   18945             : 
   18946           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&,
   18947             :                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
   18948           0 :       empty_method_body(20)
   18949             : 
   18950             :       #undef empty_method_body
   18951             : 
   18952             :       std::size_t param_count;
   18953             :    };
   18954             : 
   18955             :    template <typename T>
   18956             :    class ivararg_function : public function_traits
   18957             :    {
   18958             :    public:
   18959             : 
   18960           2 :       virtual ~ivararg_function()
   18961           2 :       {}
   18962             : 
   18963           0 :       inline virtual T operator() (const std::vector<T>&)
   18964             :       {
   18965             :          exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n"));
   18966           0 :          return std::numeric_limits<T>::quiet_NaN();
   18967             :       }
   18968             :    };
   18969             : 
   18970             :    template <typename T>
   18971             :    class igeneric_function : public function_traits
   18972             :    {
   18973             :    public:
   18974             : 
   18975             :       enum return_type
   18976             :       {
   18977             :          e_rtrn_scalar   = 0,
   18978             :          e_rtrn_string   = 1,
   18979             :          e_rtrn_overload = 2
   18980             :       };
   18981             : 
   18982             :       typedef T type;
   18983             :       typedef type_store<T> generic_type;
   18984             :       typedef typename generic_type::parameter_list parameter_list_t;
   18985             : 
   18986         939 :       explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
   18987         939 :       : parameter_sequence(param_seq)
   18988         939 :       , rtrn_type(rtr_type)
   18989         939 :       {}
   18990             : 
   18991         939 :       virtual ~igeneric_function()
   18992         939 :       {}
   18993             : 
   18994             :       #define igeneric_function_empty_body(N)        \
   18995             :       {                                              \
   18996             :          exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \
   18997             :          return std::numeric_limits<T>::quiet_NaN(); \
   18998             :       }                                              \
   18999             : 
   19000             :       // f(i_0,i_1,....,i_N) --> Scalar
   19001           0 :       inline virtual T operator() (parameter_list_t)
   19002           0 :       igeneric_function_empty_body(1)
   19003             : 
   19004             :       // f(i_0,i_1,....,i_N) --> String
   19005           0 :       inline virtual T operator() (std::string&, parameter_list_t)
   19006           0 :       igeneric_function_empty_body(2)
   19007             : 
   19008             :       // f(psi,i_0,i_1,....,i_N) --> Scalar
   19009           0 :       inline virtual T operator() (const std::size_t&, parameter_list_t)
   19010           0 :       igeneric_function_empty_body(3)
   19011             : 
   19012             :       // f(psi,i_0,i_1,....,i_N) --> String
   19013           0 :       inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
   19014           0 :       igeneric_function_empty_body(4)
   19015             : 
   19016             :       #undef igeneric_function_empty_body
   19017             : 
   19018             :       std::string parameter_sequence;
   19019             :       return_type rtrn_type;
   19020             :    };
   19021             : 
   19022             :    #ifndef exprtk_disable_string_capabilities
   19023             :    template <typename T>
   19024             :    class stringvar_base
   19025             :    {
   19026             :    public:
   19027             : 
   19028             :       typedef typename details::stringvar_node<T> stringvar_node_t;
   19029             : 
   19030             :       stringvar_base(const std::string& name, stringvar_node_t* svn)
   19031             :       : name_(name)
   19032             :       , string_varnode_(svn)
   19033             :       {}
   19034             : 
   19035             :       bool valid() const
   19036             :       {
   19037             :          return !name_.empty() && (0 != string_varnode_);
   19038             :       }
   19039             : 
   19040             :       std::string name() const
   19041             :       {
   19042             :          assert(string_varnode_);
   19043             :          return name_;
   19044             :       }
   19045             : 
   19046             :       void rebase(std::string& s)
   19047             :       {
   19048             :          assert(string_varnode_);
   19049             :          string_varnode_->rebase(s);
   19050             :       }
   19051             : 
   19052             :    private:
   19053             : 
   19054             :       std::string name_;
   19055             :       stringvar_node_t* string_varnode_;
   19056             :    };
   19057             :    #endif
   19058             : 
   19059             :    template <typename T> class parser;
   19060             :    template <typename T> class expression_helper;
   19061             : 
   19062             :    template <typename T>
   19063             :    class symbol_table
   19064             :    {
   19065             :    public:
   19066             : 
   19067             :      enum symtab_mutability_type
   19068             :      {
   19069             :        e_unknown   = 0,
   19070             :        e_mutable   = 1,
   19071             :        e_immutable = 2
   19072             :      };
   19073             : 
   19074             :      typedef T (*ff00_functor)();
   19075             :      typedef T (*ff01_functor)(T);
   19076             :      typedef T (*ff02_functor)(T, T);
   19077             :      typedef T (*ff03_functor)(T, T, T);
   19078             :      typedef T (*ff04_functor)(T, T, T, T);
   19079             :      typedef T (*ff05_functor)(T, T, T, T, T);
   19080             :      typedef T (*ff06_functor)(T, T, T, T, T, T);
   19081             :      typedef T (*ff07_functor)(T, T, T, T, T, T, T);
   19082             :      typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
   19083             :      typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
   19084             :      typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
   19085             :      typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
   19086             :      typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
   19087             :      typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
   19088             :      typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
   19089             :      typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
   19090             : 
   19091             :    protected:
   19092             : 
   19093             :        struct freefunc00 exprtk_final : public exprtk::ifunction<T>
   19094             :        {
   19095             :           using exprtk::ifunction<T>::operator();
   19096             : 
   19097             :           explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
   19098             :           inline T operator() () exprtk_override
   19099             :           { return f(); }
   19100             :           ff00_functor f;
   19101             :        };
   19102             : 
   19103             :       struct freefunc01 exprtk_final : public exprtk::ifunction<T>
   19104             :       {
   19105             :          using exprtk::ifunction<T>::operator();
   19106             : 
   19107         102 :          explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
   19108           0 :          inline T operator() (const T& v0) exprtk_override
   19109           0 :          { return f(v0); }
   19110             :          ff01_functor f;
   19111             :       };
   19112             : 
   19113             :       struct freefunc02 exprtk_final : public exprtk::ifunction<T>
   19114             :       {
   19115             :          using exprtk::ifunction<T>::operator();
   19116             : 
   19117         102 :          explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
   19118           0 :          inline T operator() (const T& v0, const T& v1) exprtk_override
   19119           0 :          { return f(v0, v1); }
   19120             :          ff02_functor f;
   19121             :       };
   19122             : 
   19123             :       struct freefunc03 exprtk_final : public exprtk::ifunction<T>
   19124             :       {
   19125             :          using exprtk::ifunction<T>::operator();
   19126             : 
   19127         102 :          explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
   19128           0 :          inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override
   19129           0 :          { return f(v0, v1, v2); }
   19130             :          ff03_functor f;
   19131             :       };
   19132             : 
   19133             :       struct freefunc04 exprtk_final : public exprtk::ifunction<T>
   19134             :       {
   19135             :          using exprtk::ifunction<T>::operator();
   19136             : 
   19137         102 :          explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
   19138           0 :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override
   19139           0 :          { return f(v0, v1, v2, v3); }
   19140             :          ff04_functor f;
   19141             :       };
   19142             : 
   19143             :       struct freefunc05 : public exprtk::ifunction<T>
   19144             :       {
   19145             :          using exprtk::ifunction<T>::operator();
   19146             : 
   19147         102 :          explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
   19148           0 :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override
   19149           0 :          { return f(v0, v1, v2, v3, v4); }
   19150             :          ff05_functor f;
   19151             :       };
   19152             : 
   19153             :       struct freefunc06 exprtk_final : public exprtk::ifunction<T>
   19154             :       {
   19155             :          using exprtk::ifunction<T>::operator();
   19156             : 
   19157         102 :          explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
   19158           0 :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override
   19159           0 :          { return f(v0, v1, v2, v3, v4, v5); }
   19160             :          ff06_functor f;
   19161             :       };
   19162             : 
   19163             :       struct freefunc07 exprtk_final : public exprtk::ifunction<T>
   19164             :       {
   19165             :          using exprtk::ifunction<T>::operator();
   19166             : 
   19167             :          explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
   19168             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19169             :                               const T& v5, const T& v6) exprtk_override
   19170             :          { return f(v0, v1, v2, v3, v4, v5, v6); }
   19171             :          ff07_functor f;
   19172             :       };
   19173             : 
   19174             :       struct freefunc08 exprtk_final : public exprtk::ifunction<T>
   19175             :       {
   19176             :          using exprtk::ifunction<T>::operator();
   19177             : 
   19178             :          explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
   19179             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19180             :                               const T& v5, const T& v6, const T& v7) exprtk_override
   19181             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
   19182             :          ff08_functor f;
   19183             :       };
   19184             : 
   19185             :       struct freefunc09 exprtk_final : public exprtk::ifunction<T>
   19186             :       {
   19187             :          using exprtk::ifunction<T>::operator();
   19188             : 
   19189             :          explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
   19190             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19191             :                               const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override
   19192             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
   19193             :          ff09_functor f;
   19194             :       };
   19195             : 
   19196             :       struct freefunc10 exprtk_final : public exprtk::ifunction<T>
   19197             :       {
   19198             :          using exprtk::ifunction<T>::operator();
   19199             : 
   19200             :          explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
   19201             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19202             :                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override
   19203             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
   19204             :          ff10_functor f;
   19205             :       };
   19206             : 
   19207             :       struct freefunc11 exprtk_final : public exprtk::ifunction<T>
   19208             :       {
   19209             :          using exprtk::ifunction<T>::operator();
   19210             : 
   19211             :          explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
   19212             :          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
   19213             :                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override
   19214             :          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
   19215             :          ff11_functor f;
   19216             :       };
   19217             : 
   19218             :       struct freefunc12 exprtk_final : public exprtk::ifunction<T>
   19219             :       {
   19220             :          using exprtk::ifunction<T>::operator();
   19221             : 
   19222             :          explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
   19223             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19224             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19225             :                               const T& v10, const T& v11) exprtk_override
   19226             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
   19227             :          ff12_functor f;
   19228             :       };
   19229             : 
   19230             :       struct freefunc13 exprtk_final : public exprtk::ifunction<T>
   19231             :       {
   19232             :          using exprtk::ifunction<T>::operator();
   19233             : 
   19234             :          explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
   19235             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19236             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19237             :                               const T& v10, const T& v11, const T& v12) exprtk_override
   19238             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
   19239             :          ff13_functor f;
   19240             :       };
   19241             : 
   19242             :       struct freefunc14 exprtk_final : public exprtk::ifunction<T>
   19243             :       {
   19244             :          using exprtk::ifunction<T>::operator();
   19245             : 
   19246             :          explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
   19247             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19248             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19249             :                               const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override
   19250             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
   19251             :          ff14_functor f;
   19252             :       };
   19253             : 
   19254             :       struct freefunc15 exprtk_final : public exprtk::ifunction<T>
   19255             :       {
   19256             :          using exprtk::ifunction<T>::operator();
   19257             : 
   19258             :          explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
   19259             :          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
   19260             :                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
   19261             :                               const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override
   19262             :          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
   19263             :          ff15_functor f;
   19264             :       };
   19265             : 
   19266             :       template <typename Type, typename RawType>
   19267             :       struct type_store
   19268             :       {
   19269             :          typedef details::expression_node<T>*        expression_ptr;
   19270             :          typedef typename details::variable_node<T>  variable_node_t;
   19271             :          typedef ifunction<T>                        ifunction_t;
   19272             :          typedef ivararg_function<T>                 ivararg_function_t;
   19273             :          typedef igeneric_function<T>                igeneric_function_t;
   19274             :          typedef details::vector_holder<T>           vector_t;
   19275             :          #ifndef exprtk_disable_string_capabilities
   19276             :          typedef typename details::stringvar_node<T> stringvar_node_t;
   19277             :          #endif
   19278             : 
   19279             :          typedef Type type_t;
   19280             :          typedef type_t* type_ptr;
   19281             :          typedef std::pair<bool,type_ptr> type_pair_t;
   19282             :          typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
   19283             :          typedef typename type_map_t::iterator tm_itr_t;
   19284             :          typedef typename type_map_t::const_iterator tm_const_itr_t;
   19285             : 
   19286             :          enum { lut_size = 256 };
   19287             : 
   19288             :          type_map_t  map;
   19289             :          std::size_t size;
   19290             : 
   19291      668704 :          type_store()
   19292      668704 :          : size(0)
   19293      668704 :          {}
   19294             : 
   19295             :          struct deleter
   19296             :          {
   19297             :             #define exprtk_define_process(Type)                  \
   19298             :             static inline void process(std::pair<bool,Type*>& n) \
   19299             :             {                                                    \
   19300             :                delete n.second;                                  \
   19301             :             }                                                    \
   19302             : 
   19303      443757 :             exprtk_define_process(variable_node_t )
   19304        6422 :             exprtk_define_process(vector_t        )
   19305             :             #ifndef exprtk_disable_string_capabilities
   19306      122310 :             exprtk_define_process(stringvar_node_t)
   19307             :             #endif
   19308             : 
   19309             :             #undef exprtk_define_process
   19310             : 
   19311             :             template <typename DeleteType>
   19312      143012 :             static inline void process(std::pair<bool,DeleteType*>&)
   19313      143012 :             {}
   19314             :          };
   19315             : 
   19316     3857681 :          inline bool symbol_exists(const std::string& symbol_name) const
   19317             :          {
   19318     3857681 :             if (symbol_name.empty())
   19319           0 :                return false;
   19320     3857681 :             else if (map.end() != map.find(symbol_name))
   19321      205027 :                return true;
   19322             :             else
   19323     3652654 :                return false;
   19324             :          }
   19325             : 
   19326             :          template <typename PtrType>
   19327           4 :          inline std::string entity_name(const PtrType& ptr) const
   19328             :          {
   19329           4 :             if (map.empty())
   19330           0 :                return std::string();
   19331             : 
   19332           4 :             tm_const_itr_t itr = map.begin();
   19333             : 
   19334           7 :             while (map.end() != itr)
   19335             :             {
   19336           7 :                if (itr->second.second == ptr)
   19337             :                {
   19338           4 :                   return itr->first;
   19339             :                }
   19340             :                else
   19341           3 :                   ++itr;
   19342             :             }
   19343             : 
   19344           0 :             return std::string();
   19345             :          }
   19346             : 
   19347     1955774 :          inline bool is_constant(const std::string& symbol_name) const
   19348             :          {
   19349     1955774 :             if (symbol_name.empty())
   19350           0 :                return false;
   19351             :             else
   19352             :             {
   19353     1955774 :                const tm_const_itr_t itr = map.find(symbol_name);
   19354             : 
   19355     1955774 :                if (map.end() == itr)
   19356      102929 :                   return false;
   19357             :                else
   19358     1852845 :                   return (*itr).second.first;
   19359             :             }
   19360             :          }
   19361             : 
   19362             :          template <typename Tie, typename RType>
   19363        6422 :          inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
   19364             :          {
   19365        6422 :             if (symbol_name.size() > 1)
   19366             :             {
   19367      204160 :                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
   19368             :                {
   19369      201840 :                   if (details::imatch(symbol_name, details::reserved_symbols[i]))
   19370             :                   {
   19371           0 :                      return false;
   19372             :                   }
   19373             :                }
   19374             :             }
   19375             : 
   19376        6422 :             const tm_itr_t itr = map.find(symbol_name);
   19377             : 
   19378        6422 :             if (map.end() == itr)
   19379             :             {
   19380        6422 :                map[symbol_name] = Tie::make(t,is_const);
   19381        6422 :                ++size;
   19382             :             }
   19383             : 
   19384        6422 :             return true;
   19385             :          }
   19386             : 
   19387             :          struct tie_array
   19388             :          {
   19389        2143 :             static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
   19390             :             {
   19391        2143 :                return std::make_pair(is_const, new vector_t(v.first, v.second));
   19392             :             }
   19393             :          };
   19394             : 
   19395             :          struct tie_stdvec
   19396             :          {
   19397             :             template <typename Allocator>
   19398          84 :             static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
   19399             :             {
   19400          84 :                return std::make_pair(is_const, new vector_t(v));
   19401             :             }
   19402             :          };
   19403             : 
   19404             :          struct tie_vecview
   19405             :          {
   19406        4195 :             static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
   19407             :             {
   19408        4195 :                return std::make_pair(is_const, new vector_t(v));
   19409             :             }
   19410             :          };
   19411             : 
   19412             :          struct tie_stddeq
   19413             :          {
   19414             :             template <typename Allocator>
   19415             :             static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
   19416             :             {
   19417             :                return std::make_pair(is_const, new vector_t(v));
   19418             :             }
   19419             :          };
   19420             : 
   19421             :          template <std::size_t v_size>
   19422        2143 :          inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
   19423             :          {
   19424             :             return add_impl<tie_array,std::pair<T*,std::size_t> >
   19425        2143 :                       (symbol_name, std::make_pair(v,v_size), is_const);
   19426             :          }
   19427             : 
   19428           0 :          inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
   19429             :          {
   19430             :             return add_impl<tie_array,std::pair<T*,std::size_t> >
   19431           0 :                      (symbol_name, std::make_pair(v,v_size), is_const);
   19432             :          }
   19433             : 
   19434             :          template <typename Allocator>
   19435          84 :          inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
   19436             :          {
   19437             :             return add_impl<tie_stdvec,std::vector<T,Allocator>&>
   19438          84 :                       (symbol_name, v, is_const);
   19439             :          }
   19440             : 
   19441        4195 :          inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
   19442             :          {
   19443             :             return add_impl<tie_vecview,exprtk::vector_view<T>&>
   19444        4195 :                       (symbol_name, v, is_const);
   19445             :          }
   19446             : 
   19447             :          template <typename Allocator>
   19448             :          inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
   19449             :          {
   19450             :             return add_impl<tie_stddeq,std::deque<T,Allocator>&>
   19451             :                       (symbol_name, v, is_const);
   19452             :          }
   19453             : 
   19454      710083 :          inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false)
   19455             :          {
   19456             :             struct tie
   19457             :             {
   19458      443757 :                static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false)
   19459             :                {
   19460      443757 :                   return std::make_pair(is_constant, new variable_node_t(t));
   19461             :                }
   19462             : 
   19463             :                #ifndef exprtk_disable_string_capabilities
   19464      122310 :                static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false)
   19465             :                {
   19466      122310 :                   return std::make_pair(is_constant, new stringvar_node_t(t));
   19467             :                }
   19468             :                #endif
   19469             : 
   19470      143011 :                static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
   19471             :                {
   19472      143011 :                   return std::make_pair(is_constant,&t);
   19473             :                }
   19474             : 
   19475           2 :                static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
   19476             :                {
   19477           2 :                   return std::make_pair(is_constant,&t);
   19478             :                }
   19479             : 
   19480        1003 :                static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
   19481             :                {
   19482        1003 :                   return std::make_pair(is_constant,&t);
   19483             :                }
   19484             :             };
   19485             : 
   19486      710083 :             const tm_itr_t itr = map.find(symbol_name);
   19487             : 
   19488      710083 :             if (map.end() == itr)
   19489             :             {
   19490      710083 :                map[symbol_name] = tie::make(t_,is_const);
   19491      710083 :                ++size;
   19492             :             }
   19493             : 
   19494      710083 :             return true;
   19495             :          }
   19496             : 
   19497    14417963 :          inline type_ptr get(const std::string& symbol_name) const
   19498             :          {
   19499    14417963 :             const tm_const_itr_t itr = map.find(symbol_name);
   19500             : 
   19501    14417963 :             if (map.end() == itr)
   19502      493391 :                return reinterpret_cast<type_ptr>(0);
   19503             :             else
   19504    13924572 :                return itr->second.second;
   19505             :          }
   19506             : 
   19507             :          template <typename TType, typename TRawType, typename PtrType>
   19508             :          struct ptr_match
   19509             :          {
   19510             :             static inline bool test(const PtrType, const void*)
   19511             :             {
   19512             :                return false;
   19513             :             }
   19514             :          };
   19515             : 
   19516             :          template <typename TType, typename TRawType>
   19517             :          struct ptr_match<TType,TRawType,variable_node_t*>
   19518             :          {
   19519         960 :             static inline bool test(const variable_node_t* p, const void* ptr)
   19520             :             {
   19521             :                exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr));
   19522         960 :                return (&(p->ref()) == ptr);
   19523             :             }
   19524             :          };
   19525             : 
   19526         320 :          inline type_ptr get_from_varptr(const void* ptr) const
   19527             :          {
   19528         320 :             tm_const_itr_t itr = map.begin();
   19529             : 
   19530        1280 :             while (map.end() != itr)
   19531             :             {
   19532         960 :                type_ptr ret_ptr = itr->second.second;
   19533             : 
   19534         960 :                if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
   19535             :                {
   19536           0 :                   return ret_ptr;
   19537             :                }
   19538             : 
   19539         960 :                ++itr;
   19540             :             }
   19541             : 
   19542         320 :             return type_ptr(0);
   19543             :          }
   19544             : 
   19545         422 :          inline bool remove(const std::string& symbol_name, const bool delete_node = true)
   19546             :          {
   19547         422 :             const tm_itr_t itr = map.find(symbol_name);
   19548             : 
   19549         422 :             if (map.end() != itr)
   19550             :             {
   19551         411 :                if (delete_node)
   19552             :                {
   19553         411 :                   deleter::process((*itr).second);
   19554             :                }
   19555             : 
   19556         411 :                map.erase(itr);
   19557         411 :                --size;
   19558             : 
   19559         411 :                return true;
   19560             :             }
   19561             :             else
   19562          11 :                return false;
   19563             :          }
   19564             : 
   19565             :          inline RawType& type_ref(const std::string& symbol_name)
   19566             :          {
   19567             :             struct init_type
   19568             :             {
   19569             :                static inline double set(double)           { return (0.0);           }
   19570             :                static inline double set(long double)      { return (0.0);           }
   19571             :                static inline float  set(float)            { return (0.0f);          }
   19572             :                static inline std::string set(std::string) { return std::string(""); }
   19573             :             };
   19574             : 
   19575             :             static RawType null_type = init_type::set(RawType());
   19576             : 
   19577             :             const tm_const_itr_t itr = map.find(symbol_name);
   19578             : 
   19579             :             if (map.end() == itr)
   19580             :                return null_type;
   19581             :             else
   19582             :                return itr->second.second->ref();
   19583             :          }
   19584             : 
   19585      749124 :          inline void clear(const bool delete_node = true)
   19586             :          {
   19587      749124 :             if (!map.empty())
   19588             :             {
   19589      171852 :                if (delete_node)
   19590             :                {
   19591      171852 :                   tm_itr_t itr = map.begin();
   19592      171852 :                   tm_itr_t end = map.end  ();
   19593             : 
   19594      886942 :                   while (end != itr)
   19595             :                   {
   19596      715090 :                      deleter::process((*itr).second);
   19597      715090 :                      ++itr;
   19598             :                   }
   19599             :                }
   19600             : 
   19601      171852 :                map.clear();
   19602             :             }
   19603             : 
   19604      749124 :             size = 0;
   19605      749124 :          }
   19606             : 
   19607             :          template <typename Allocator,
   19608             :                    template <typename, typename> class Sequence>
   19609          20 :          inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
   19610             :          {
   19611          20 :             std::size_t count = 0;
   19612             : 
   19613          20 :             if (!map.empty())
   19614             :             {
   19615          20 :                tm_const_itr_t itr = map.begin();
   19616          20 :                tm_const_itr_t end = map.end  ();
   19617             : 
   19618         100 :                while (end != itr)
   19619             :                {
   19620          80 :                   list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
   19621          80 :                   ++itr;
   19622          80 :                   ++count;
   19623             :                }
   19624             :             }
   19625             : 
   19626          20 :             return count;
   19627             :          }
   19628             : 
   19629             :          template <typename Allocator,
   19630             :                    template <typename, typename> class Sequence>
   19631        3655 :          inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
   19632             :          {
   19633        3655 :             std::size_t count = 0;
   19634             : 
   19635        3655 :             if (!map.empty())
   19636             :             {
   19637         641 :                tm_const_itr_t itr = map.begin();
   19638         641 :                tm_const_itr_t end = map.end  ();
   19639             : 
   19640        2899 :                while (end != itr)
   19641             :                {
   19642        2258 :                   vlist.push_back((*itr).first);
   19643        2258 :                   ++itr;
   19644        2258 :                   ++count;
   19645             :                }
   19646             :             }
   19647             : 
   19648        3655 :             return count;
   19649             :          }
   19650             :       };
   19651             : 
   19652             :       typedef details::expression_node<T>*        expression_ptr;
   19653             :       typedef typename details::variable_node<T>  variable_t;
   19654             :       typedef typename details::vector_holder<T>  vector_holder_t;
   19655             :       typedef variable_t*                         variable_ptr;
   19656             :       #ifndef exprtk_disable_string_capabilities
   19657             :       typedef typename details::stringvar_node<T> stringvar_t;
   19658             :       typedef stringvar_t*                        stringvar_ptr;
   19659             :       #endif
   19660             :       typedef ifunction        <T>                function_t;
   19661             :       typedef ivararg_function <T>                vararg_function_t;
   19662             :       typedef igeneric_function<T>                generic_function_t;
   19663             :       typedef function_t*                         function_ptr;
   19664             :       typedef vararg_function_t*                  vararg_function_ptr;
   19665             :       typedef generic_function_t*                 generic_function_ptr;
   19666             : 
   19667             :       static const std::size_t lut_size = 256;
   19668             : 
   19669             :       // Symbol Table Holder
   19670             :       struct control_block
   19671             :       {
   19672             :          struct st_data
   19673             :          {
   19674             :             type_store<variable_t        , T                 > variable_store;
   19675             :             type_store<function_t        , function_t        > function_store;
   19676             :             type_store<vararg_function_t , vararg_function_t > vararg_function_store;
   19677             :             type_store<generic_function_t, generic_function_t> generic_function_store;
   19678             :             type_store<generic_function_t, generic_function_t> string_function_store;
   19679             :             type_store<generic_function_t, generic_function_t> overload_function_store;
   19680             :             type_store<vector_holder_t   , vector_holder_t   > vector_store;
   19681             :             #ifndef exprtk_disable_string_capabilities
   19682             :             type_store<stringvar_t       , std::string       > stringvar_store;
   19683             :             #endif
   19684             : 
   19685       83588 :             st_data()
   19686       83588 :             {
   19687     2674816 :                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
   19688             :                {
   19689     2591228 :                   reserved_symbol_table_.insert(details::reserved_words[i]);
   19690             :                }
   19691             : 
   19692     7355744 :                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
   19693             :                {
   19694     7272156 :                   reserved_symbol_table_.insert(details::reserved_symbols[i]);
   19695             :                }
   19696       83588 :             }
   19697             : 
   19698       83588 :            ~st_data()
   19699             :             {
   19700       84200 :                for (std::size_t i = 0; i < free_function_list_.size(); ++i)
   19701             :                {
   19702         612 :                   delete free_function_list_[i];
   19703             :                }
   19704       83588 :             }
   19705             : 
   19706    17642876 :             inline bool is_reserved_symbol(const std::string& symbol) const
   19707             :             {
   19708    17642876 :                return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
   19709             :             }
   19710             : 
   19711       83588 :             static inline st_data* create()
   19712             :             {
   19713       83588 :                return (new st_data);
   19714             :             }
   19715             : 
   19716       83588 :             static inline void destroy(st_data*& sd)
   19717             :             {
   19718       83588 :                delete sd;
   19719       83588 :                sd = reinterpret_cast<st_data*>(0);
   19720       83588 :             }
   19721             : 
   19722             :             std::list<T>               local_symbol_list_;
   19723             :             std::list<std::string>     local_stringvar_list_;
   19724             :             std::set<std::string>      reserved_symbol_table_;
   19725             :             std::vector<ifunction<T>*> free_function_list_;
   19726             :          };
   19727             : 
   19728       83588 :          control_block()
   19729       83588 :          : ref_count(1)
   19730       83588 :          , data_(st_data::create())
   19731       83588 :          , mutability_(e_mutable)
   19732       83588 :          {}
   19733             : 
   19734             :          explicit control_block(st_data* data)
   19735             :          : ref_count(1)
   19736             :          , data_(data)
   19737             :          , mutability_(e_mutable)
   19738             :          {}
   19739             : 
   19740       83588 :         ~control_block()
   19741             :          {
   19742       83588 :             if (data_ && (0 == ref_count))
   19743             :             {
   19744       83588 :                st_data::destroy(data_);
   19745             :             }
   19746       83588 :          }
   19747             : 
   19748       83588 :          static inline control_block* create()
   19749             :          {
   19750       83588 :             return (new control_block);
   19751             :          }
   19752             : 
   19753             :          template <typename SymTab>
   19754     1072373 :          static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
   19755             :          {
   19756     1072373 :             if (cntrl_blck)
   19757             :             {
   19758     1072373 :                if (
   19759     2144746 :                     (0 !=   cntrl_blck->ref_count) &&
   19760     1072373 :                     (0 == --cntrl_blck->ref_count)
   19761             :                   )
   19762             :                {
   19763       83588 :                   if (sym_tab)
   19764       83587 :                      sym_tab->clear();
   19765             : 
   19766       83588 :                   delete cntrl_blck;
   19767             :                }
   19768             : 
   19769     1072373 :                cntrl_blck = 0;
   19770             :             }
   19771     1072373 :          }
   19772             : 
   19773       83588 :          void set_mutability(const symtab_mutability_type mutability)
   19774             :          {
   19775       83588 :             mutability_ = mutability;
   19776       83588 :          }
   19777             : 
   19778             :          std::size_t ref_count;
   19779             :          st_data* data_;
   19780             :          symtab_mutability_type mutability_;
   19781             :       };
   19782             : 
   19783             :    public:
   19784             : 
   19785       83588 :       explicit symbol_table(const symtab_mutability_type mutability = e_mutable)
   19786       83588 :       : control_block_(control_block::create())
   19787             :       {
   19788       83588 :          control_block_->set_mutability(mutability);
   19789       83588 :          clear();
   19790       83588 :       }
   19791             : 
   19792     1072371 :      ~symbol_table()
   19793             :       {
   19794     1072371 :          exprtk::details::dump_ptr("~symbol_table", this);
   19795     1072371 :          control_block::destroy(control_block_, this);
   19796     1072371 :       }
   19797             : 
   19798      988783 :       symbol_table(const symbol_table<T>& st)
   19799             :       {
   19800      988783 :          control_block_ = st.control_block_;
   19801      988783 :          control_block_->ref_count++;
   19802      988783 :       }
   19803             : 
   19804           2 :       inline symbol_table<T>& operator=(const symbol_table<T>& st)
   19805             :       {
   19806           2 :          if (this != &st)
   19807             :          {
   19808           2 :             control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
   19809             : 
   19810           2 :             control_block_ = st.control_block_;
   19811           2 :             control_block_->ref_count++;
   19812             :          }
   19813             : 
   19814           2 :          return (*this);
   19815             :       }
   19816             : 
   19817           2 :       inline bool operator==(const symbol_table<T>& st) const
   19818             :       {
   19819           2 :          return (this == &st) || (control_block_ == st.control_block_);
   19820             :       }
   19821             : 
   19822     1813627 :       inline symtab_mutability_type mutability() const
   19823             :       {
   19824     1813627 :          return valid() ? control_block_->mutability_ : e_unknown;
   19825             :       }
   19826             : 
   19827      187281 :       inline void clear_variables(const bool delete_node = true)
   19828             :       {
   19829      187281 :          local_data().variable_store.clear(delete_node);
   19830      187281 :       }
   19831             : 
   19832      187281 :       inline void clear_functions()
   19833             :       {
   19834      187281 :          local_data().function_store.clear();
   19835      187281 :       }
   19836             : 
   19837      187281 :       inline void clear_strings()
   19838             :       {
   19839             :          #ifndef exprtk_disable_string_capabilities
   19840      187281 :          local_data().stringvar_store.clear();
   19841             :          #endif
   19842      187281 :       }
   19843             : 
   19844      187281 :       inline void clear_vectors()
   19845             :       {
   19846      187281 :          local_data().vector_store.clear();
   19847      187281 :       }
   19848             : 
   19849      187281 :       inline void clear_local_constants()
   19850             :       {
   19851      187281 :          local_data().local_symbol_list_.clear();
   19852      187281 :       }
   19853             : 
   19854      187281 :       inline void clear()
   19855             :       {
   19856      187281 :          if (!valid()) return;
   19857      187281 :          clear_variables      ();
   19858      187281 :          clear_functions      ();
   19859      187281 :          clear_strings        ();
   19860      187281 :          clear_vectors        ();
   19861      187281 :          clear_local_constants();
   19862             :       }
   19863             : 
   19864         600 :       inline std::size_t variable_count() const
   19865             :       {
   19866         600 :          if (valid())
   19867         600 :             return local_data().variable_store.size;
   19868             :          else
   19869           0 :             return 0;
   19870             :       }
   19871             : 
   19872             :       #ifndef exprtk_disable_string_capabilities
   19873          10 :       inline std::size_t stringvar_count() const
   19874             :       {
   19875          10 :          if (valid())
   19876          10 :             return local_data().stringvar_store.size;
   19877             :          else
   19878           0 :             return 0;
   19879             :       }
   19880             :       #endif
   19881             : 
   19882             :       inline std::size_t function_count() const
   19883             :       {
   19884             :          if (valid())
   19885             :             return local_data().function_store.size;
   19886             :          else
   19887             :             return 0;
   19888             :       }
   19889             : 
   19890             :       inline std::size_t vector_count() const
   19891             :       {
   19892             :          if (valid())
   19893             :             return local_data().vector_store.size;
   19894             :          else
   19895             :             return 0;
   19896             :       }
   19897             : 
   19898    12000045 :       inline variable_ptr get_variable(const std::string& variable_name) const
   19899             :       {
   19900    12000045 :          if (!valid())
   19901           0 :             return reinterpret_cast<variable_ptr>(0);
   19902    12000045 :          else if (!valid_symbol(variable_name))
   19903           0 :             return reinterpret_cast<variable_ptr>(0);
   19904             :          else
   19905    12000045 :             return local_data().variable_store.get(variable_name);
   19906             :       }
   19907             : 
   19908             :       inline variable_ptr get_variable(const T& var_ref) const
   19909             :       {
   19910             :          if (!valid())
   19911             :             return reinterpret_cast<variable_ptr>(0);
   19912             :          else
   19913             :             return local_data().variable_store.get_from_varptr(
   19914             :                                                   reinterpret_cast<const void*>(&var_ref));
   19915             :       }
   19916             : 
   19917             :       #ifndef exprtk_disable_string_capabilities
   19918          44 :       inline stringvar_ptr get_stringvar(const std::string& string_name) const
   19919             :       {
   19920          44 :          if (!valid())
   19921           0 :             return reinterpret_cast<stringvar_ptr>(0);
   19922          44 :          else if (!valid_symbol(string_name))
   19923           0 :             return reinterpret_cast<stringvar_ptr>(0);
   19924             :          else
   19925          44 :             return local_data().stringvar_store.get(string_name);
   19926             :       }
   19927             : 
   19928             :       inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const
   19929             :       {
   19930             :          static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0));
   19931             :          if (!valid())
   19932             :             return null_stringvar_base;
   19933             :          else if (!valid_symbol(string_name))
   19934             :             return null_stringvar_base;
   19935             : 
   19936             :          stringvar_ptr stringvar = local_data().stringvar_store.get(string_name);
   19937             : 
   19938             :          if (0 == stringvar)
   19939             :          {
   19940             :             return null_stringvar_base;
   19941             :          }
   19942             : 
   19943             :          return stringvar_base<T>(string_name,stringvar);
   19944             :       }
   19945             :       #endif
   19946             : 
   19947        2178 :       inline function_ptr get_function(const std::string& function_name) const
   19948             :       {
   19949        2178 :          if (!valid())
   19950           0 :             return reinterpret_cast<function_ptr>(0);
   19951        2178 :          else if (!valid_symbol(function_name))
   19952           0 :             return reinterpret_cast<function_ptr>(0);
   19953             :          else
   19954        2178 :             return local_data().function_store.get(function_name);
   19955             :       }
   19956             : 
   19957           0 :       inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
   19958             :       {
   19959           0 :          if (!valid())
   19960           0 :             return reinterpret_cast<vararg_function_ptr>(0);
   19961           0 :          else if (!valid_symbol(vararg_function_name))
   19962           0 :             return reinterpret_cast<vararg_function_ptr>(0);
   19963             :          else
   19964           0 :             return local_data().vararg_function_store.get(vararg_function_name);
   19965             :       }
   19966             : 
   19967           0 :       inline generic_function_ptr get_generic_function(const std::string& function_name) const
   19968             :       {
   19969           0 :          if (!valid())
   19970           0 :             return reinterpret_cast<generic_function_ptr>(0);
   19971           0 :          else if (!valid_symbol(function_name))
   19972           0 :             return reinterpret_cast<generic_function_ptr>(0);
   19973             :          else
   19974           0 :             return local_data().generic_function_store.get(function_name);
   19975             :       }
   19976             : 
   19977           0 :       inline generic_function_ptr get_string_function(const std::string& function_name) const
   19978             :       {
   19979           0 :          if (!valid())
   19980           0 :             return reinterpret_cast<generic_function_ptr>(0);
   19981           0 :          else if (!valid_symbol(function_name))
   19982           0 :             return reinterpret_cast<generic_function_ptr>(0);
   19983             :          else
   19984           0 :             return local_data().string_function_store.get(function_name);
   19985             :       }
   19986             : 
   19987           0 :       inline generic_function_ptr get_overload_function(const std::string& function_name) const
   19988             :       {
   19989           0 :          if (!valid())
   19990           0 :             return reinterpret_cast<generic_function_ptr>(0);
   19991           0 :          else if (!valid_symbol(function_name))
   19992           0 :             return reinterpret_cast<generic_function_ptr>(0);
   19993             :          else
   19994           0 :             return local_data().overload_function_store.get(function_name);
   19995             :       }
   19996             : 
   19997             :       typedef vector_holder_t* vector_holder_ptr;
   19998             : 
   19999           4 :       inline vector_holder_ptr get_vector(const std::string& vector_name) const
   20000             :       {
   20001           4 :          if (!valid())
   20002           0 :             return reinterpret_cast<vector_holder_ptr>(0);
   20003           4 :          else if (!valid_symbol(vector_name))
   20004           0 :             return reinterpret_cast<vector_holder_ptr>(0);
   20005             :          else
   20006           4 :             return local_data().vector_store.get(vector_name);
   20007             :       }
   20008             : 
   20009             :       inline T& variable_ref(const std::string& symbol_name)
   20010             :       {
   20011             :          static T null_var = T(0);
   20012             :          if (!valid())
   20013             :             return null_var;
   20014             :          else if (!valid_symbol(symbol_name))
   20015             :             return null_var;
   20016             :          else
   20017             :             return local_data().variable_store.type_ref(symbol_name);
   20018             :       }
   20019             : 
   20020             :       #ifndef exprtk_disable_string_capabilities
   20021             :       inline std::string& stringvar_ref(const std::string& symbol_name)
   20022             :       {
   20023             :          static std::string null_stringvar;
   20024             :          if (!valid())
   20025             :             return null_stringvar;
   20026             :          else if (!valid_symbol(symbol_name))
   20027             :             return null_stringvar;
   20028             :          else
   20029             :             return local_data().stringvar_store.type_ref(symbol_name);
   20030             :       }
   20031             :       #endif
   20032             : 
   20033             :       inline bool is_constant_node(const std::string& symbol_name) const
   20034             :       {
   20035             :          if (!valid())
   20036             :             return false;
   20037             :          else if (!valid_symbol(symbol_name))
   20038             :             return false;
   20039             :          else
   20040             :             return local_data().variable_store.is_constant(symbol_name);
   20041             :       }
   20042             : 
   20043             :       #ifndef exprtk_disable_string_capabilities
   20044             :       inline bool is_constant_string(const std::string& symbol_name) const
   20045             :       {
   20046             :          if (!valid())
   20047             :             return false;
   20048             :          else if (!valid_symbol(symbol_name))
   20049             :             return false;
   20050             :          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
   20051             :             return false;
   20052             :          else
   20053             :             return local_data().stringvar_store.is_constant(symbol_name);
   20054             :       }
   20055             :       #endif
   20056             : 
   20057        2302 :       inline bool create_variable(const std::string& variable_name, const T& value = T(0))
   20058             :       {
   20059        2302 :          if (!valid())
   20060           0 :             return false;
   20061        2302 :          else if (!valid_symbol(variable_name))
   20062           0 :             return false;
   20063        2302 :          else if (symbol_exists(variable_name))
   20064           0 :             return false;
   20065             : 
   20066        2302 :          local_data().local_symbol_list_.push_back(value);
   20067        2302 :          T& t = local_data().local_symbol_list_.back();
   20068             : 
   20069        2302 :          return add_variable(variable_name,t);
   20070             :       }
   20071             : 
   20072             :       #ifndef exprtk_disable_string_capabilities
   20073             :       inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
   20074             :       {
   20075             :          if (!valid())
   20076             :             return false;
   20077             :          else if (!valid_symbol(stringvar_name))
   20078             :             return false;
   20079             :          else if (symbol_exists(stringvar_name))
   20080             :             return false;
   20081             : 
   20082             :          local_data().local_stringvar_list_.push_back(value);
   20083             :          std::string& s = local_data().local_stringvar_list_.back();
   20084             : 
   20085             :          return add_stringvar(stringvar_name,s);
   20086             :       }
   20087             :       #endif
   20088             : 
   20089      443833 :       inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
   20090             :       {
   20091      443833 :          if (!valid())
   20092           0 :             return false;
   20093      443833 :          else if (!valid_symbol(variable_name))
   20094           0 :             return false;
   20095      443833 :          else if (symbol_exists(variable_name))
   20096          76 :             return false;
   20097             :          else
   20098      443757 :             return local_data().variable_store.add(variable_name, t, is_constant);
   20099             :       }
   20100             : 
   20101      101541 :       inline bool add_constant(const std::string& constant_name, const T& value)
   20102             :       {
   20103      101541 :          if (!valid())
   20104           0 :             return false;
   20105      101541 :          else if (!valid_symbol(constant_name))
   20106           0 :             return false;
   20107      101541 :          else if (symbol_exists(constant_name))
   20108           0 :             return false;
   20109             : 
   20110      101541 :          local_data().local_symbol_list_.push_back(value);
   20111      101541 :          T& t = local_data().local_symbol_list_.back();
   20112             : 
   20113      101541 :          return add_variable(constant_name, t, true);
   20114             :       }
   20115             : 
   20116             :       #ifndef exprtk_disable_string_capabilities
   20117      122386 :       inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
   20118             :       {
   20119      122386 :          if (!valid())
   20120           0 :             return false;
   20121      122386 :          else if (!valid_symbol(stringvar_name))
   20122           0 :             return false;
   20123      122386 :          else if (symbol_exists(stringvar_name))
   20124          76 :             return false;
   20125             :          else
   20126      122310 :             return local_data().stringvar_store.add(stringvar_name, s, is_constant);
   20127             :       }
   20128             :       #endif
   20129             : 
   20130      143009 :       inline bool add_function(const std::string& function_name, function_t& function)
   20131             :       {
   20132      143009 :          if (!valid())
   20133           0 :             return false;
   20134      143009 :          else if (!valid_symbol(function_name))
   20135           0 :             return false;
   20136      143009 :          else if (symbol_exists(function_name))
   20137           0 :             return false;
   20138             :          else
   20139      143009 :             return local_data().function_store.add(function_name,function);
   20140             :       }
   20141             : 
   20142           2 :       inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
   20143             :       {
   20144           2 :          if (!valid())
   20145           0 :             return false;
   20146           2 :          else if (!valid_symbol(vararg_function_name))
   20147           0 :             return false;
   20148           2 :          else if (symbol_exists(vararg_function_name))
   20149           0 :             return false;
   20150             :          else
   20151           2 :             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
   20152             :       }
   20153             : 
   20154        1003 :       inline bool add_function(const std::string& function_name, generic_function_t& function)
   20155             :       {
   20156        1003 :          if (!valid())
   20157           0 :             return false;
   20158        1003 :          else if (!valid_symbol(function_name))
   20159           0 :             return false;
   20160        1003 :          else if (symbol_exists(function_name))
   20161           0 :             return false;
   20162             :          else
   20163             :          {
   20164        1003 :             switch (function.rtrn_type)
   20165             :             {
   20166        1000 :                case generic_function_t::e_rtrn_scalar :
   20167        2000 :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20168        2000 :                          local_data().generic_function_store.add(function_name,function) : false;
   20169             : 
   20170           1 :                case generic_function_t::e_rtrn_string :
   20171           2 :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20172           2 :                          local_data().string_function_store.add(function_name,function)  : false;
   20173             : 
   20174           2 :                case generic_function_t::e_rtrn_overload :
   20175           4 :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
   20176           4 :                          local_data().overload_function_store.add(function_name,function) : false;
   20177             :             }
   20178             :          }
   20179             : 
   20180           0 :          return false;
   20181             :       }
   20182             : 
   20183             :       #define exprtk_define_freefunction(NN)                                                \
   20184             :       inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
   20185             :       {                                                                                     \
   20186             :          if (!valid())                                                                      \
   20187             :          { return false; }                                                                  \
   20188             :          if (!valid_symbol(function_name))                                                  \
   20189             :          { return false; }                                                                  \
   20190             :          if (symbol_exists(function_name))                                                  \
   20191             :          { return false; }                                                                  \
   20192             :                                                                                             \
   20193             :          exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                          \
   20194             :                                                                                             \
   20195             :          local_data().free_function_list_.push_back(ifunc);                                 \
   20196             :                                                                                             \
   20197             :          return add_function(function_name,(*local_data().free_function_list_.back()));     \
   20198             :       }                                                                                     \
   20199             : 
   20200         102 :       exprtk_define_freefunction(00) exprtk_define_freefunction(01)
   20201         204 :       exprtk_define_freefunction(02) exprtk_define_freefunction(03)
   20202         204 :       exprtk_define_freefunction(04) exprtk_define_freefunction(05)
   20203         102 :       exprtk_define_freefunction(06) exprtk_define_freefunction(07)
   20204             :       exprtk_define_freefunction(08) exprtk_define_freefunction(09)
   20205             :       exprtk_define_freefunction(10) exprtk_define_freefunction(11)
   20206             :       exprtk_define_freefunction(12) exprtk_define_freefunction(13)
   20207             :       exprtk_define_freefunction(14) exprtk_define_freefunction(15)
   20208             : 
   20209             :       #undef exprtk_define_freefunction
   20210             : 
   20211           2 :       inline bool add_reserved_function(const std::string& function_name, function_t& function)
   20212             :       {
   20213           2 :          if (!valid())
   20214           0 :             return false;
   20215           2 :          else if (!valid_symbol(function_name,false))
   20216           0 :             return false;
   20217           2 :          else if (symbol_exists(function_name,false))
   20218           0 :             return false;
   20219             :          else
   20220           2 :             return local_data().function_store.add(function_name,function);
   20221             :       }
   20222             : 
   20223             :       inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
   20224             :       {
   20225             :          if (!valid())
   20226             :             return false;
   20227             :          else if (!valid_symbol(vararg_function_name,false))
   20228             :             return false;
   20229             :          else if (symbol_exists(vararg_function_name,false))
   20230             :             return false;
   20231             :          else
   20232             :             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
   20233             :       }
   20234             : 
   20235             :       inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
   20236             :       {
   20237             :          if (!valid())
   20238             :             return false;
   20239             :          else if (!valid_symbol(function_name,false))
   20240             :             return false;
   20241             :          else if (symbol_exists(function_name,false))
   20242             :             return false;
   20243             :          else
   20244             :          {
   20245             :             switch (function.rtrn_type)
   20246             :             {
   20247             :                case generic_function_t::e_rtrn_scalar :
   20248             :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20249             :                          local_data().generic_function_store.add(function_name,function) : false;
   20250             : 
   20251             :                case generic_function_t::e_rtrn_string :
   20252             :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
   20253             :                          local_data().string_function_store.add(function_name,function)  : false;
   20254             : 
   20255             :                case generic_function_t::e_rtrn_overload :
   20256             :                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
   20257             :                          local_data().overload_function_store.add(function_name,function) : false;
   20258             :             }
   20259             :          }
   20260             : 
   20261             :          return false;
   20262             :       }
   20263             : 
   20264             :       template <std::size_t N>
   20265        2143 :       inline bool add_vector(const std::string& vector_name, T (&v)[N])
   20266             :       {
   20267        2143 :          if (!valid())
   20268           0 :             return false;
   20269        2143 :          else if (!valid_symbol(vector_name))
   20270           0 :             return false;
   20271        2143 :          else if (symbol_exists(vector_name))
   20272           0 :             return false;
   20273             :          else
   20274        2143 :             return local_data().vector_store.add(vector_name,v);
   20275             :       }
   20276             : 
   20277           0 :       inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
   20278             :       {
   20279           0 :          if (!valid())
   20280           0 :             return false;
   20281           0 :          else if (!valid_symbol(vector_name))
   20282           0 :             return false;
   20283           0 :          else if (symbol_exists(vector_name))
   20284           0 :             return false;
   20285           0 :          else if (0 == v_size)
   20286           0 :             return false;
   20287             :          else
   20288           0 :             return local_data().vector_store.add(vector_name, v, v_size);
   20289             :       }
   20290             : 
   20291             :       template <typename Allocator>
   20292          84 :       inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
   20293             :       {
   20294          84 :          if (!valid())
   20295           0 :             return false;
   20296          84 :          else if (!valid_symbol(vector_name))
   20297           0 :             return false;
   20298          84 :          else if (symbol_exists(vector_name))
   20299           0 :             return false;
   20300          84 :          else if (0 == v.size())
   20301           0 :             return false;
   20302             :          else
   20303          84 :             return local_data().vector_store.add(vector_name,v);
   20304             :       }
   20305             : 
   20306        4195 :       inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
   20307             :       {
   20308        4195 :          if (!valid())
   20309           0 :             return false;
   20310        4195 :          else if (!valid_symbol(vector_name))
   20311           0 :             return false;
   20312        4195 :          else if (symbol_exists(vector_name))
   20313           0 :             return false;
   20314        4195 :          else if (0 == v.size())
   20315           0 :             return false;
   20316             :          else
   20317        4195 :             return local_data().vector_store.add(vector_name,v);
   20318             :       }
   20319             : 
   20320         344 :       inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
   20321             :       {
   20322         344 :          if (!valid())
   20323           0 :             return false;
   20324             :          else
   20325         344 :             return local_data().variable_store.remove(variable_name, delete_node);
   20326             :       }
   20327             : 
   20328             :       #ifndef exprtk_disable_string_capabilities
   20329          43 :       inline bool remove_stringvar(const std::string& string_name)
   20330             :       {
   20331          43 :          if (!valid())
   20332           0 :             return false;
   20333             :          else
   20334          43 :             return local_data().stringvar_store.remove(string_name);
   20335             :       }
   20336             :       #endif
   20337             : 
   20338          29 :       inline bool remove_function(const std::string& function_name)
   20339             :       {
   20340          29 :          if (!valid())
   20341           0 :             return false;
   20342             :          else
   20343          29 :             return local_data().function_store.remove(function_name);
   20344             :       }
   20345             : 
   20346           3 :       inline bool remove_vararg_function(const std::string& vararg_function_name)
   20347             :       {
   20348           3 :          if (!valid())
   20349           0 :             return false;
   20350             :          else
   20351           3 :             return local_data().vararg_function_store.remove(vararg_function_name);
   20352             :       }
   20353             : 
   20354           3 :       inline bool remove_vector(const std::string& vector_name)
   20355             :       {
   20356           3 :          if (!valid())
   20357           0 :             return false;
   20358             :          else
   20359           3 :             return local_data().vector_store.remove(vector_name);
   20360             :       }
   20361             : 
   20362       33080 :       inline bool add_constants()
   20363             :       {
   20364       33080 :          return add_pi      () &&
   20365       66160 :                 add_epsilon () &&
   20366       66160 :                 add_infinity() ;
   20367             :       }
   20368             : 
   20369       33081 :       inline bool add_pi()
   20370             :       {
   20371       33081 :          const typename details::numeric::details::number_type<T>::type num_type;
   20372       33081 :          static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
   20373       66162 :          return add_constant("pi",local_pi);
   20374             :       }
   20375             : 
   20376       33080 :       inline bool add_epsilon()
   20377             :       {
   20378       33080 :          static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
   20379       66160 :          return add_constant("epsilon",local_epsilon);
   20380             :       }
   20381             : 
   20382       33080 :       inline bool add_infinity()
   20383             :       {
   20384             :          static const T local_infinity = std::numeric_limits<T>::infinity();
   20385       66160 :          return add_constant("inf",local_infinity);
   20386             :       }
   20387             : 
   20388             :       template <typename Package>
   20389          62 :       inline bool add_package(Package& package)
   20390             :       {
   20391          62 :          return package.register_package(*this);
   20392             :       }
   20393             : 
   20394             :       template <typename Allocator,
   20395             :                 template <typename, typename> class Sequence>
   20396          10 :       inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
   20397             :       {
   20398          10 :          if (!valid())
   20399           0 :             return 0;
   20400             :          else
   20401          10 :             return local_data().variable_store.get_list(vlist);
   20402             :       }
   20403             : 
   20404             :       template <typename Allocator,
   20405             :                 template <typename, typename> class Sequence>
   20406          10 :       inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
   20407             :       {
   20408          10 :          if (!valid())
   20409           0 :             return 0;
   20410             :          else
   20411          10 :             return local_data().variable_store.get_list(vlist);
   20412             :       }
   20413             : 
   20414             :       #ifndef exprtk_disable_string_capabilities
   20415             :       template <typename Allocator,
   20416             :                 template <typename, typename> class Sequence>
   20417          10 :       inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
   20418             :       {
   20419          10 :          if (!valid())
   20420           0 :             return 0;
   20421             :          else
   20422          10 :             return local_data().stringvar_store.get_list(svlist);
   20423             :       }
   20424             : 
   20425             :       template <typename Allocator,
   20426             :                 template <typename, typename> class Sequence>
   20427          10 :       inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
   20428             :       {
   20429          10 :          if (!valid())
   20430           0 :             return 0;
   20431             :          else
   20432          10 :             return local_data().stringvar_store.get_list(svlist);
   20433             :       }
   20434             :       #endif
   20435             : 
   20436             :       template <typename Allocator,
   20437             :                 template <typename, typename> class Sequence>
   20438             :       inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const
   20439             :       {
   20440             :          if (!valid())
   20441             :             return 0;
   20442             :          else
   20443             :             return local_data().vector_store.get_list(vec_list);
   20444             :       }
   20445             : 
   20446             :       template <typename Allocator,
   20447             :                 template <typename, typename> class Sequence>
   20448             :       inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const
   20449             :       {
   20450             :          if (!valid())
   20451             :             return 0;
   20452             : 
   20453             :          std::vector<std::string> function_names;
   20454             :          std::size_t count = 0;
   20455             : 
   20456             :          count += local_data().function_store         .get_list(function_names);
   20457             :          count += local_data().vararg_function_store  .get_list(function_names);
   20458             :          count += local_data().generic_function_store .get_list(function_names);
   20459             :          count += local_data().string_function_store  .get_list(function_names);
   20460             :          count += local_data().overload_function_store.get_list(function_names);
   20461             : 
   20462             :          std::set<std::string> function_set;
   20463             : 
   20464             :          for (std::size_t i = 0; i < function_names.size(); ++i)
   20465             :          {
   20466             :             function_set.insert(function_names[i]);
   20467             :          }
   20468             : 
   20469             :          std::copy(function_set.begin(),function_set.end(),
   20470             :                    std::back_inserter(function_list));
   20471             : 
   20472             :          return count;
   20473             :       }
   20474             : 
   20475      877577 :       inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
   20476             :       {
   20477             :          /*
   20478             :             Function will return true if symbol_name exists as either a
   20479             :             reserved symbol, variable, stringvar, vector or function name
   20480             :             in any of the type stores.
   20481             :          */
   20482      877577 :          if (!valid())
   20483           0 :             return false;
   20484      877577 :          else if (local_data().variable_store.symbol_exists(symbol_name))
   20485         118 :             return true;
   20486             :          #ifndef exprtk_disable_string_capabilities
   20487      877459 :          else if (local_data().stringvar_store.symbol_exists(symbol_name))
   20488         118 :             return true;
   20489             :          #endif
   20490      877341 :          else if (local_data().vector_store.symbol_exists(symbol_name))
   20491           2 :             return true;
   20492      877339 :          else if (local_data().function_store.symbol_exists(symbol_name))
   20493          20 :             return true;
   20494      877319 :          else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
   20495           0 :             return true;
   20496             :          else
   20497      877319 :             return false;
   20498             :       }
   20499             : 
   20500         727 :       inline bool is_variable(const std::string& variable_name) const
   20501             :       {
   20502         727 :          if (!valid())
   20503           0 :             return false;
   20504             :          else
   20505         727 :             return local_data().variable_store.symbol_exists(variable_name);
   20506             :       }
   20507             : 
   20508             :       #ifndef exprtk_disable_string_capabilities
   20509         727 :       inline bool is_stringvar(const std::string& stringvar_name) const
   20510             :       {
   20511         727 :          if (!valid())
   20512           0 :             return false;
   20513             :          else
   20514         727 :             return local_data().stringvar_store.symbol_exists(stringvar_name);
   20515             :       }
   20516             : 
   20517             :       inline bool is_conststr_stringvar(const std::string& symbol_name) const
   20518             :       {
   20519             :          if (!valid())
   20520             :             return false;
   20521             :          else if (!valid_symbol(symbol_name))
   20522             :             return false;
   20523             :          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
   20524             :             return false;
   20525             : 
   20526             :          return (
   20527             :                   local_data().stringvar_store.symbol_exists(symbol_name) ||
   20528             :                   local_data().stringvar_store.is_constant  (symbol_name)
   20529             :                 );
   20530             :       }
   20531             :       #endif
   20532             : 
   20533         727 :       inline bool is_function(const std::string& function_name) const
   20534             :       {
   20535         727 :          if (!valid())
   20536           0 :             return false;
   20537             :          else
   20538         727 :             return local_data().function_store.symbol_exists(function_name);
   20539             :       }
   20540             : 
   20541         727 :       inline bool is_vararg_function(const std::string& vararg_function_name) const
   20542             :       {
   20543         727 :          if (!valid())
   20544           0 :             return false;
   20545             :          else
   20546         727 :             return local_data().vararg_function_store.symbol_exists(vararg_function_name);
   20547             :       }
   20548             : 
   20549         727 :       inline bool is_vector(const std::string& vector_name) const
   20550             :       {
   20551         727 :          if (!valid())
   20552           0 :             return false;
   20553             :          else
   20554         727 :             return local_data().vector_store.symbol_exists(vector_name);
   20555             :       }
   20556             : 
   20557             :       inline std::string get_variable_name(const expression_ptr& ptr) const
   20558             :       {
   20559             :          return local_data().variable_store.entity_name(ptr);
   20560             :       }
   20561             : 
   20562             :       inline std::string get_vector_name(const vector_holder_ptr& ptr) const
   20563             :       {
   20564             :          return local_data().vector_store.entity_name(ptr);
   20565             :       }
   20566             : 
   20567             :       #ifndef exprtk_disable_string_capabilities
   20568             :       inline std::string get_stringvar_name(const expression_ptr& ptr) const
   20569             :       {
   20570             :          return local_data().stringvar_store.entity_name(ptr);
   20571             :       }
   20572             : 
   20573             :       inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
   20574             :       {
   20575             :          return local_data().stringvar_store.entity_name(ptr);
   20576             :       }
   20577             :       #endif
   20578             : 
   20579    34407899 :       inline bool valid() const
   20580             :       {
   20581             :          // Symbol table sanity check.
   20582    34407899 :          return control_block_ && control_block_->data_;
   20583             :       }
   20584             : 
   20585         727 :       inline void load_from(const symbol_table<T>& st)
   20586             :       {
   20587             :          {
   20588         727 :             std::vector<std::string> name_list;
   20589             : 
   20590         727 :             st.local_data().function_store.get_list(name_list);
   20591             : 
   20592         727 :             if (!name_list.empty())
   20593             :             {
   20594        2799 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   20595             :                {
   20596        2178 :                   exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
   20597        2178 :                   add_function(name_list[i],ifunc);
   20598             :                }
   20599             :             }
   20600         727 :          }
   20601             : 
   20602             :          {
   20603         727 :             std::vector<std::string> name_list;
   20604             : 
   20605         727 :             st.local_data().vararg_function_store.get_list(name_list);
   20606             : 
   20607         727 :             if (!name_list.empty())
   20608             :             {
   20609           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   20610             :                {
   20611           0 :                   exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
   20612           0 :                   add_function(name_list[i],ivafunc);
   20613             :                }
   20614             :             }
   20615         727 :          }
   20616             : 
   20617             :          {
   20618         727 :             std::vector<std::string> name_list;
   20619             : 
   20620         727 :             st.local_data().generic_function_store.get_list(name_list);
   20621             : 
   20622         727 :             if (!name_list.empty())
   20623             :             {
   20624           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   20625             :                {
   20626           0 :                   exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
   20627           0 :                   add_function(name_list[i],ifunc);
   20628             :                }
   20629             :             }
   20630         727 :          }
   20631             : 
   20632             :          {
   20633         727 :             std::vector<std::string> name_list;
   20634             : 
   20635         727 :             st.local_data().string_function_store.get_list(name_list);
   20636             : 
   20637         727 :             if (!name_list.empty())
   20638             :             {
   20639           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   20640             :                {
   20641           0 :                   exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
   20642           0 :                   add_function(name_list[i],ifunc);
   20643             :                }
   20644             :             }
   20645         727 :          }
   20646             : 
   20647             :          {
   20648         727 :             std::vector<std::string> name_list;
   20649             : 
   20650         727 :             st.local_data().overload_function_store.get_list(name_list);
   20651             : 
   20652         727 :             if (!name_list.empty())
   20653             :             {
   20654           0 :                for (std::size_t i = 0; i < name_list.size(); ++i)
   20655             :                {
   20656           0 :                   exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
   20657           0 :                   add_function(name_list[i],ifunc);
   20658             :                }
   20659             :             }
   20660         727 :          }
   20661         727 :       }
   20662             : 
   20663           0 :       inline void load_variables_from(const symbol_table<T>& st)
   20664             :       {
   20665           0 :          std::vector<std::string> name_list;
   20666             : 
   20667           0 :          st.local_data().variable_store.get_list(name_list);
   20668             : 
   20669           0 :          if (!name_list.empty())
   20670             :          {
   20671           0 :             for (std::size_t i = 0; i < name_list.size(); ++i)
   20672             :             {
   20673           0 :                T& variable = st.get_variable(name_list[i])->ref();
   20674           0 :                add_variable(name_list[i], variable);
   20675             :             }
   20676             :          }
   20677           0 :       }
   20678             : 
   20679           0 :       inline void load_vectors_from(const symbol_table<T>& st)
   20680             :       {
   20681           0 :          std::vector<std::string> name_list;
   20682             : 
   20683           0 :          st.local_data().vector_store.get_list(name_list);
   20684             : 
   20685           0 :          if (!name_list.empty())
   20686             :          {
   20687           0 :             for (std::size_t i = 0; i < name_list.size(); ++i)
   20688             :             {
   20689           0 :                vector_holder_t& vecholder = *st.get_vector(name_list[i]);
   20690           0 :                add_vector(name_list[i], vecholder.data(), vecholder.size());
   20691             :             }
   20692             :          }
   20693           0 :       }
   20694             : 
   20695             :    private:
   20696             : 
   20697    16765584 :       inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
   20698             :       {
   20699    16765584 :          if (symbol.empty())
   20700           0 :             return false;
   20701    16765584 :          else if (!details::is_letter(symbol[0]))
   20702          23 :             return false;
   20703    16765561 :          else if (symbol.size() > 1)
   20704             :          {
   20705     3112133 :             for (std::size_t i = 1; i < symbol.size(); ++i)
   20706             :             {
   20707     2236345 :                if (
   20708     2246316 :                     !details::is_letter_or_digit(symbol[i]) &&
   20709        9971 :                     ('_' != symbol[i])
   20710             :                   )
   20711             :                {
   20712         604 :                   if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
   20713         604 :                      continue;
   20714             :                   else
   20715           0 :                      return false;
   20716             :                }
   20717             :             }
   20718             :          }
   20719             : 
   20720    16765561 :          return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
   20721             :       }
   20722             : 
   20723      180418 :       inline bool valid_function(const std::string& symbol) const
   20724             :       {
   20725      180418 :          if (symbol.empty())
   20726           0 :             return false;
   20727      180418 :          else if (!details::is_letter(symbol[0]))
   20728         115 :             return false;
   20729      180303 :          else if (symbol.size() > 1)
   20730             :          {
   20731      629641 :             for (std::size_t i = 1; i < symbol.size(); ++i)
   20732             :             {
   20733      482124 :                if (
   20734      489499 :                     !details::is_letter_or_digit(symbol[i]) &&
   20735        7375 :                     ('_' != symbol[i])
   20736             :                   )
   20737             :                {
   20738        1820 :                   if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
   20739        1820 :                      continue;
   20740             :                   else
   20741           0 :                      return false;
   20742             :                }
   20743             :             }
   20744             :          }
   20745             : 
   20746      180303 :          return true;
   20747             :       }
   20748             : 
   20749             :       typedef typename control_block::st_data local_data_t;
   20750             : 
   20751     1862242 :       inline local_data_t& local_data()
   20752             :       {
   20753     1862242 :          return *(control_block_->data_);
   20754             :       }
   20755             : 
   20756    37878903 :       inline const local_data_t& local_data() const
   20757             :       {
   20758    37878903 :          return *(control_block_->data_);
   20759             :       }
   20760             : 
   20761             :       control_block* control_block_;
   20762             : 
   20763             :       friend class parser<T>;
   20764             :    }; // class symbol_table
   20765             : 
   20766             :    template <typename T>
   20767             :    class function_compositor;
   20768             : 
   20769             :    template <typename T>
   20770             :    class expression
   20771             :    {
   20772             :    private:
   20773             : 
   20774             :       typedef details::expression_node<T>*  expression_ptr;
   20775             :       typedef details::vector_holder<T>*    vector_holder_ptr;
   20776             :       typedef std::vector<symbol_table<T> > symtab_list_t;
   20777             : 
   20778             :       struct control_block
   20779             :       {
   20780             :          enum data_type
   20781             :          {
   20782             :             e_unknown  ,
   20783             :             e_expr     ,
   20784             :             e_vecholder,
   20785             :             e_data     ,
   20786             :             e_vecdata  ,
   20787             :             e_string
   20788             :          };
   20789             : 
   20790             :          struct data_pack
   20791             :          {
   20792             :             data_pack()
   20793             :             : pointer(0)
   20794             :             , type(e_unknown)
   20795             :             , size(0)
   20796             :             {}
   20797             : 
   20798      118765 :             data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
   20799      118765 :             : pointer(ptr)
   20800      118765 :             , type(dt)
   20801      118765 :             , size(sz)
   20802      118765 :             {}
   20803             : 
   20804             :             void*       pointer;
   20805             :             data_type   type;
   20806             :             std::size_t size;
   20807             :          };
   20808             : 
   20809             :          typedef std::vector<data_pack> local_data_list_t;
   20810             :          typedef results_context<T>     results_context_t;
   20811             :          typedef control_block*         cntrl_blck_ptr_t;
   20812             : 
   20813             :          control_block()
   20814             :          : ref_count(0)
   20815             :          , expr     (0)
   20816             :          , results  (0)
   20817             :          , retinv_null(false)
   20818             :          , return_invoked(&retinv_null)
   20819             :          {}
   20820             : 
   20821      685256 :          explicit control_block(expression_ptr e)
   20822      685256 :          : ref_count(1)
   20823      685256 :          , expr     (e)
   20824      685256 :          , results  (0)
   20825      685256 :          , retinv_null(false)
   20826      685256 :          , return_invoked(&retinv_null)
   20827      685256 :          {}
   20828             : 
   20829      685256 :         ~control_block()
   20830             :          {
   20831      685256 :             if (expr && details::branch_deletable(expr))
   20832             :             {
   20833      685011 :                destroy_node(expr);
   20834             :             }
   20835             : 
   20836      685256 :             if (!local_data_list.empty())
   20837             :             {
   20838      150157 :                for (std::size_t i = 0; i < local_data_list.size(); ++i)
   20839             :                {
   20840      118765 :                   switch (local_data_list[i].type)
   20841             :                   {
   20842       45326 :                      case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
   20843       45326 :                                         break;
   20844             : 
   20845       18761 :                      case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
   20846       18761 :                                         break;
   20847             : 
   20848       26432 :                      case e_data      : delete reinterpret_cast<T*>(local_data_list[i].pointer);
   20849       26432 :                                         break;
   20850             : 
   20851       18761 :                      case e_vecdata   : delete [] reinterpret_cast<T*>(local_data_list[i].pointer);
   20852       18761 :                                         break;
   20853             : 
   20854        9485 :                      case e_string    : delete reinterpret_cast<std::string*>(local_data_list[i].pointer);
   20855        9485 :                                         break;
   20856             : 
   20857           0 :                      default          : break;
   20858             :                   }
   20859             :                }
   20860             :             }
   20861             : 
   20862      685256 :             if (results)
   20863             :             {
   20864         111 :                delete results;
   20865             :             }
   20866      685256 :          }
   20867             : 
   20868      685256 :          static inline cntrl_blck_ptr_t create(expression_ptr e)
   20869             :          {
   20870      685256 :             return new control_block(e);
   20871             :          }
   20872             : 
   20873      577748 :          static inline void destroy(cntrl_blck_ptr_t& cntrl_blck)
   20874             :          {
   20875      577748 :             if (cntrl_blck)
   20876             :             {
   20877      569828 :                if (
   20878     1139656 :                     (0 !=   cntrl_blck->ref_count) &&
   20879      569828 :                     (0 == --cntrl_blck->ref_count)
   20880             :                   )
   20881             :                {
   20882      334407 :                   delete cntrl_blck;
   20883             :                }
   20884             : 
   20885      569828 :                cntrl_blck = 0;
   20886             :             }
   20887      577748 :          }
   20888             : 
   20889             :          std::size_t ref_count;
   20890             :          expression_ptr expr;
   20891             :          local_data_list_t local_data_list;
   20892             :          results_context_t* results;
   20893             :          bool  retinv_null;
   20894             :          bool* return_invoked;
   20895             : 
   20896             :          friend class function_compositor<T>;
   20897             :       };
   20898             : 
   20899             :    public:
   20900             : 
   20901      335330 :       expression()
   20902      335330 :       : control_block_(0)
   20903             :       {
   20904      335330 :          set_expression(new details::null_node<T>());
   20905      335330 :       }
   20906             : 
   20907      233967 :       expression(const expression<T>& e)
   20908      233967 :       : control_block_    (e.control_block_    )
   20909      233967 :       , symbol_table_list_(e.symbol_table_list_)
   20910             :       {
   20911      233967 :          control_block_->ref_count++;
   20912      233967 :       }
   20913             : 
   20914             :       explicit expression(const symbol_table<T>& symbol_table)
   20915             :       : control_block_(0)
   20916             :       {
   20917             :          set_expression(new details::null_node<T>());
   20918             :          symbol_table_list_.push_back(symbol_table);
   20919             :       }
   20920             : 
   20921        1454 :       inline expression<T>& operator=(const expression<T>& e)
   20922             :       {
   20923        1454 :          if (this != &e)
   20924             :          {
   20925        1454 :             if (control_block_)
   20926             :             {
   20927        1454 :                if (
   20928        2908 :                     (0 !=   control_block_->ref_count) &&
   20929        1454 :                     (0 == --control_block_->ref_count)
   20930             :                   )
   20931             :                {
   20932        1454 :                   delete control_block_;
   20933             :                }
   20934             : 
   20935        1454 :                control_block_ = 0;
   20936             :             }
   20937             : 
   20938        1454 :             control_block_ = e.control_block_;
   20939        1454 :             control_block_->ref_count++;
   20940        1454 :             symbol_table_list_ = e.symbol_table_list_;
   20941             :          }
   20942             : 
   20943        1454 :          return *this;
   20944             :       }
   20945             : 
   20946             :       inline bool operator==(const expression<T>& e) const
   20947             :       {
   20948             :          return (this == &e);
   20949             :       }
   20950             : 
   20951      350426 :       inline bool operator!() const
   20952             :       {
   20953             :          return (
   20954      700352 :                   (0 == control_block_      ) ||
   20955      349926 :                   (0 == control_block_->expr)
   20956      350426 :                 );
   20957             :       }
   20958             : 
   20959        8451 :       inline expression<T>& release()
   20960             :       {
   20961        8451 :          exprtk::details::dump_ptr("expression::release", this);
   20962        8451 :          control_block::destroy(control_block_);
   20963             : 
   20964        8451 :          return (*this);
   20965             :       }
   20966             : 
   20967      569297 :      ~expression()
   20968             :       {
   20969      569297 :          control_block::destroy(control_block_);
   20970      569297 :       }
   20971             : 
   20972   196273010 :       inline T value() const
   20973             :       {
   20974   196273010 :          assert(control_block_      );
   20975   196273010 :          assert(control_block_->expr);
   20976             : 
   20977   196273010 :          return control_block_->expr->value();
   20978             :       }
   20979             : 
   20980             :       inline T operator() () const
   20981             :       {
   20982             :          return value();
   20983             :       }
   20984             : 
   20985             :       inline operator T() const
   20986             :       {
   20987             :          return value();
   20988             :       }
   20989             : 
   20990             :       inline operator bool() const
   20991             :       {
   20992             :          return details::is_true(value());
   20993             :       }
   20994             : 
   20995      354640 :       inline void register_symbol_table(symbol_table<T>& st)
   20996             :       {
   20997   200346173 :          for (std::size_t i = 0; i < symbol_table_list_.size(); ++i)
   20998             :          {
   20999   199991533 :             if (&st == &symbol_table_list_[i])
   21000             :             {
   21001           0 :                return;
   21002             :             }
   21003             :          }
   21004             : 
   21005      354640 :          symbol_table_list_.push_back(st);
   21006             :       }
   21007             : 
   21008    36000003 :       inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
   21009             :       {
   21010    12000001 :          return symbol_table_list_[index];
   21011             :       }
   21012             : 
   21013             :       inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
   21014             :       {
   21015             :          return symbol_table_list_[index];
   21016             :       }
   21017             : 
   21018             :       typedef results_context<T> results_context_t;
   21019             : 
   21020          45 :       inline const results_context_t& results() const
   21021             :       {
   21022          45 :          if (control_block_->results)
   21023          45 :             return (*control_block_->results);
   21024             :          else
   21025             :          {
   21026           0 :             static const results_context_t null_results;
   21027           0 :             return null_results;
   21028             :          }
   21029             :       }
   21030             : 
   21031          30 :       inline bool return_invoked() const
   21032             :       {
   21033          30 :          return (*control_block_->return_invoked);
   21034             :       }
   21035             : 
   21036             :    private:
   21037             : 
   21038      360925 :       inline symtab_list_t get_symbol_table_list() const
   21039             :       {
   21040      360925 :          return symbol_table_list_;
   21041             :       }
   21042             : 
   21043      685256 :       inline void set_expression(const expression_ptr expr)
   21044             :       {
   21045      685256 :          if (expr)
   21046             :          {
   21047      685256 :             if (control_block_)
   21048             :             {
   21049      349395 :                if (0 == --control_block_->ref_count)
   21050             :                {
   21051      349395 :                   delete control_block_;
   21052             :                }
   21053             :             }
   21054             : 
   21055      685256 :             control_block_ = control_block::create(expr);
   21056             :          }
   21057      685256 :       }
   21058             : 
   21059       45326 :       inline void register_local_var(expression_ptr expr)
   21060             :       {
   21061       45326 :          if (expr)
   21062             :          {
   21063       45326 :             if (control_block_)
   21064             :             {
   21065       45326 :                control_block_->
   21066       45326 :                   local_data_list.push_back(
   21067             :                      typename expression<T>::control_block::
   21068       90652 :                         data_pack(reinterpret_cast<void*>(expr),
   21069             :                                   control_block::e_expr));
   21070             :             }
   21071             :          }
   21072       45326 :       }
   21073             : 
   21074       18761 :       inline void register_local_var(vector_holder_ptr vec_holder)
   21075             :       {
   21076       18761 :          if (vec_holder)
   21077             :          {
   21078       18761 :             if (control_block_)
   21079             :             {
   21080       18761 :                control_block_->
   21081       18761 :                   local_data_list.push_back(
   21082             :                      typename expression<T>::control_block::
   21083       37522 :                         data_pack(reinterpret_cast<void*>(vec_holder),
   21084             :                                   control_block::e_vecholder));
   21085             :             }
   21086             :          }
   21087       18761 :       }
   21088             : 
   21089       54678 :       inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
   21090             :       {
   21091       54678 :          if (data)
   21092             :          {
   21093       54678 :             if (control_block_)
   21094             :             {
   21095       54678 :                typename control_block::data_type dt = control_block::e_data;
   21096             : 
   21097       54678 :                switch (data_mode)
   21098             :                {
   21099       26432 :                   case 0 : dt = control_block::e_data;    break;
   21100       18761 :                   case 1 : dt = control_block::e_vecdata; break;
   21101        9485 :                   case 2 : dt = control_block::e_string;  break;
   21102             :                }
   21103             : 
   21104       54678 :                control_block_->
   21105       54678 :                   local_data_list.push_back(
   21106             :                      typename expression<T>::control_block::
   21107      109356 :                         data_pack(reinterpret_cast<void*>(data), dt, size));
   21108             :             }
   21109             :          }
   21110       54678 :       }
   21111             : 
   21112         727 :       inline const typename control_block::local_data_list_t& local_data_list()
   21113             :       {
   21114         727 :          if (control_block_)
   21115             :          {
   21116         727 :             return control_block_->local_data_list;
   21117             :          }
   21118             :          else
   21119             :          {
   21120           0 :             static typename control_block::local_data_list_t null_local_data_list;
   21121           0 :             return null_local_data_list;
   21122             :          }
   21123             :       }
   21124             : 
   21125      349926 :       inline void register_return_results(results_context_t* rc)
   21126             :       {
   21127      349926 :          if (control_block_ && rc)
   21128             :          {
   21129         111 :             control_block_->results = rc;
   21130             :          }
   21131      349926 :       }
   21132             : 
   21133      349926 :       inline void set_retinvk(bool* retinvk_ptr)
   21134             :       {
   21135      349926 :          if (control_block_)
   21136             :          {
   21137      349926 :             control_block_->return_invoked = retinvk_ptr;
   21138             :          }
   21139      349926 :       }
   21140             : 
   21141             :       control_block* control_block_;
   21142             :       symtab_list_t  symbol_table_list_;
   21143             : 
   21144             :       friend class parser<T>;
   21145             :       friend class expression_helper<T>;
   21146             :       friend class function_compositor<T>;
   21147             :       template <typename TT>
   21148             :       friend bool is_valid(const expression<TT>& expr);
   21149             :    }; // class expression
   21150             : 
   21151             :    template <typename T>
   21152             :    class expression_helper
   21153             :    {
   21154             :    public:
   21155             : 
   21156       10747 :       static inline bool is_constant(const expression<T>& expr)
   21157             :       {
   21158       10747 :          return expr.control_block_ && details::is_constant_node(expr.control_block_->expr);
   21159             :       }
   21160             : 
   21161             :       static inline bool is_variable(const expression<T>& expr)
   21162             :       {
   21163             :          return expr.control_block_ && details::is_variable_node(expr.control_block_->expr);
   21164             :       }
   21165             : 
   21166             :       static inline bool is_unary(const expression<T>& expr)
   21167             :       {
   21168             :          return expr.control_block_ && details::is_unary_node(expr.control_block_->expr);
   21169             :       }
   21170             : 
   21171             :       static inline bool is_binary(const expression<T>& expr)
   21172             :       {
   21173             :          return expr.control_block_ && details::is_binary_node(expr.control_block_->expr);
   21174             :       }
   21175             : 
   21176             :       static inline bool is_function(const expression<T>& expr)
   21177             :       {
   21178             :          return expr.control_block_ && details::is_function(expr.control_block_->expr);
   21179             :       }
   21180             : 
   21181             :       static inline bool is_null(const expression<T>& expr)
   21182             :       {
   21183             :          return expr.control_block_ && details::is_null_node(expr.control_block_->expr);
   21184             :       }
   21185             :    };
   21186             : 
   21187             :    template <typename T>
   21188             :    inline bool is_valid(const expression<T>& expr)
   21189             :    {
   21190             :       return expr.control_block_ && !expression_helper<T>::is_null(expr);
   21191             :    }
   21192             : 
   21193             :    namespace parser_error
   21194             :    {
   21195             :       enum error_mode
   21196             :       {
   21197             :          e_unknown   = 0,
   21198             :          e_syntax    = 1,
   21199             :          e_token     = 2,
   21200             :          e_numeric   = 4,
   21201             :          e_symtab    = 5,
   21202             :          e_lexer     = 6,
   21203             :          e_synthesis = 7,
   21204             :          e_helper    = 8,
   21205             :          e_parser    = 9
   21206             :       };
   21207             : 
   21208             :       struct type
   21209             :       {
   21210       43680 :          type()
   21211       87360 :          : mode(parser_error::e_unknown)
   21212       43680 :          , line_no  (0)
   21213       43680 :          , column_no(0)
   21214       43680 :          {}
   21215             : 
   21216             :          lexer::token token;
   21217             :          error_mode mode;
   21218             :          std::string diagnostic;
   21219             :          std::string src_location;
   21220             :          std::string error_line;
   21221             :          std::size_t line_no;
   21222             :          std::size_t column_no;
   21223             :       };
   21224             : 
   21225           1 :       inline type make_error(const error_mode mode,
   21226             :                              const std::string& diagnostic   = "",
   21227             :                              const std::string& src_location = "")
   21228             :       {
   21229           1 :          type t;
   21230           1 :          t.mode         = mode;
   21231           1 :          t.token.type   = lexer::token::e_error;
   21232           1 :          t.diagnostic   = diagnostic;
   21233           1 :          t.src_location = src_location;
   21234             :          exprtk_debug(("%s\n", diagnostic .c_str()));
   21235           1 :          return t;
   21236           0 :       }
   21237             : 
   21238       43679 :       inline type make_error(const error_mode mode,
   21239             :                              const lexer::token& tk,
   21240             :                              const std::string& diagnostic   = "",
   21241             :                              const std::string& src_location = "")
   21242             :       {
   21243       43679 :          type t;
   21244       43679 :          t.mode         = mode;
   21245       43679 :          t.token        = tk;
   21246       43679 :          t.diagnostic   = diagnostic;
   21247       43679 :          t.src_location = src_location;
   21248             :          exprtk_debug(("%s\n", diagnostic .c_str()));
   21249       43679 :          return t;
   21250           0 :       }
   21251             : 
   21252           0 :       inline std::string to_str(error_mode mode)
   21253             :       {
   21254           0 :          switch (mode)
   21255             :          {
   21256           0 :             case e_unknown : return std::string("Unknown Error");
   21257           0 :             case e_syntax  : return std::string("Syntax Error" );
   21258           0 :             case e_token   : return std::string("Token Error"  );
   21259           0 :             case e_numeric : return std::string("Numeric Error");
   21260           0 :             case e_symtab  : return std::string("Symbol Error" );
   21261           0 :             case e_lexer   : return std::string("Lexer Error"  );
   21262           0 :             case e_helper  : return std::string("Helper Error" );
   21263           0 :             case e_parser  : return std::string("Parser Error" );
   21264           0 :             default        : return std::string("Unknown Error");
   21265             :          }
   21266             :       }
   21267             : 
   21268           0 :       inline bool update_error(type& error, const std::string& expression)
   21269             :       {
   21270           0 :          if (
   21271           0 :               expression.empty()                         ||
   21272           0 :               (error.token.position > expression.size()) ||
   21273           0 :               (std::numeric_limits<std::size_t>::max() == error.token.position)
   21274             :             )
   21275             :          {
   21276           0 :             return false;
   21277             :          }
   21278             : 
   21279           0 :          std::size_t error_line_start = 0;
   21280             : 
   21281           0 :          for (std::size_t i = error.token.position; i > 0; --i)
   21282             :          {
   21283           0 :             const details::char_t c = expression[i];
   21284             : 
   21285           0 :             if (('\n' == c) || ('\r' == c))
   21286             :             {
   21287           0 :                error_line_start = i + 1;
   21288           0 :                break;
   21289             :             }
   21290             :          }
   21291             : 
   21292           0 :          std::size_t next_nl_position = std::min(expression.size(),
   21293           0 :                                                  expression.find_first_of('\n',error.token.position + 1));
   21294             : 
   21295           0 :          error.column_no  = error.token.position - error_line_start;
   21296           0 :          error.error_line = expression.substr(error_line_start,
   21297           0 :                                               next_nl_position - error_line_start);
   21298             : 
   21299           0 :          error.line_no = 0;
   21300             : 
   21301           0 :          for (std::size_t i = 0; i < next_nl_position; ++i)
   21302             :          {
   21303           0 :             if ('\n' == expression[i])
   21304           0 :                ++error.line_no;
   21305             :          }
   21306             : 
   21307           0 :          return true;
   21308             :       }
   21309             : 
   21310             :       inline void dump_error(const type& error)
   21311             :       {
   21312             :          printf("Position: %02d   Type: [%s]   Msg: %s\n",
   21313             :                 static_cast<int>(error.token.position),
   21314             :                 exprtk::parser_error::to_str(error.mode).c_str(),
   21315             :                 error.diagnostic.c_str());
   21316             :       }
   21317             :    }
   21318             : 
   21319             :    namespace details
   21320             :    {
   21321             :       template <typename Parser>
   21322           4 :       inline void disable_type_checking(Parser& p)
   21323             :       {
   21324           4 :          p.state_.type_check_enabled = false;
   21325           4 :       }
   21326             :    }
   21327             : 
   21328             :    template <typename T>
   21329             :    class parser : public lexer::parser_helper
   21330             :    {
   21331             :    private:
   21332             : 
   21333             :       enum precedence_level
   21334             :       {
   21335             :          e_level00, e_level01, e_level02, e_level03, e_level04,
   21336             :          e_level05, e_level06, e_level07, e_level08, e_level09,
   21337             :          e_level10, e_level11, e_level12, e_level13, e_level14
   21338             :       };
   21339             : 
   21340             :       typedef const T&                                       cref_t;
   21341             :       typedef const T                                        const_t;
   21342             :       typedef ifunction<T>                                   F;
   21343             :       typedef ivararg_function<T>                            VAF;
   21344             :       typedef igeneric_function<T>                           GF;
   21345             :       typedef ifunction<T>                                   ifunction_t;
   21346             :       typedef ivararg_function<T>                            ivararg_function_t;
   21347             :       typedef igeneric_function<T>                           igeneric_function_t;
   21348             :       typedef details::expression_node<T>                    expression_node_t;
   21349             :       typedef details::literal_node<T>                       literal_node_t;
   21350             :       typedef details::unary_node<T>                         unary_node_t;
   21351             :       typedef details::binary_node<T>                        binary_node_t;
   21352             :       typedef details::trinary_node<T>                       trinary_node_t;
   21353             :       typedef details::quaternary_node<T>                    quaternary_node_t;
   21354             :       typedef details::conditional_node<T>                   conditional_node_t;
   21355             :       typedef details::cons_conditional_node<T>              cons_conditional_node_t;
   21356             :       typedef details::while_loop_node<T>                    while_loop_node_t;
   21357             :       typedef details::repeat_until_loop_node<T>             repeat_until_loop_node_t;
   21358             :       typedef details::for_loop_node<T>                      for_loop_node_t;
   21359             :       typedef details::while_loop_rtc_node<T>                while_loop_rtc_node_t;
   21360             :       typedef details::repeat_until_loop_rtc_node<T>         repeat_until_loop_rtc_node_t;
   21361             :       typedef details::for_loop_rtc_node<T>                  for_loop_rtc_node_t;
   21362             :       #ifndef exprtk_disable_break_continue
   21363             :       typedef details::while_loop_bc_node<T>                 while_loop_bc_node_t;
   21364             :       typedef details::repeat_until_loop_bc_node<T>          repeat_until_loop_bc_node_t;
   21365             :       typedef details::for_loop_bc_node<T>                   for_loop_bc_node_t;
   21366             :       typedef details::while_loop_bc_rtc_node<T>             while_loop_bc_rtc_node_t;
   21367             :       typedef details::repeat_until_loop_bc_rtc_node<T>      repeat_until_loop_bc_rtc_node_t;
   21368             :       typedef details::for_loop_bc_rtc_node<T>               for_loop_bc_rtc_node_t;
   21369             :       #endif
   21370             :       typedef details::switch_node<T>                        switch_node_t;
   21371             :       typedef details::variable_node<T>                      variable_node_t;
   21372             :       typedef details::vector_elem_node<T>                   vector_elem_node_t;
   21373             :       typedef details::vector_celem_node<T>                  vector_celem_node_t;
   21374             :       typedef details::vector_elem_rtc_node<T>               vector_elem_rtc_node_t;
   21375             :       typedef details::vector_celem_rtc_node<T>              vector_celem_rtc_node_t;
   21376             :       typedef details::rebasevector_elem_node<T>             rebasevector_elem_node_t;
   21377             :       typedef details::rebasevector_celem_node<T>            rebasevector_celem_node_t;
   21378             :       typedef details::rebasevector_elem_rtc_node<T>         rebasevector_elem_rtc_node_t;
   21379             :       typedef details::rebasevector_celem_rtc_node<T>        rebasevector_celem_rtc_node_t;
   21380             :       typedef details::vector_node<T>                        vector_node_t;
   21381             :       typedef details::vector_size_node<T>                   vector_size_node_t;
   21382             :       typedef details::range_pack<T>                         range_t;
   21383             :       #ifndef exprtk_disable_string_capabilities
   21384             :       typedef details::stringvar_node<T>                     stringvar_node_t;
   21385             :       typedef details::string_literal_node<T>                string_literal_node_t;
   21386             :       typedef details::string_range_node<T>                  string_range_node_t;
   21387             :       typedef details::const_string_range_node<T>            const_string_range_node_t;
   21388             :       typedef details::generic_string_range_node<T>          generic_string_range_node_t;
   21389             :       typedef details::string_concat_node<T>                 string_concat_node_t;
   21390             :       typedef details::assignment_string_node<T>             assignment_string_node_t;
   21391             :       typedef details::assignment_string_range_node<T>       assignment_string_range_node_t;
   21392             :       typedef details::conditional_string_node<T>            conditional_string_node_t;
   21393             :       typedef details::cons_conditional_str_node<T>          cons_conditional_str_node_t;
   21394             :       #endif
   21395             :       typedef details::assignment_node<T>                    assignment_node_t;
   21396             :       typedef details::assignment_vec_elem_node<T>           assignment_vec_elem_node_t;
   21397             :       typedef details::assignment_vec_elem_rtc_node<T>       assignment_vec_elem_rtc_node_t;
   21398             :       typedef details::assignment_rebasevec_elem_node<T>     assignment_rebasevec_elem_node_t;
   21399             :       typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t;
   21400             :       typedef details::assignment_rebasevec_celem_node<T>    assignment_rebasevec_celem_node_t;
   21401             :       typedef details::assignment_vec_node<T>                assignment_vec_node_t;
   21402             :       typedef details::assignment_vecvec_node<T>             assignment_vecvec_node_t;
   21403             :       typedef details::conditional_vector_node<T>            conditional_vector_node_t;
   21404             :       typedef details::scand_node<T>                         scand_node_t;
   21405             :       typedef details::scor_node<T>                          scor_node_t;
   21406             :       typedef lexer::token                                   token_t;
   21407             :       typedef expression_node_t*                             expression_node_ptr;
   21408             :       typedef expression<T>                                  expression_t;
   21409             :       typedef symbol_table<T>                                symbol_table_t;
   21410             :       typedef typename expression<T>::symtab_list_t          symbol_table_list_t;
   21411             :       typedef details::vector_holder<T>                      vector_holder_t;
   21412             :       typedef vector_holder_t*                               vector_holder_ptr;
   21413             : 
   21414             :       typedef typename details::functor_t<T> functor_t;
   21415             :       typedef typename functor_t::qfunc_t    quaternary_functor_t;
   21416             :       typedef typename functor_t::tfunc_t    trinary_functor_t;
   21417             :       typedef typename functor_t::bfunc_t    binary_functor_t;
   21418             :       typedef typename functor_t::ufunc_t    unary_functor_t;
   21419             : 
   21420             :       typedef details::operator_type operator_t;
   21421             : 
   21422             :       typedef std::map<operator_t, unary_functor_t  > unary_op_map_t;
   21423             :       typedef std::map<operator_t, binary_functor_t > binary_op_map_t;
   21424             :       typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t;
   21425             : 
   21426             :       typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
   21427             :       typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
   21428             : 
   21429             :       typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
   21430             :       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
   21431             :       typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
   21432             : 
   21433             :       typedef details::T0oT1_define<T, cref_t , cref_t > vov_t;
   21434             :       typedef details::T0oT1_define<T, const_t, cref_t > cov_t;
   21435             :       typedef details::T0oT1_define<T, cref_t , const_t> voc_t;
   21436             : 
   21437             :       typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t;
   21438             :       typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t;
   21439             :       typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t;
   21440             :       typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t;
   21441             :       typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t;
   21442             :       typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t;
   21443             :       typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t;
   21444             : 
   21445             :       typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t;
   21446             :       typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t;
   21447             :       typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t;
   21448             :       typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t;
   21449             :       typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t;
   21450             : 
   21451             :       typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t;
   21452             :       typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t;
   21453             :       typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t;
   21454             :       typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t;
   21455             : 
   21456             :       typedef results_context<T> results_context_t;
   21457             : 
   21458             :       typedef parser_helper prsrhlpr_t;
   21459             : 
   21460             :       struct scope_element
   21461             :       {
   21462             :          enum element_type
   21463             :          {
   21464             :             e_none    ,
   21465             :             e_variable,
   21466             :             e_vector  ,
   21467             :             e_vecelem ,
   21468             :             e_string
   21469             :          };
   21470             : 
   21471             :          typedef details::vector_holder<T> vector_holder_t;
   21472             :          typedef variable_node_t*          variable_node_ptr;
   21473             :          typedef vector_holder_t*          vector_holder_ptr;
   21474             :          typedef expression_node_t*        expression_node_ptr;
   21475             :          #ifndef exprtk_disable_string_capabilities
   21476             :          typedef stringvar_node_t*         stringvar_node_ptr;
   21477             :          #endif
   21478             : 
   21479      170725 :          scope_element()
   21480      341450 :          : name("???")
   21481      170725 :          , size (std::numeric_limits<std::size_t>::max())
   21482      170725 :          , index(std::numeric_limits<std::size_t>::max())
   21483      170725 :          , depth(std::numeric_limits<std::size_t>::max())
   21484      170725 :          , ref_count(0)
   21485      170725 :          , ip_index (0)
   21486      170725 :          , type     (e_none)
   21487      170725 :          , active   (false)
   21488      170725 :          , data     (0)
   21489      170725 :          , var_node (0)
   21490      170725 :          , vec_node (0)
   21491             :          #ifndef exprtk_disable_string_capabilities
   21492      170725 :          , str_node(0)
   21493             :          #endif
   21494      170725 :          {}
   21495             : 
   21496      126577 :          bool operator < (const scope_element& se) const
   21497             :          {
   21498      126577 :             if (ip_index < se.ip_index)
   21499           2 :                return true;
   21500      126575 :             else if (ip_index > se.ip_index)
   21501        7040 :                return false;
   21502      119535 :             else if (depth < se.depth)
   21503         899 :                return true;
   21504      118636 :             else if (depth > se.depth)
   21505        6568 :                return false;
   21506      112068 :             else if (index < se.index)
   21507       12785 :                return true;
   21508       99283 :             else if (index > se.index)
   21509       32686 :                return false;
   21510             :             else
   21511       66597 :                return (name < se.name);
   21512             :          }
   21513             : 
   21514       27869 :          void clear()
   21515             :          {
   21516       27869 :             name   = "???";
   21517       27869 :             size   = std::numeric_limits<std::size_t>::max();
   21518       27869 :             index  = std::numeric_limits<std::size_t>::max();
   21519       27869 :             depth  = std::numeric_limits<std::size_t>::max();
   21520       27869 :             type   = e_none;
   21521       27869 :             active = false;
   21522       27869 :             ref_count = 0;
   21523       27869 :             ip_index  = 0;
   21524       27869 :             data      = 0;
   21525       27869 :             var_node  = 0;
   21526       27869 :             vec_node  = 0;
   21527             :             #ifndef exprtk_disable_string_capabilities
   21528       27869 :             str_node  = 0;
   21529             :             #endif
   21530       27869 :          }
   21531             : 
   21532             :          std::string  name;
   21533             :          std::size_t  size;
   21534             :          std::size_t  index;
   21535             :          std::size_t  depth;
   21536             :          std::size_t  ref_count;
   21537             :          std::size_t  ip_index;
   21538             :          element_type type;
   21539             :          bool         active;
   21540             :          void*        data;
   21541             :          expression_node_ptr var_node;
   21542             :          vector_holder_ptr   vec_node;
   21543             :          #ifndef exprtk_disable_string_capabilities
   21544             :          stringvar_node_ptr str_node;
   21545             :          #endif
   21546             :       };
   21547             : 
   21548             :       class scope_element_manager
   21549             :       {
   21550             :       public:
   21551             : 
   21552             :          typedef expression_node_t* expression_node_ptr;
   21553             :          typedef variable_node_t*   variable_node_ptr;
   21554             :          typedef parser<T>          parser_t;
   21555             : 
   21556      106542 :          explicit scope_element_manager(parser<T>& p)
   21557      106542 :          : parser_(p)
   21558      106542 :          , input_param_cnt_(0)
   21559      106542 :          {}
   21560             : 
   21561      414013 :          inline std::size_t size() const
   21562             :          {
   21563      414013 :             return element_.size();
   21564             :          }
   21565             : 
   21566      229884 :          inline bool empty() const
   21567             :          {
   21568      229884 :             return element_.empty();
   21569             :          }
   21570             : 
   21571       64087 :          inline scope_element& get_element(const std::size_t& index)
   21572             :          {
   21573       64087 :             if (index < element_.size())
   21574       64087 :                return element_[index];
   21575             :             else
   21576           0 :                return null_element_;
   21577             :          }
   21578             : 
   21579      124214 :          inline scope_element& get_element(const std::string& var_name,
   21580             :                                            const std::size_t index = std::numeric_limits<std::size_t>::max())
   21581             :          {
   21582      124214 :             const std::size_t current_depth = parser_.state_.scope_depth;
   21583             : 
   21584      218489 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21585             :             {
   21586      101457 :                scope_element& se = element_[i];
   21587             : 
   21588      101457 :                if (se.depth > current_depth)
   21589        1484 :                   continue;
   21590       99973 :                else if (
   21591      123296 :                          details::imatch(se.name, var_name) &&
   21592       23323 :                          (se.index == index)
   21593             :                        )
   21594        7182 :                   return se;
   21595             :             }
   21596             : 
   21597      117032 :             return null_element_;
   21598             :          }
   21599             : 
   21600      214932 :          inline scope_element& get_active_element(const std::string& var_name,
   21601             :                                                   const std::size_t index = std::numeric_limits<std::size_t>::max())
   21602             :          {
   21603      214932 :             const std::size_t current_depth = parser_.state_.scope_depth;
   21604             : 
   21605      343661 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21606             :             {
   21607      278887 :                scope_element& se = element_[i];
   21608             : 
   21609      278887 :                if (se.depth > current_depth)
   21610          38 :                   continue;
   21611      278849 :                else if (
   21612      278849 :                          details::imatch(se.name, var_name) &&
   21613      429247 :                          (se.index == index)                &&
   21614      150398 :                          (se.active)
   21615             :                        )
   21616      150158 :                   return se;
   21617             :             }
   21618             : 
   21619       64774 :             return null_element_;
   21620             :          }
   21621             : 
   21622       64183 :          inline bool add_element(const scope_element& se)
   21623             :          {
   21624      124309 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21625             :             {
   21626       60126 :                scope_element& cse = element_[i];
   21627             : 
   21628       60126 :                if (
   21629       60126 :                     details::imatch(cse.name, se.name) &&
   21630       17799 :                     (cse.depth <= se.depth)            &&
   21631       16879 :                     (cse.index == se.index)            &&
   21632        1120 :                     (cse.size  == se.size )            &&
   21633       78085 :                     (cse.type  == se.type )            &&
   21634         160 :                     (cse.active)
   21635             :                   )
   21636           0 :                   return false;
   21637             :             }
   21638             : 
   21639       64183 :             element_.push_back(se);
   21640       64183 :             std::sort(element_.begin(),element_.end());
   21641             : 
   21642       64183 :             return true;
   21643             :          }
   21644             : 
   21645       20264 :          inline void deactivate(const std::size_t& scope_depth)
   21646             :          {
   21647             :             exprtk_debug(("deactivate() - Scope depth: %d\n",
   21648             :                           static_cast<int>(parser_.state_.scope_depth)));
   21649             : 
   21650       59314 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21651             :             {
   21652       39050 :                scope_element& se = element_[i];
   21653             : 
   21654       39050 :                if (se.active && (se.depth >= scope_depth))
   21655             :                {
   21656             :                   exprtk_debug(("deactivate() - element[%02d] '%s'\n",
   21657             :                                 static_cast<int>(i),
   21658             :                                 se.name.c_str()));
   21659             : 
   21660       16292 :                   se.active = false;
   21661             :                }
   21662             :             }
   21663       20264 :          }
   21664             : 
   21665       27869 :          inline void free_element(scope_element& se)
   21666             :          {
   21667             :             exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
   21668             : 
   21669       27869 :             switch (se.type)
   21670             :             {
   21671       11893 :                case scope_element::e_variable   : delete reinterpret_cast<T*>(se.data);
   21672       11893 :                                                   delete se.var_node;
   21673       11893 :                                                   break;
   21674             : 
   21675       11245 :                case scope_element::e_vector     : delete[] reinterpret_cast<T*>(se.data);
   21676       11245 :                                                   delete se.vec_node;
   21677       11245 :                                                   break;
   21678             : 
   21679        4176 :                case scope_element::e_vecelem    : delete se.var_node;
   21680        4176 :                                                   break;
   21681             : 
   21682             :                #ifndef exprtk_disable_string_capabilities
   21683         555 :                case scope_element::e_string     : delete reinterpret_cast<std::string*>(se.data);
   21684         555 :                                                   delete se.str_node;
   21685         555 :                                                   break;
   21686             :                #endif
   21687             : 
   21688           0 :                default                          : return;
   21689             :             }
   21690             : 
   21691       27869 :             se.clear();
   21692             :          }
   21693             : 
   21694      382452 :          inline void cleanup()
   21695             :          {
   21696      410321 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21697             :             {
   21698       27869 :                free_element(element_[i]);
   21699             :             }
   21700             : 
   21701      382452 :             element_.clear();
   21702             : 
   21703      382452 :             input_param_cnt_ = 0;
   21704      382452 :          }
   21705             : 
   21706        2140 :          inline std::size_t next_ip_index()
   21707             :          {
   21708        2140 :             return ++input_param_cnt_;
   21709             :          }
   21710             : 
   21711         320 :          inline expression_node_ptr get_variable(const T& v)
   21712             :          {
   21713         480 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21714             :             {
   21715         480 :                scope_element& se = element_[i];
   21716             : 
   21717         480 :                if (
   21718         960 :                     se.active   &&
   21719         960 :                     se.var_node &&
   21720         480 :                     details::is_variable_node(se.var_node)
   21721             :                   )
   21722             :                {
   21723         480 :                   variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
   21724             : 
   21725         480 :                   if (&(vn->ref()) == (&v))
   21726             :                   {
   21727         320 :                      return se.var_node;
   21728             :                   }
   21729             :                }
   21730             :             }
   21731             : 
   21732           0 :             return expression_node_ptr(0);
   21733             :          }
   21734             : 
   21735         375 :          inline std::string get_vector_name(const T* data)
   21736             :          {
   21737        1273 :             for (std::size_t i = 0; i < element_.size(); ++i)
   21738             :             {
   21739         898 :                scope_element& se = element_[i];
   21740             : 
   21741         898 :                if (
   21742        1796 :                     se.active   &&
   21743        1191 :                     se.vec_node &&
   21744         293 :                     (se.vec_node->data() == data)
   21745             :                   )
   21746             :                {
   21747           0 :                   return se.name;
   21748             :                }
   21749             :             }
   21750             : 
   21751         750 :             return "neo-vector";
   21752             :          }
   21753             : 
   21754             :       private:
   21755             : 
   21756             :          scope_element_manager(const scope_element_manager&) exprtk_delete;
   21757             :          scope_element_manager& operator=(const scope_element_manager&) exprtk_delete;
   21758             : 
   21759             :          parser_t& parser_;
   21760             :          std::vector<scope_element> element_;
   21761             :          scope_element null_element_;
   21762             :          std::size_t input_param_cnt_;
   21763             :       };
   21764             : 
   21765             :       class scope_handler
   21766             :       {
   21767             :       public:
   21768             : 
   21769             :          typedef parser<T> parser_t;
   21770             : 
   21771       20264 :          explicit scope_handler(parser<T>& p)
   21772       20264 :          : parser_(p)
   21773             :          {
   21774       20264 :             parser_.state_.scope_depth++;
   21775             :             #ifdef exprtk_enable_debugging
   21776             :             const std::string depth(2 * parser_.state_.scope_depth,'-');
   21777             :             exprtk_debug(("%s> Scope Depth: %02d\n",
   21778             :                           depth.c_str(),
   21779             :                           static_cast<int>(parser_.state_.scope_depth)));
   21780             :             #endif
   21781       20264 :          }
   21782             : 
   21783       20264 :         ~scope_handler()
   21784             :          {
   21785       20264 :             parser_.sem_.deactivate(parser_.state_.scope_depth);
   21786       20264 :             parser_.state_.scope_depth--;
   21787             :             #ifdef exprtk_enable_debugging
   21788             :             const std::string depth(2 * parser_.state_.scope_depth,'-');
   21789             :             exprtk_debug(("<%s Scope Depth: %02d\n",
   21790             :                           depth.c_str(),
   21791             :                           static_cast<int>(parser_.state_.scope_depth)));
   21792             :             #endif
   21793       20264 :          }
   21794             : 
   21795             :       private:
   21796             : 
   21797             :          scope_handler(const scope_handler&) exprtk_delete;
   21798             :          scope_handler& operator=(const scope_handler&) exprtk_delete;
   21799             : 
   21800             :          parser_t& parser_;
   21801             :       };
   21802             : 
   21803             :       template <typename T_>
   21804             :       struct halfopen_range_policy
   21805             :       {
   21806          51 :          static inline bool is_within(const T_& v, const T_& begin, const T_& end)
   21807             :          {
   21808          51 :             assert(begin <= end);
   21809          51 :             return (begin <= v) && (v < end);
   21810             :          }
   21811             : 
   21812             :          static inline bool is_less(const T_& v, const T_& begin)
   21813             :          {
   21814             :             return (v < begin);
   21815             :          }
   21816             : 
   21817          20 :          static inline bool is_greater(const T_& v, const T_& end)
   21818             :          {
   21819          20 :             return (end <= v);
   21820             :          }
   21821             : 
   21822       57374 :          static inline bool end_inclusive()
   21823             :          {
   21824       57374 :             return false;
   21825             :          }
   21826             :       };
   21827             : 
   21828             :       template <typename T_>
   21829             :       struct closed_range_policy
   21830             :       {
   21831             :          static inline bool is_within(const T_& v, const T_& begin, const T_& end)
   21832             :          {
   21833             :             assert(begin <= end);
   21834             :             return (begin <= v) && (v <= end);
   21835             :          }
   21836             : 
   21837             :          static inline bool is_less(const T_& v, const T_& begin)
   21838             :          {
   21839             :             return (v < begin);
   21840             :          }
   21841             : 
   21842             :          static inline bool is_greater(const T_& v, const T_& end)
   21843             :          {
   21844             :             return (end < v);
   21845             :          }
   21846             : 
   21847             :          static inline bool end_inclusive()
   21848             :          {
   21849             :             return true;
   21850             :          }
   21851             :       };
   21852             : 
   21853             :       template <typename IntervalPointType,
   21854             :                 typename RangePolicy = halfopen_range_policy<IntervalPointType> >
   21855             :       class interval_container_t
   21856             :       {
   21857             :       public:
   21858             : 
   21859             :          typedef IntervalPointType interval_point_t;
   21860             :          typedef std::pair<interval_point_t, interval_point_t> interval_t;
   21861             :          typedef std::map<interval_point_t, interval_t> interval_map_t;
   21862             :          typedef typename interval_map_t::const_iterator interval_map_citr_t;
   21863             : 
   21864             :          std::size_t size() const
   21865             :          {
   21866             :             return interval_map_.size();
   21867             :          }
   21868             : 
   21869      371453 :          void reset()
   21870             :          {
   21871      371453 :             interval_map_.clear();
   21872      371453 :          }
   21873             : 
   21874       57374 :          bool in_interval(const interval_point_t point, interval_t& interval) const
   21875             :          {
   21876       57374 :             interval_map_citr_t itr = RangePolicy::end_inclusive() ?
   21877           0 :                                       interval_map_.lower_bound(point):
   21878       57374 :                                       interval_map_.upper_bound(point);
   21879             : 
   21880       57394 :             for (; itr != interval_map_.end(); ++itr)
   21881             :             {
   21882          51 :                const interval_point_t& begin = itr->second.first;
   21883          51 :                const interval_point_t& end   = itr->second.second;
   21884             : 
   21885          51 :                if (RangePolicy::is_within(point, begin, end))
   21886             :                {
   21887          31 :                   interval = interval_t(begin,end);
   21888          31 :                   return true;
   21889             :                }
   21890          20 :                else if (RangePolicy::is_greater(point, end))
   21891             :                {
   21892           0 :                   break;
   21893             :                }
   21894             :             }
   21895             : 
   21896       57343 :             return false;
   21897             :          }
   21898             : 
   21899         107 :          bool in_interval(const interval_point_t point) const
   21900             :          {
   21901         107 :             interval_t interval;
   21902         214 :             return in_interval(point,interval);
   21903             :          }
   21904             : 
   21905          55 :          bool add_interval(const interval_point_t begin, const interval_point_t end)
   21906             :          {
   21907          55 :             if ((end <= begin) || in_interval(begin) || in_interval(end))
   21908             :             {
   21909           3 :                return false;
   21910             :             }
   21911             : 
   21912          52 :             interval_map_[end] = std::make_pair(begin, end);
   21913             : 
   21914          52 :             return true;
   21915             :          }
   21916             : 
   21917          55 :          bool add_interval(const interval_t interval)
   21918             :          {
   21919          55 :             return add_interval(interval.first, interval.second);
   21920             :          }
   21921             : 
   21922             :       private:
   21923             : 
   21924             :          interval_map_t interval_map_;
   21925             :       };
   21926             : 
   21927             :       class stack_limit_handler
   21928             :       {
   21929             :       public:
   21930             : 
   21931             :          typedef parser<T> parser_t;
   21932             : 
   21933    12390872 :          explicit stack_limit_handler(parser<T>& p)
   21934    12390872 :          : parser_(p)
   21935    12390872 :          , limit_exceeded_(false)
   21936             :          {
   21937    12390872 :             if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
   21938             :             {
   21939           0 :                limit_exceeded_ = true;
   21940           0 :                parser_.set_error(make_error(
   21941             :                   parser_error::e_parser,
   21942           0 :                   "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
   21943           0 :                   " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
   21944             :                   exprtk_error_location));
   21945             :             }
   21946    12390872 :          }
   21947             : 
   21948    12390872 :         ~stack_limit_handler()
   21949             :          {
   21950    12390872 :             assert(parser_.state_.stack_depth > 0);
   21951    12390872 :             parser_.state_.stack_depth--;
   21952    12390872 :          }
   21953             : 
   21954    12390872 :          bool operator!()
   21955             :          {
   21956    12390872 :             return limit_exceeded_;
   21957             :          }
   21958             : 
   21959             :       private:
   21960             : 
   21961             :          stack_limit_handler(const stack_limit_handler&) exprtk_delete;
   21962             :          stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete;
   21963             : 
   21964             :          parser_t& parser_;
   21965             :          bool limit_exceeded_;
   21966             :       };
   21967             : 
   21968             :       struct symtab_store
   21969             :       {
   21970             :          symbol_table_list_t symtab_list_;
   21971             : 
   21972             :          typedef typename symbol_table_t::local_data_t local_data_t;
   21973             :          typedef typename symbol_table_t::variable_ptr variable_ptr;
   21974             :          typedef typename symbol_table_t::function_ptr function_ptr;
   21975             :          #ifndef exprtk_disable_string_capabilities
   21976             :          typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
   21977             :          #endif
   21978             :          typedef typename symbol_table_t::vector_holder_ptr    vector_holder_ptr;
   21979             :          typedef typename symbol_table_t::vararg_function_ptr  vararg_function_ptr;
   21980             :          typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
   21981             : 
   21982             :          struct variable_context
   21983             :          {
   21984     2030084 :             variable_context()
   21985     2030084 :             : symbol_table(0)
   21986     2030084 :             , variable(0)
   21987     2030084 :             {}
   21988             : 
   21989             :             const symbol_table_t* symbol_table;
   21990             :             variable_ptr variable;
   21991             :          };
   21992             : 
   21993             :          struct vector_context
   21994             :          {
   21995        6869 :             vector_context()
   21996        6869 :             : symbol_table(0)
   21997        6869 :             , vector_holder(0)
   21998        6869 :             {}
   21999             : 
   22000             :             const symbol_table_t* symbol_table;
   22001             :             vector_holder_ptr vector_holder;
   22002             :          };
   22003             : 
   22004             :          #ifndef exprtk_disable_string_capabilities
   22005             :          struct string_context
   22006             :          {
   22007       49475 :             string_context()
   22008       49475 :             : symbol_table(0)
   22009       49475 :             , str_var(0)
   22010       49475 :             {}
   22011             : 
   22012             :             const symbol_table_t* symbol_table;
   22013             :             stringvar_ptr str_var;
   22014             :          };
   22015             :          #endif
   22016             : 
   22017     2027972 :          inline bool empty() const
   22018             :          {
   22019     2027972 :             return symtab_list_.empty();
   22020             :          }
   22021             : 
   22022             :          inline void clear()
   22023             :          {
   22024             :             symtab_list_.clear();
   22025             :          }
   22026             : 
   22027     2027972 :          inline bool valid() const
   22028             :          {
   22029     2027972 :             if (!empty())
   22030             :             {
   22031     2027804 :                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22032             :                {
   22033     2027804 :                   if (symtab_list_[i].valid())
   22034     2027804 :                      return true;
   22035             :                }
   22036             :             }
   22037             : 
   22038         168 :             return false;
   22039             :          }
   22040             : 
   22041     3942275 :          inline bool valid_symbol(const std::string& symbol) const
   22042             :          {
   22043     3942275 :             if (!symtab_list_.empty())
   22044     3942201 :                return symtab_list_[0].valid_symbol(symbol);
   22045             :             else
   22046          74 :                return false;
   22047             :          }
   22048             : 
   22049      180478 :          inline bool valid_function_name(const std::string& symbol) const
   22050             :          {
   22051      180478 :             if (!symtab_list_.empty())
   22052      180418 :                return symtab_list_[0].valid_function(symbol);
   22053             :             else
   22054          60 :                return false;
   22055             :          }
   22056             : 
   22057     2030084 :          inline variable_context get_variable_context(const std::string& variable_name) const
   22058             :          {
   22059     2030084 :             variable_context result;
   22060     2030084 :             if (!valid_symbol(variable_name))
   22061        2497 :                return result;
   22062             : 
   22063     2322697 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22064             :             {
   22065     2095478 :                if (!symtab_list_[i].valid())
   22066             :                {
   22067           0 :                   continue;
   22068             :                }
   22069             : 
   22070     2095478 :                result.variable = local_data(i)
   22071     2095478 :                                     .variable_store.get(variable_name);
   22072     2095478 :                if (result.variable)
   22073             :                {
   22074     1800368 :                   result.symbol_table = &symtab_list_[i];
   22075     1800368 :                   break;
   22076             :                }
   22077             :             }
   22078             : 
   22079     2027587 :             return result;
   22080             :          }
   22081             : 
   22082        3002 :          inline variable_ptr get_variable(const std::string& variable_name) const
   22083             :          {
   22084        3002 :             if (!valid_symbol(variable_name))
   22085           0 :                return reinterpret_cast<variable_ptr>(0);
   22086             : 
   22087        3002 :             variable_ptr result = reinterpret_cast<variable_ptr>(0);
   22088             : 
   22089        3002 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22090             :             {
   22091        3002 :                if (!symtab_list_[i].valid())
   22092           0 :                   continue;
   22093             :                else
   22094        3002 :                   result = local_data(i)
   22095        3002 :                               .variable_store.get(variable_name);
   22096             : 
   22097        3002 :                if (result) break;
   22098             :             }
   22099             : 
   22100        3002 :             return result;
   22101             :          }
   22102             : 
   22103         320 :          inline variable_ptr get_variable(const T& var_ref) const
   22104             :          {
   22105         320 :             variable_ptr result = reinterpret_cast<variable_ptr>(0);
   22106             : 
   22107         640 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22108             :             {
   22109         320 :                if (!symtab_list_[i].valid())
   22110           0 :                   continue;
   22111             :                else
   22112         320 :                   result = local_data(i).variable_store
   22113         320 :                               .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
   22114             : 
   22115         320 :                if (result) break;
   22116             :             }
   22117             : 
   22118         320 :             return result;
   22119             :          }
   22120             : 
   22121             :          #ifndef exprtk_disable_string_capabilities
   22122       49475 :          inline string_context get_string_context(const std::string& string_name) const
   22123             :          {
   22124       49475 :             string_context result;
   22125             : 
   22126       49475 :             if (!valid_symbol(string_name))
   22127           0 :                return result;
   22128             : 
   22129       49475 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22130             :             {
   22131       49475 :                if (!symtab_list_[i].valid())
   22132             :                {
   22133           0 :                   continue;
   22134             :                }
   22135             : 
   22136       49475 :                result.str_var = local_data(i).stringvar_store.get(string_name);
   22137             : 
   22138       49475 :                if (result.str_var)
   22139             :                {
   22140       49475 :                   result.symbol_table = &symtab_list_[i];
   22141       49475 :                   break;
   22142             :                }
   22143             :             }
   22144             : 
   22145       49475 :             return result;
   22146             :          }
   22147             : 
   22148             :          inline stringvar_ptr get_stringvar(const std::string& string_name) const
   22149             :          {
   22150             :             if (!valid_symbol(string_name))
   22151             :                return reinterpret_cast<stringvar_ptr>(0);
   22152             : 
   22153             :             stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
   22154             : 
   22155             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22156             :             {
   22157             :                if (!symtab_list_[i].valid())
   22158             :                   continue;
   22159             :                else
   22160             :                   result = local_data(i)
   22161             :                               .stringvar_store.get(string_name);
   22162             : 
   22163             :                if (result) break;
   22164             :             }
   22165             : 
   22166             :             return result;
   22167             :          }
   22168             :          #endif
   22169             : 
   22170       85351 :          inline function_ptr get_function(const std::string& function_name) const
   22171             :          {
   22172       85351 :             if (!valid_function_name(function_name))
   22173          35 :                return reinterpret_cast<function_ptr>(0);
   22174             : 
   22175       85316 :             function_ptr result = reinterpret_cast<function_ptr>(0);
   22176             : 
   22177      128054 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22178             :             {
   22179      103349 :                if (!symtab_list_[i].valid())
   22180           0 :                   continue;
   22181             :                else
   22182      103349 :                   result = local_data(i)
   22183      103349 :                               .function_store.get(function_name);
   22184             : 
   22185      103349 :                if (result) break;
   22186             :             }
   22187             : 
   22188       85316 :             return result;
   22189             :          }
   22190             : 
   22191       24740 :          inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
   22192             :          {
   22193       24740 :             if (!valid_function_name(vararg_function_name))
   22194          35 :                return reinterpret_cast<vararg_function_ptr>(0);
   22195             : 
   22196       24705 :             vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
   22197             : 
   22198       64994 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22199             :             {
   22200       40338 :                if (!symtab_list_[i].valid())
   22201           0 :                   continue;
   22202             :                else
   22203       40338 :                   result = local_data(i)
   22204       40338 :                               .vararg_function_store.get(vararg_function_name);
   22205             : 
   22206       40338 :                if (result) break;
   22207             :             }
   22208             : 
   22209       24705 :             return result;
   22210             :          }
   22211             : 
   22212       24691 :          inline generic_function_ptr get_generic_function(const std::string& function_name) const
   22213             :          {
   22214       24691 :             if (!valid_function_name(function_name))
   22215          35 :                return reinterpret_cast<generic_function_ptr>(0);
   22216             : 
   22217       24656 :             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
   22218             : 
   22219       63120 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22220             :             {
   22221       40289 :                if (!symtab_list_[i].valid())
   22222           0 :                   continue;
   22223             :                else
   22224       40289 :                   result = local_data(i)
   22225       40289 :                               .generic_function_store.get(function_name);
   22226             : 
   22227       40289 :                if (result) break;
   22228             :             }
   22229             : 
   22230       24656 :             return result;
   22231             :          }
   22232             : 
   22233       22866 :          inline generic_function_ptr get_string_function(const std::string& function_name) const
   22234             :          {
   22235       22866 :             if (!valid_function_name(function_name))
   22236          35 :                return reinterpret_cast<generic_function_ptr>(0);
   22237             : 
   22238       22831 :             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
   22239             : 
   22240       61259 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22241             :             {
   22242       38464 :                if (!symtab_list_[i].valid())
   22243           0 :                   continue;
   22244             :                else
   22245             :                   result =
   22246       38464 :                      local_data(i).string_function_store.get(function_name);
   22247             : 
   22248       38464 :                if (result) break;
   22249             :             }
   22250             : 
   22251       22831 :             return result;
   22252             :          }
   22253             : 
   22254       22830 :          inline generic_function_ptr get_overload_function(const std::string& function_name) const
   22255             :          {
   22256       22830 :             if (!valid_function_name(function_name))
   22257          35 :                return reinterpret_cast<generic_function_ptr>(0);
   22258             : 
   22259       22795 :             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
   22260             : 
   22261       61151 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22262             :             {
   22263       38428 :                if (!symtab_list_[i].valid())
   22264           0 :                   continue;
   22265             :                else
   22266             :                   result =
   22267       38428 :                      local_data(i).overload_function_store.get(function_name);
   22268             : 
   22269       38428 :                if (result) break;
   22270             :             }
   22271             : 
   22272       22795 :             return result;
   22273             :          }
   22274             : 
   22275        6869 :          inline vector_context get_vector_context(const std::string& vector_name) const
   22276             :          {
   22277        6869 :             vector_context result;
   22278        6869 :             if (!valid_symbol(vector_name))
   22279           0 :                return result;
   22280             : 
   22281        6869 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22282             :             {
   22283        6869 :                if (!symtab_list_[i].valid())
   22284             :                {
   22285           0 :                   continue;
   22286             :                }
   22287             : 
   22288        6869 :                result.vector_holder = local_data(i).vector_store.get(vector_name);
   22289             : 
   22290        6869 :                if (result.vector_holder)
   22291             :                {
   22292        6869 :                   result.symbol_table = &symtab_list_[i];
   22293        6869 :                   break;
   22294             :                }
   22295             :             }
   22296             : 
   22297        6869 :             return result;
   22298             :          }
   22299             : 
   22300             :          inline vector_holder_ptr get_vector(const std::string& vector_name) const
   22301             :          {
   22302             :             if (!valid_symbol(vector_name))
   22303             :                return reinterpret_cast<vector_holder_ptr>(0);
   22304             : 
   22305             :             vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
   22306             : 
   22307             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22308             :             {
   22309             :                if (!symtab_list_[i].valid())
   22310             :                {
   22311             :                   continue;
   22312             :                }
   22313             : 
   22314             :                result = local_data(i).vector_store.get(vector_name);
   22315             : 
   22316             :                if (result)
   22317             :                {
   22318             :                   break;
   22319             :                }
   22320             :             }
   22321             : 
   22322             :             return result;
   22323             :          }
   22324             : 
   22325     1803370 :          inline bool is_constant_node(const std::string& symbol_name) const
   22326             :          {
   22327     1803370 :             if (!valid_symbol(symbol_name))
   22328           0 :                return false;
   22329             : 
   22330     3665084 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22331             :             {
   22332     1906299 :                if (!symtab_list_[i].valid())
   22333             :                {
   22334           0 :                   continue;
   22335             :                }
   22336             : 
   22337     1906299 :                if (local_data(i).variable_store.is_constant(symbol_name))
   22338             :                {
   22339       44585 :                   return true;
   22340             :                }
   22341             :             }
   22342             : 
   22343     1758785 :             return false;
   22344             :          }
   22345             : 
   22346             :          #ifndef exprtk_disable_string_capabilities
   22347       49475 :          inline bool is_constant_string(const std::string& symbol_name) const
   22348             :          {
   22349       49475 :             if (!valid_symbol(symbol_name))
   22350           0 :                return false;
   22351             : 
   22352       98974 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22353             :             {
   22354       49499 :                if (!symtab_list_[i].valid())
   22355           0 :                   continue;
   22356       49499 :                else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
   22357          24 :                   continue;
   22358       49475 :                else if (local_data(i).stringvar_store.is_constant(symbol_name))
   22359           0 :                   return true;
   22360             :             }
   22361             : 
   22362       49475 :             return false;
   22363             :          }
   22364             :          #endif
   22365             : 
   22366       56410 :          inline bool symbol_exists(const std::string& symbol) const
   22367             :          {
   22368      112763 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22369             :             {
   22370       56353 :                if (!symtab_list_[i].valid())
   22371             :                {
   22372           0 :                   continue;
   22373             :                }
   22374             : 
   22375       56353 :                if (symtab_list_[i].symbol_exists(symbol))
   22376             :                {
   22377           0 :                   return true;
   22378             :                }
   22379             :             }
   22380             : 
   22381       56410 :             return false;
   22382             :          }
   22383             : 
   22384         400 :          inline bool is_variable(const std::string& variable_name) const
   22385             :          {
   22386         800 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22387             :             {
   22388         400 :                if (!symtab_list_[i].valid())
   22389           0 :                   continue;
   22390         400 :                else if (
   22391         400 :                          symtab_list_[i].local_data().variable_store
   22392         400 :                            .symbol_exists(variable_name)
   22393             :                        )
   22394           0 :                   return true;
   22395             :             }
   22396             : 
   22397         400 :             return false;
   22398             :          }
   22399             : 
   22400             :          #ifndef exprtk_disable_string_capabilities
   22401      134826 :          inline bool is_stringvar(const std::string& stringvar_name) const
   22402             :          {
   22403      242398 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22404             :             {
   22405      157047 :                if (!symtab_list_[i].valid())
   22406           0 :                   continue;
   22407      157047 :                else if (
   22408      157047 :                          symtab_list_[i].local_data().stringvar_store
   22409      157047 :                            .symbol_exists(stringvar_name)
   22410             :                        )
   22411       49475 :                   return true;
   22412             :             }
   22413             : 
   22414       85351 :             return false;
   22415             :          }
   22416             : 
   22417       49475 :          inline bool is_conststr_stringvar(const std::string& symbol_name) const
   22418             :          {
   22419       49475 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22420             :             {
   22421       49475 :                if (!symtab_list_[i].valid())
   22422           0 :                   continue;
   22423       49475 :                else if (
   22424       49475 :                          symtab_list_[i].local_data().stringvar_store
   22425       49475 :                            .symbol_exists(symbol_name)
   22426             :                        )
   22427             :                {
   22428             :                   return (
   22429       49475 :                            local_data(i).stringvar_store.symbol_exists(symbol_name) ||
   22430           0 :                            local_data(i).stringvar_store.is_constant  (symbol_name)
   22431       49475 :                          );
   22432             : 
   22433             :                }
   22434             :             }
   22435             : 
   22436           0 :             return false;
   22437             :          }
   22438             :          #endif
   22439             : 
   22440             :          inline bool is_function(const std::string& function_name) const
   22441             :          {
   22442             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22443             :             {
   22444             :                if (!symtab_list_[i].valid())
   22445             :                   continue;
   22446             :                else if (
   22447             :                          local_data(i).vararg_function_store
   22448             :                            .symbol_exists(function_name)
   22449             :                        )
   22450             :                   return true;
   22451             :             }
   22452             : 
   22453             :             return false;
   22454             :          }
   22455             : 
   22456             :          inline bool is_vararg_function(const std::string& vararg_function_name) const
   22457             :          {
   22458             :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22459             :             {
   22460             :                if (!symtab_list_[i].valid())
   22461             :                   continue;
   22462             :                else if (
   22463             :                          local_data(i).vararg_function_store
   22464             :                            .symbol_exists(vararg_function_name)
   22465             :                        )
   22466             :                   return true;
   22467             :             }
   22468             : 
   22469             :             return false;
   22470             :          }
   22471             : 
   22472       22838 :          inline bool is_vector(const std::string& vector_name) const
   22473             :          {
   22474       54403 :             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
   22475             :             {
   22476       38434 :                if (!symtab_list_[i].valid())
   22477           0 :                   continue;
   22478       38434 :                else if (
   22479       38434 :                          local_data(i).vector_store
   22480       38434 :                            .symbol_exists(vector_name)
   22481             :                        )
   22482        6869 :                   return true;
   22483             :             }
   22484             : 
   22485       15969 :             return false;
   22486             :          }
   22487             : 
   22488           3 :          inline std::string get_variable_name(const expression_node_ptr& ptr) const
   22489             :          {
   22490           6 :             return local_data().variable_store.entity_name(ptr);
   22491             :          }
   22492             : 
   22493           0 :          inline std::string get_vector_name(const vector_holder_ptr& ptr) const
   22494             :          {
   22495           0 :             return local_data().vector_store.entity_name(ptr);
   22496             :          }
   22497             : 
   22498             :          #ifndef exprtk_disable_string_capabilities
   22499           1 :          inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
   22500             :          {
   22501           2 :             return local_data().stringvar_store.entity_name(ptr);
   22502             :          }
   22503             : 
   22504             :          inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
   22505             :          {
   22506             :             return local_data().stringvar_store.entity_name(ptr);
   22507             :          }
   22508             :          #endif
   22509             : 
   22510             :          inline local_data_t& local_data(const std::size_t& index = 0)
   22511             :          {
   22512             :             return symtab_list_[index].local_data();
   22513             :          }
   22514             : 
   22515           8 :          inline const local_data_t& local_data(const std::size_t& index = 0) const
   22516             :          {
   22517     4509198 :             return symtab_list_[index].local_data();
   22518             :          }
   22519             : 
   22520       15624 :          inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
   22521             :          {
   22522        5208 :             return symtab_list_[index];
   22523             :          }
   22524             :       };
   22525             : 
   22526             :       struct parser_state
   22527             :       {
   22528      106542 :          parser_state()
   22529      106542 :          : type_check_enabled(true)
   22530             :          {
   22531      106542 :             reset();
   22532      106542 :          }
   22533             : 
   22534      477995 :          void reset()
   22535             :          {
   22536      477995 :             parsing_return_stmt     = false;
   22537      477995 :             parsing_break_stmt      = false;
   22538      477995 :             return_stmt_present     = false;
   22539      477995 :             side_effect_present     = false;
   22540      477995 :             scope_depth             = 0;
   22541      477995 :             stack_depth             = 0;
   22542      477995 :             parsing_loop_stmt_count = 0;
   22543      477995 :          }
   22544             : 
   22545             :          #ifndef exprtk_enable_debugging
   22546      224828 :          void activate_side_effect(const std::string&)
   22547             :          #else
   22548             :          void activate_side_effect(const std::string& source)
   22549             :          #endif
   22550             :          {
   22551      224828 :             if (!side_effect_present)
   22552             :             {
   22553      129482 :                side_effect_present = true;
   22554             : 
   22555             :                exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str()));
   22556             :             }
   22557      224828 :          }
   22558             : 
   22559             :          bool parsing_return_stmt;
   22560             :          bool parsing_break_stmt;
   22561             :          bool return_stmt_present;
   22562             :          bool side_effect_present;
   22563             :          bool type_check_enabled;
   22564             :          std::size_t scope_depth;
   22565             :          std::size_t stack_depth;
   22566             :          std::size_t parsing_loop_stmt_count;
   22567             :       };
   22568             : 
   22569             :    public:
   22570             : 
   22571             :       struct unknown_symbol_resolver
   22572             :       {
   22573             : 
   22574             :          enum usr_symbol_type
   22575             :          {
   22576             :             e_usr_unknown_type  = 0,
   22577             :             e_usr_variable_type = 1,
   22578             :             e_usr_constant_type = 2
   22579             :          };
   22580             : 
   22581             :          enum usr_mode
   22582             :          {
   22583             :             e_usrmode_default  = 0,
   22584             :             e_usrmode_extended = 1
   22585             :          };
   22586             : 
   22587             :          usr_mode mode;
   22588             : 
   22589      106746 :          unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
   22590      106746 :          : mode(m)
   22591      106746 :          {}
   22592             : 
   22593      106746 :          virtual ~unknown_symbol_resolver()
   22594      106746 :          {}
   22595             : 
   22596           2 :          virtual bool process(const std::string& /*unknown_symbol*/,
   22597             :                               usr_symbol_type&   st,
   22598             :                               T&                 default_value,
   22599             :                               std::string&       error_message)
   22600             :          {
   22601           2 :             if (e_usrmode_default != mode)
   22602           0 :                return false;
   22603             : 
   22604           2 :             st = e_usr_variable_type;
   22605           2 :             default_value = T(0);
   22606           2 :             error_message.clear();
   22607             : 
   22608           2 :             return true;
   22609             :          }
   22610             : 
   22611           0 :          virtual bool process(const std::string& /* unknown_symbol */,
   22612             :                               symbol_table_t&    /* symbol_table   */,
   22613             :                               std::string&       /* error_message  */)
   22614             :          {
   22615           0 :             return false;
   22616             :          }
   22617             :       };
   22618             : 
   22619             :       enum collect_type
   22620             :       {
   22621             :          e_ct_none        = 0,
   22622             :          e_ct_variables   = 1,
   22623             :          e_ct_functions   = 2,
   22624             :          e_ct_assignments = 4
   22625             :       };
   22626             : 
   22627             :       enum symbol_type
   22628             :       {
   22629             :          e_st_unknown        = 0,
   22630             :          e_st_variable       = 1,
   22631             :          e_st_vector         = 2,
   22632             :          e_st_vecelem        = 3,
   22633             :          e_st_string         = 4,
   22634             :          e_st_function       = 5,
   22635             :          e_st_local_variable = 6,
   22636             :          e_st_local_vector   = 7,
   22637             :          e_st_local_string   = 8
   22638             :       };
   22639             : 
   22640             :       class dependent_entity_collector
   22641             :       {
   22642             :       public:
   22643             : 
   22644             :          typedef std::pair<std::string,symbol_type> symbol_t;
   22645             :          typedef std::vector<symbol_t> symbol_list_t;
   22646             : 
   22647      106542 :          dependent_entity_collector(const std::size_t options = e_ct_none)
   22648      106542 :          : options_(options)
   22649      106542 :          , collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  )
   22650      106542 :          , collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  )
   22651      106542 :          , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments)
   22652      106542 :          , return_present_   (false)
   22653      106542 :          , final_stmt_return_(false)
   22654      106542 :          {}
   22655             : 
   22656             :          template <typename Allocator,
   22657             :                    template <typename, typename> class Sequence>
   22658           3 :          inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
   22659             :          {
   22660           3 :             if (!collect_variables_ && !collect_functions_)
   22661           0 :                return 0;
   22662           3 :             else if (symbol_name_list_.empty())
   22663           0 :                return 0;
   22664             : 
   22665          23 :             for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
   22666             :             {
   22667          20 :                details::case_normalise(symbol_name_list_[i].first);
   22668             :             }
   22669             : 
   22670           3 :             std::sort(symbol_name_list_.begin(), symbol_name_list_.end());
   22671             : 
   22672             :             std::unique_copy
   22673           3 :             (
   22674             :                symbol_name_list_.begin(),
   22675             :                symbol_name_list_.end  (),
   22676             :                std::back_inserter(symbols_list)
   22677             :             );
   22678             : 
   22679           3 :             return symbols_list.size();
   22680             :          }
   22681             : 
   22682             :          template <typename Allocator,
   22683             :                    template <typename, typename> class Sequence>
   22684           1 :          inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
   22685             :          {
   22686           1 :             if (!collect_assignments_)
   22687           0 :                return 0;
   22688           1 :             else if (assignment_name_list_.empty())
   22689           0 :                return 0;
   22690             : 
   22691           5 :             for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
   22692             :             {
   22693           4 :                details::case_normalise(assignment_name_list_[i].first);
   22694             :             }
   22695             : 
   22696           1 :             std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
   22697             : 
   22698             :             std::unique_copy
   22699           1 :             (
   22700             :                assignment_name_list_.begin(),
   22701             :                assignment_name_list_.end  (),
   22702             :                std::back_inserter(assignment_list)
   22703             :             );
   22704             : 
   22705           1 :             return assignment_list.size();
   22706             :          }
   22707             : 
   22708      371924 :          void clear()
   22709             :          {
   22710      371924 :             symbol_name_list_    .clear();
   22711      371924 :             assignment_name_list_.clear();
   22712      371924 :             retparam_list_       .clear();
   22713      371924 :             return_present_    = false;
   22714      371924 :             final_stmt_return_ = false;
   22715      371924 :          }
   22716             : 
   22717      106545 :          bool& collect_variables()
   22718             :          {
   22719      106545 :             return collect_variables_;
   22720             :          }
   22721             : 
   22722      106545 :          bool& collect_functions()
   22723             :          {
   22724      106545 :             return collect_functions_;
   22725             :          }
   22726             : 
   22727      163782 :          bool& collect_assignments()
   22728             :          {
   22729      163782 :             return collect_assignments_;
   22730             :          }
   22731             : 
   22732        1484 :          bool return_present() const
   22733             :          {
   22734        1484 :             return return_present_;
   22735             :          }
   22736             : 
   22737             :          bool final_stmt_return() const
   22738             :          {
   22739             :             return final_stmt_return_;
   22740             :          }
   22741             : 
   22742             :          typedef std::vector<std::string> retparam_list_t;
   22743             : 
   22744           0 :          retparam_list_t return_param_type_list() const
   22745             :          {
   22746           0 :             return retparam_list_;
   22747             :          }
   22748             : 
   22749             :       private:
   22750             : 
   22751     2375038 :          inline void add_symbol(const std::string& symbol, const symbol_type st)
   22752             :          {
   22753     2375038 :             switch (st)
   22754             :             {
   22755     1975786 :                case e_st_variable       :
   22756             :                case e_st_vector         :
   22757             :                case e_st_string         :
   22758             :                case e_st_local_variable :
   22759             :                case e_st_local_vector   :
   22760     1975786 :                case e_st_local_string   : if (collect_variables_)
   22761             :                                              symbol_name_list_
   22762          19 :                                                 .push_back(std::make_pair(symbol, st));
   22763     1975786 :                                           break;
   22764             : 
   22765      399252 :                case e_st_function       : if (collect_functions_)
   22766             :                                              symbol_name_list_
   22767           5 :                                                 .push_back(std::make_pair(symbol, st));
   22768      399252 :                                           break;
   22769             : 
   22770           0 :                default                  : return;
   22771             :             }
   22772             :          }
   22773             : 
   22774           4 :          inline void add_assignment(const std::string& symbol, const symbol_type st)
   22775             :          {
   22776           4 :             switch (st)
   22777             :             {
   22778           4 :                case e_st_variable       :
   22779             :                case e_st_vector         :
   22780           4 :                case e_st_string         : if (collect_assignments_)
   22781             :                                              assignment_name_list_
   22782           4 :                                                 .push_back(std::make_pair(symbol, st));
   22783           4 :                                           break;
   22784             : 
   22785           0 :                default                  : return;
   22786             :             }
   22787             :          }
   22788             : 
   22789             :          std::size_t options_;
   22790             :          bool collect_variables_;
   22791             :          bool collect_functions_;
   22792             :          bool collect_assignments_;
   22793             :          bool return_present_;
   22794             :          bool final_stmt_return_;
   22795             :          symbol_list_t symbol_name_list_;
   22796             :          symbol_list_t assignment_name_list_;
   22797             :          retparam_list_t retparam_list_;
   22798             : 
   22799             :          friend class parser<T>;
   22800             :       };
   22801             : 
   22802             :       class settings_store
   22803             :       {
   22804             :       private:
   22805             : 
   22806             :          typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
   22807             :          typedef disabled_entity_set_t::iterator des_itr_t;
   22808             : 
   22809             :       public:
   22810             : 
   22811             :          enum settings_compilation_options
   22812             :          {
   22813             :             e_unknown              =    0,
   22814             :             e_replacer             =    1,
   22815             :             e_joiner               =    2,
   22816             :             e_numeric_check        =    4,
   22817             :             e_bracket_check        =    8,
   22818             :             e_sequence_check       =   16,
   22819             :             e_commutative_check    =   32,
   22820             :             e_strength_reduction   =   64,
   22821             :             e_disable_vardef       =  128,
   22822             :             e_collect_vars         =  256,
   22823             :             e_collect_funcs        =  512,
   22824             :             e_collect_assings      = 1024,
   22825             :             e_disable_usr_on_rsrvd = 2048,
   22826             :             e_disable_zero_return  = 4096
   22827             :          };
   22828             : 
   22829             :          enum settings_base_funcs
   22830             :          {
   22831             :             e_bf_unknown = 0,
   22832             :             e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin    ,
   22833             :             e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh   ,
   22834             :             e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos     ,
   22835             :             e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal   ,
   22836             :             e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1   ,
   22837             :             e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp  ,
   22838             :             e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p   ,
   22839             :             e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max     ,
   22840             :             e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul     ,
   22841             :             e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round   ,
   22842             :             e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin     ,
   22843             :             e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum     ,
   22844             :             e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc   ,
   22845             :             e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad ,
   22846             :             e_bf_rad2deg   , e_bf_grad2deg
   22847             :          };
   22848             : 
   22849             :          enum settings_control_structs
   22850             :          {
   22851             :             e_ctrl_unknown = 0,
   22852             :             e_ctrl_ifelse,
   22853             :             e_ctrl_switch,
   22854             :             e_ctrl_for_loop,
   22855             :             e_ctrl_while_loop,
   22856             :             e_ctrl_repeat_loop,
   22857             :             e_ctrl_return
   22858             :          };
   22859             : 
   22860             :          enum settings_logic_opr
   22861             :          {
   22862             :             e_logic_unknown = 0,
   22863             :             e_logic_and, e_logic_nand , e_logic_nor ,
   22864             :             e_logic_not, e_logic_or   , e_logic_xnor,
   22865             :             e_logic_xor, e_logic_scand, e_logic_scor
   22866             :          };
   22867             : 
   22868             :          enum settings_arithmetic_opr
   22869             :          {
   22870             :             e_arith_unknown = 0,
   22871             :             e_arith_add, e_arith_sub, e_arith_mul,
   22872             :             e_arith_div, e_arith_mod, e_arith_pow
   22873             :          };
   22874             : 
   22875             :          enum settings_assignment_opr
   22876             :          {
   22877             :             e_assign_unknown = 0,
   22878             :             e_assign_assign, e_assign_addass, e_assign_subass,
   22879             :             e_assign_mulass, e_assign_divass, e_assign_modass
   22880             :          };
   22881             : 
   22882             :          enum settings_inequality_opr
   22883             :          {
   22884             :             e_ineq_unknown = 0,
   22885             :             e_ineq_lt   , e_ineq_lte, e_ineq_eq    ,
   22886             :             e_ineq_equal, e_ineq_ne , e_ineq_nequal,
   22887             :             e_ineq_gte  , e_ineq_gt
   22888             :          };
   22889             : 
   22890             :          static const std::size_t default_compile_all_opts =
   22891             :                                      e_replacer          +
   22892             :                                      e_joiner            +
   22893             :                                      e_numeric_check     +
   22894             :                                      e_bracket_check     +
   22895             :                                      e_sequence_check    +
   22896             :                                      e_commutative_check +
   22897             :                                      e_strength_reduction;
   22898             : 
   22899      106542 :          settings_store(const std::size_t compile_options = default_compile_all_opts)
   22900      106542 :          : max_stack_depth_(400)
   22901      106542 :          , max_node_depth_(10000)
   22902      106542 :          , max_local_vector_size_(2000000000)
   22903             :          {
   22904      106542 :            load_compile_options(compile_options);
   22905      106542 :          }
   22906             : 
   22907             :          settings_store& enable_all_base_functions()
   22908             :          {
   22909             :             disabled_func_set_.clear();
   22910             :             return (*this);
   22911             :          }
   22912             : 
   22913             :          settings_store& enable_all_control_structures()
   22914             :          {
   22915             :             disabled_ctrl_set_.clear();
   22916             :             return (*this);
   22917             :          }
   22918             : 
   22919             :          settings_store& enable_all_logic_ops()
   22920             :          {
   22921             :             disabled_logic_set_.clear();
   22922             :             return (*this);
   22923             :          }
   22924             : 
   22925             :          settings_store& enable_all_arithmetic_ops()
   22926             :          {
   22927             :             disabled_arithmetic_set_.clear();
   22928             :             return (*this);
   22929             :          }
   22930             : 
   22931             :          settings_store& enable_all_assignment_ops()
   22932             :          {
   22933             :             disabled_assignment_set_.clear();
   22934             :             return (*this);
   22935             :          }
   22936             : 
   22937             :          settings_store& enable_all_inequality_ops()
   22938             :          {
   22939             :             disabled_inequality_set_.clear();
   22940             :             return (*this);
   22941             :          }
   22942             : 
   22943             :          settings_store& enable_local_vardef()
   22944             :          {
   22945             :             disable_vardef_ = false;
   22946             :             return (*this);
   22947             :          }
   22948             : 
   22949             :          settings_store& enable_commutative_check()
   22950             :          {
   22951             :             enable_commutative_check_ = true;
   22952             :             return (*this);
   22953             :          }
   22954             : 
   22955             :          settings_store& enable_strength_reduction()
   22956             :          {
   22957             :             enable_strength_reduction_ = true;
   22958             :             return (*this);
   22959             :          }
   22960             : 
   22961             :          settings_store& disable_all_base_functions()
   22962             :          {
   22963             :             std::copy(details::base_function_list,
   22964             :                       details::base_function_list + details::base_function_list_size,
   22965             :                       std::insert_iterator<disabled_entity_set_t>
   22966             :                          (disabled_func_set_, disabled_func_set_.begin()));
   22967             :             return (*this);
   22968             :          }
   22969             : 
   22970             :          settings_store& disable_all_control_structures()
   22971             :          {
   22972             :             std::copy(details::cntrl_struct_list,
   22973             :                       details::cntrl_struct_list + details::cntrl_struct_list_size,
   22974             :                       std::insert_iterator<disabled_entity_set_t>
   22975             :                          (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
   22976             :             return (*this);
   22977             :          }
   22978             : 
   22979             :          settings_store& disable_all_logic_ops()
   22980             :          {
   22981             :             std::copy(details::logic_ops_list,
   22982             :                       details::logic_ops_list + details::logic_ops_list_size,
   22983             :                       std::insert_iterator<disabled_entity_set_t>
   22984             :                         (disabled_logic_set_, disabled_logic_set_.begin()));
   22985             :             return (*this);
   22986             :          }
   22987             : 
   22988             :          settings_store& disable_all_arithmetic_ops()
   22989             :          {
   22990             :             std::copy(details::arithmetic_ops_list,
   22991             :                       details::arithmetic_ops_list + details::arithmetic_ops_list_size,
   22992             :                       std::insert_iterator<disabled_entity_set_t>
   22993             :                          (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
   22994             :             return (*this);
   22995             :          }
   22996             : 
   22997             :          settings_store& disable_all_assignment_ops()
   22998             :          {
   22999             :             std::copy(details::assignment_ops_list,
   23000             :                       details::assignment_ops_list + details::assignment_ops_list_size,
   23001             :                       std::insert_iterator<disabled_entity_set_t>
   23002             :                          (disabled_assignment_set_, disabled_assignment_set_.begin()));
   23003             :             return (*this);
   23004             :          }
   23005             : 
   23006             :          settings_store& disable_all_inequality_ops()
   23007             :          {
   23008             :             std::copy(details::inequality_ops_list,
   23009             :                       details::inequality_ops_list + details::inequality_ops_list_size,
   23010             :                       std::insert_iterator<disabled_entity_set_t>
   23011             :                          (disabled_inequality_set_, disabled_inequality_set_.begin()));
   23012             :             return (*this);
   23013             :          }
   23014             : 
   23015             :          settings_store& disable_local_vardef()
   23016             :          {
   23017             :             disable_vardef_ = true;
   23018             :             return (*this);
   23019             :          }
   23020             : 
   23021             :          settings_store& disable_commutative_check()
   23022             :          {
   23023             :             enable_commutative_check_ = false;
   23024             :             return (*this);
   23025             :          }
   23026             : 
   23027             :          settings_store& disable_strength_reduction()
   23028             :          {
   23029             :             enable_strength_reduction_ = false;
   23030             :             return (*this);
   23031             :          }
   23032             : 
   23033      480406 :          bool replacer_enabled           () const { return enable_replacer_;           }
   23034      489322 :          bool commutative_check_enabled  () const { return enable_commutative_check_;  }
   23035      477206 :          bool joiner_enabled             () const { return enable_joiner_;             }
   23036      583748 :          bool numeric_check_enabled      () const { return enable_numeric_check_;      }
   23037      106542 :          bool bracket_check_enabled      () const { return enable_bracket_check_;      }
   23038      106542 :          bool sequence_check_enabled     () const { return enable_sequence_check_;     }
   23039      597484 :          bool strength_reduction_enabled () const { return enable_strength_reduction_; }
   23040      106542 :          bool collect_variables_enabled  () const { return enable_collect_vars_;       }
   23041      106542 :          bool collect_functions_enabled  () const { return enable_collect_funcs_;      }
   23042      106542 :          bool collect_assignments_enabled() const { return enable_collect_assings_;    }
   23043       56410 :          bool vardef_disabled            () const { return disable_vardef_;            }
   23044        5208 :          bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }
   23045           1 :          bool zero_return_disabled       () const { return disable_zero_return_;       }
   23046             : 
   23047      530250 :          bool function_enabled(const std::string& function_name) const
   23048             :          {
   23049      530250 :             if (disabled_func_set_.empty())
   23050      524250 :                return true;
   23051             :             else
   23052        6000 :                return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
   23053             :          }
   23054             : 
   23055        9152 :          bool control_struct_enabled(const std::string& control_struct) const
   23056             :          {
   23057        9152 :             if (disabled_ctrl_set_.empty())
   23058        9152 :                return true;
   23059             :             else
   23060           0 :                return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
   23061             :          }
   23062             : 
   23063             :          bool logic_enabled(const std::string& logic_operation) const
   23064             :          {
   23065             :             if (disabled_logic_set_.empty())
   23066             :                return true;
   23067             :             else
   23068             :                return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
   23069             :          }
   23070             : 
   23071             :          bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
   23072             :          {
   23073             :             if (disabled_logic_set_.empty())
   23074             :                return true;
   23075             :             else
   23076             :                return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
   23077             :                                                             .find(arith_opr_to_string(arithmetic_operation));
   23078             :          }
   23079             : 
   23080       23195 :          bool assignment_enabled(const details::operator_type& assignment) const
   23081             :          {
   23082       23195 :             if (disabled_assignment_set_.empty())
   23083       23195 :                return true;
   23084             :             else
   23085           0 :                return disabled_assignment_set_.end() == disabled_assignment_set_
   23086           0 :                                                            .find(assign_opr_to_string(assignment));
   23087             :          }
   23088             : 
   23089             :          bool inequality_enabled(const details::operator_type& inequality) const
   23090             :          {
   23091             :             if (disabled_inequality_set_.empty())
   23092             :                return true;
   23093             :             else
   23094             :                return disabled_inequality_set_.end() == disabled_inequality_set_
   23095             :                                                            .find(inequality_opr_to_string(inequality));
   23096             :          }
   23097             : 
   23098             :          bool function_disabled(const std::string& function_name) const
   23099             :          {
   23100             :             if (disabled_func_set_.empty())
   23101             :                return false;
   23102             :             else
   23103             :                return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
   23104             :          }
   23105             : 
   23106             :          bool control_struct_disabled(const std::string& control_struct) const
   23107             :          {
   23108             :             if (disabled_ctrl_set_.empty())
   23109             :                return false;
   23110             :             else
   23111             :                return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
   23112             :          }
   23113             : 
   23114         728 :          bool logic_disabled(const std::string& logic_operation) const
   23115             :          {
   23116         728 :             if (disabled_logic_set_.empty())
   23117         728 :                return false;
   23118             :             else
   23119           0 :                return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
   23120             :          }
   23121             : 
   23122     2771581 :          bool assignment_disabled(const details::operator_type assignment_operation) const
   23123             :          {
   23124     2771581 :             if (disabled_assignment_set_.empty())
   23125     2771581 :                return false;
   23126             :             else
   23127           0 :                return disabled_assignment_set_.end() != disabled_assignment_set_
   23128           0 :                                                            .find(assign_opr_to_string(assignment_operation));
   23129             :          }
   23130             : 
   23131     2771581 :          bool logic_disabled(const details::operator_type logic_operation) const
   23132             :          {
   23133     2771581 :             if (disabled_logic_set_.empty())
   23134     2771581 :                return false;
   23135             :             else
   23136           0 :                return disabled_logic_set_.end() != disabled_logic_set_
   23137           0 :                                                            .find(logic_opr_to_string(logic_operation));
   23138             :          }
   23139             : 
   23140     2771581 :          bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
   23141             :          {
   23142     2771581 :             if (disabled_arithmetic_set_.empty())
   23143     2771581 :                return false;
   23144             :             else
   23145           0 :                return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
   23146           0 :                                                            .find(arith_opr_to_string(arithmetic_operation));
   23147             :          }
   23148             : 
   23149     2771581 :          bool inequality_disabled(const details::operator_type& inequality) const
   23150             :          {
   23151     2771581 :             if (disabled_inequality_set_.empty())
   23152     2771581 :                return false;
   23153             :             else
   23154           0 :                return disabled_inequality_set_.end() != disabled_inequality_set_
   23155           0 :                                                            .find(inequality_opr_to_string(inequality));
   23156             :          }
   23157             : 
   23158        3200 :          settings_store& disable_base_function(const settings_base_funcs bf)
   23159             :          {
   23160        3200 :             if (
   23161        3200 :                  (e_bf_unknown != bf) &&
   23162             :                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
   23163             :                )
   23164             :             {
   23165        3200 :                disabled_func_set_.insert(details::base_function_list[bf - 1]);
   23166             :             }
   23167             : 
   23168        3200 :             return (*this);
   23169             :          }
   23170             : 
   23171             :          settings_store& disable_control_structure(const settings_control_structs ctrl_struct)
   23172             :          {
   23173             :             if (
   23174             :                  (e_ctrl_unknown != ctrl_struct) &&
   23175             :                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
   23176             :                )
   23177             :             {
   23178             :                disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
   23179             :             }
   23180             : 
   23181             :             return (*this);
   23182             :          }
   23183             : 
   23184             :          settings_store& disable_logic_operation(const settings_logic_opr logic)
   23185             :          {
   23186             :             if (
   23187             :                  (e_logic_unknown != logic) &&
   23188             :                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
   23189             :                )
   23190             :             {
   23191             :                disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
   23192             :             }
   23193             : 
   23194             :             return (*this);
   23195             :          }
   23196             : 
   23197             :          settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
   23198             :          {
   23199             :             if (
   23200             :                  (e_arith_unknown != arithmetic) &&
   23201             :                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
   23202             :                )
   23203             :             {
   23204             :                disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
   23205             :             }
   23206             : 
   23207             :             return (*this);
   23208             :          }
   23209             : 
   23210             :          settings_store& disable_assignment_operation(const settings_assignment_opr assignment)
   23211             :          {
   23212             :             if (
   23213             :                  (e_assign_unknown != assignment) &&
   23214             :                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
   23215             :                )
   23216             :             {
   23217             :                disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
   23218             :             }
   23219             : 
   23220             :             return (*this);
   23221             :          }
   23222             : 
   23223             :          settings_store& disable_inequality_operation(const settings_inequality_opr inequality)
   23224             :          {
   23225             :             if (
   23226             :                  (e_ineq_unknown != inequality) &&
   23227             :                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
   23228             :                )
   23229             :             {
   23230             :                disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
   23231             :             }
   23232             : 
   23233             :             return (*this);
   23234             :          }
   23235             : 
   23236             :          settings_store& enable_base_function(const settings_base_funcs bf)
   23237             :          {
   23238             :             if (
   23239             :                  (e_bf_unknown != bf) &&
   23240             :                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
   23241             :                )
   23242             :             {
   23243             :                const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
   23244             : 
   23245             :                if (disabled_func_set_.end() != itr)
   23246             :                {
   23247             :                   disabled_func_set_.erase(itr);
   23248             :                }
   23249             :             }
   23250             : 
   23251             :             return (*this);
   23252             :          }
   23253             : 
   23254             :          settings_store& enable_control_structure(const settings_control_structs ctrl_struct)
   23255             :          {
   23256             :             if (
   23257             :                  (e_ctrl_unknown != ctrl_struct) &&
   23258             :                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
   23259             :                )
   23260             :             {
   23261             :                const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
   23262             : 
   23263             :                if (disabled_ctrl_set_.end() != itr)
   23264             :                {
   23265             :                   disabled_ctrl_set_.erase(itr);
   23266             :                }
   23267             :             }
   23268             : 
   23269             :             return (*this);
   23270             :          }
   23271             : 
   23272             :          settings_store& enable_logic_operation(const settings_logic_opr logic)
   23273             :          {
   23274             :             if (
   23275             :                  (e_logic_unknown != logic) &&
   23276             :                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
   23277             :                )
   23278             :             {
   23279             :                const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
   23280             : 
   23281             :                if (disabled_logic_set_.end() != itr)
   23282             :                {
   23283             :                   disabled_logic_set_.erase(itr);
   23284             :                }
   23285             :             }
   23286             : 
   23287             :             return (*this);
   23288             :          }
   23289             : 
   23290             :          settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
   23291             :          {
   23292             :             if (
   23293             :                  (e_arith_unknown != arithmetic) &&
   23294             :                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
   23295             :                )
   23296             :             {
   23297             :                const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
   23298             : 
   23299             :                if (disabled_arithmetic_set_.end() != itr)
   23300             :                {
   23301             :                   disabled_arithmetic_set_.erase(itr);
   23302             :                }
   23303             :             }
   23304             : 
   23305             :             return (*this);
   23306             :          }
   23307             : 
   23308             :          settings_store& enable_assignment_operation(const settings_assignment_opr assignment)
   23309             :          {
   23310             :             if (
   23311             :                  (e_assign_unknown != assignment) &&
   23312             :                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
   23313             :                )
   23314             :             {
   23315             :                const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
   23316             : 
   23317             :                if (disabled_assignment_set_.end() != itr)
   23318             :                {
   23319             :                   disabled_assignment_set_.erase(itr);
   23320             :                }
   23321             :             }
   23322             : 
   23323             :             return (*this);
   23324             :          }
   23325             : 
   23326             :          settings_store& enable_inequality_operation(const settings_inequality_opr inequality)
   23327             :          {
   23328             :             if (
   23329             :                  (e_ineq_unknown != inequality) &&
   23330             :                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
   23331             :                )
   23332             :             {
   23333             :                const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
   23334             : 
   23335             :                if (disabled_inequality_set_.end() != itr)
   23336             :                {
   23337             :                   disabled_inequality_set_.erase(itr);
   23338             :                }
   23339             :             }
   23340             : 
   23341             :             return (*this);
   23342             :          }
   23343             : 
   23344             :          void set_max_stack_depth(const std::size_t max_stack_depth)
   23345             :          {
   23346             :             max_stack_depth_ = max_stack_depth;
   23347             :          }
   23348             : 
   23349             :          void set_max_node_depth(const std::size_t max_node_depth)
   23350             :          {
   23351             :             max_node_depth_ = max_node_depth;
   23352             :          }
   23353             : 
   23354             :          void set_max_local_vector_size(const std::size_t max_local_vector_size)
   23355             :          {
   23356             :             max_local_vector_size_ = max_local_vector_size;
   23357             :          }
   23358             : 
   23359             :          std::size_t max_stack_depth() const
   23360             :          {
   23361             :             return max_stack_depth_;
   23362             :          }
   23363             : 
   23364             :          std::size_t max_node_depth() const
   23365             :          {
   23366             :             return max_node_depth_;
   23367             :          }
   23368             : 
   23369       19777 :          std::size_t max_local_vector_size() const
   23370             :          {
   23371       19777 :             return max_local_vector_size_;
   23372             :          }
   23373             : 
   23374             :       private:
   23375             : 
   23376      106542 :          void load_compile_options(const std::size_t compile_options)
   23377             :          {
   23378      106542 :             enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;
   23379      106542 :             enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;
   23380      106542 :             enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;
   23381      106542 :             enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;
   23382      106542 :             enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;
   23383      106542 :             enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;
   23384      106542 :             enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;
   23385      106542 :             enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;
   23386      106542 :             enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;
   23387      106542 :             enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;
   23388      106542 :             disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;
   23389      106542 :             disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
   23390      106542 :             disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
   23391      106542 :          }
   23392             : 
   23393           0 :          std::string assign_opr_to_string(details::operator_type opr) const
   23394             :          {
   23395           0 :             switch (opr)
   23396             :             {
   23397           0 :                case details::e_assign : return ":=";
   23398           0 :                case details::e_addass : return "+=";
   23399           0 :                case details::e_subass : return "-=";
   23400           0 :                case details::e_mulass : return "*=";
   23401           0 :                case details::e_divass : return "/=";
   23402           0 :                case details::e_modass : return "%=";
   23403           0 :                default                : return ""  ;
   23404             :             }
   23405             :          }
   23406             : 
   23407           0 :          std::string arith_opr_to_string(details::operator_type opr) const
   23408             :          {
   23409           0 :             switch (opr)
   23410             :             {
   23411           0 :                case details::e_add : return "+";
   23412           0 :                case details::e_sub : return "-";
   23413           0 :                case details::e_mul : return "*";
   23414           0 :                case details::e_div : return "/";
   23415           0 :                case details::e_mod : return "%";
   23416           0 :                case details::e_pow : return "^";
   23417           0 :                default             : return "" ;
   23418             :             }
   23419             :          }
   23420             : 
   23421           0 :          std::string inequality_opr_to_string(details::operator_type opr) const
   23422             :          {
   23423           0 :             switch (opr)
   23424             :             {
   23425           0 :                case details::e_lt    : return "<" ;
   23426           0 :                case details::e_lte   : return "<=";
   23427           0 :                case details::e_eq    : return "==";
   23428           0 :                case details::e_equal : return "=" ;
   23429           0 :                case details::e_ne    : return "!=";
   23430           0 :                case details::e_nequal: return "<>";
   23431           0 :                case details::e_gte   : return ">=";
   23432           0 :                case details::e_gt    : return ">" ;
   23433           0 :                default               : return ""  ;
   23434             :             }
   23435             :          }
   23436             : 
   23437           0 :          std::string logic_opr_to_string(details::operator_type opr) const
   23438             :          {
   23439           0 :             switch (opr)
   23440             :             {
   23441           0 :                case details::e_and  : return "and" ;
   23442           0 :                case details::e_or   : return "or"  ;
   23443           0 :                case details::e_xor  : return "xor" ;
   23444           0 :                case details::e_nand : return "nand";
   23445           0 :                case details::e_nor  : return "nor" ;
   23446           0 :                case details::e_xnor : return "xnor";
   23447           0 :                case details::e_notl : return "not" ;
   23448           0 :                default              : return ""    ;
   23449             :             }
   23450             :          }
   23451             : 
   23452             :          bool enable_replacer_;
   23453             :          bool enable_joiner_;
   23454             :          bool enable_numeric_check_;
   23455             :          bool enable_bracket_check_;
   23456             :          bool enable_sequence_check_;
   23457             :          bool enable_commutative_check_;
   23458             :          bool enable_strength_reduction_;
   23459             :          bool enable_collect_vars_;
   23460             :          bool enable_collect_funcs_;
   23461             :          bool enable_collect_assings_;
   23462             :          bool disable_vardef_;
   23463             :          bool disable_rsrvd_sym_usr_;
   23464             :          bool disable_zero_return_;
   23465             : 
   23466             :          disabled_entity_set_t disabled_func_set_ ;
   23467             :          disabled_entity_set_t disabled_ctrl_set_ ;
   23468             :          disabled_entity_set_t disabled_logic_set_;
   23469             :          disabled_entity_set_t disabled_arithmetic_set_;
   23470             :          disabled_entity_set_t disabled_assignment_set_;
   23471             :          disabled_entity_set_t disabled_inequality_set_;
   23472             : 
   23473             :          std::size_t max_stack_depth_;
   23474             :          std::size_t max_node_depth_;
   23475             :          std::size_t max_local_vector_size_;
   23476             : 
   23477             :          friend class parser<T>;
   23478             :       };
   23479             : 
   23480             :       typedef settings_store settings_t;
   23481             : 
   23482      106542 :       explicit parser(const settings_t& settings = settings_t())
   23483      106542 :       : settings_(settings)
   23484      106542 :       , resolve_unknown_symbol_(false)
   23485      106542 :       , results_context_(0)
   23486      106542 :       , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0))
   23487             :         #ifdef _MSC_VER
   23488             :         #pragma warning(push)
   23489             :         #pragma warning (disable:4355)
   23490             :         #endif
   23491      106542 :       , sem_(*this)
   23492             :         #ifdef _MSC_VER
   23493             :         #pragma warning(pop)
   23494             :         #endif
   23495      106542 :       , operator_joiner_2_(2)
   23496      106542 :       , operator_joiner_3_(3)
   23497      106542 :       , loop_runtime_check_(0)
   23498      106542 :       , vector_access_runtime_check_(0)
   23499      426168 :       , compilation_check_ptr_(0)
   23500             :       {
   23501      106542 :          init_precompilation();
   23502             : 
   23503      106542 :          load_operations_map           (base_ops_map_     );
   23504      106542 :          load_unary_operations_map     (unary_op_map_     );
   23505      106542 :          load_binary_operations_map    (binary_op_map_    );
   23506      106542 :          load_inv_binary_operations_map(inv_binary_op_map_);
   23507      106542 :          load_sf3_map                  (sf3_map_          );
   23508      106542 :          load_sf4_map                  (sf4_map_          );
   23509             : 
   23510      106542 :          expression_generator_.init_synthesize_map();
   23511      106542 :          expression_generator_.set_parser(*this);
   23512      106542 :          expression_generator_.set_uom (unary_op_map_     );
   23513      106542 :          expression_generator_.set_bom (binary_op_map_    );
   23514      106542 :          expression_generator_.set_ibom(inv_binary_op_map_);
   23515      106542 :          expression_generator_.set_sf3m(sf3_map_          );
   23516      106542 :          expression_generator_.set_sf4m(sf4_map_          );
   23517      106542 :          expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
   23518      106542 :       }
   23519             : 
   23520      106542 :      ~parser()
   23521      106542 :       {}
   23522             : 
   23523      106542 :       inline void init_precompilation()
   23524             :       {
   23525      106542 :          dec_.collect_variables() =
   23526      106542 :             settings_.collect_variables_enabled();
   23527             : 
   23528      106542 :          dec_.collect_functions() =
   23529      106542 :             settings_.collect_functions_enabled();
   23530             : 
   23531      106542 :          dec_.collect_assignments() =
   23532      106542 :             settings_.collect_assignments_enabled();
   23533             : 
   23534      106542 :          if (settings_.replacer_enabled())
   23535             :          {
   23536      106542 :             symbol_replacer_.clear();
   23537      426168 :             symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
   23538      426168 :             symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
   23539      106542 :             helper_assembly_.token_modifier_list.clear();
   23540      106542 :             helper_assembly_.register_modifier(&symbol_replacer_);
   23541             :          }
   23542             : 
   23543      106542 :          if (settings_.commutative_check_enabled())
   23544             :          {
   23545     3409312 :             for (std::size_t i = 0; i < details::reserved_words_size; ++i)
   23546             :             {
   23547     3302771 :                commutative_inserter_.ignore_symbol(details::reserved_words[i]);
   23548             :             }
   23549             : 
   23550      106541 :             helper_assembly_.token_inserter_list.clear();
   23551      106541 :             helper_assembly_.register_inserter(&commutative_inserter_);
   23552             :          }
   23553             : 
   23554      106542 :          if (settings_.joiner_enabled())
   23555             :          {
   23556      106542 :             helper_assembly_.token_joiner_list.clear();
   23557      106542 :             helper_assembly_.register_joiner(&operator_joiner_2_);
   23558      106542 :             helper_assembly_.register_joiner(&operator_joiner_3_);
   23559             :          }
   23560             : 
   23561      106542 :          if (
   23562      106542 :               settings_.numeric_check_enabled () ||
   23563      106542 :               settings_.bracket_check_enabled () ||
   23564           0 :               settings_.sequence_check_enabled()
   23565             :             )
   23566             :          {
   23567      106542 :             helper_assembly_.token_scanner_list.clear();
   23568             : 
   23569      106542 :             if (settings_.numeric_check_enabled())
   23570             :             {
   23571      106542 :                helper_assembly_.register_scanner(&numeric_checker_);
   23572             :             }
   23573             : 
   23574      106542 :             if (settings_.bracket_check_enabled())
   23575             :             {
   23576      106542 :                helper_assembly_.register_scanner(&bracket_checker_);
   23577             :             }
   23578             : 
   23579      106542 :             if (settings_.sequence_check_enabled())
   23580             :             {
   23581      106542 :                helper_assembly_.register_scanner(&sequence_validator_      );
   23582      106542 :                helper_assembly_.register_scanner(&sequence_validator_3tkns_);
   23583             :             }
   23584             :          }
   23585      106542 :       }
   23586             : 
   23587      371453 :       inline bool compile(const std::string& expression_string, expression<T>& expr)
   23588             :       {
   23589      371453 :          state_               .reset();
   23590      371453 :          error_list_          .clear();
   23591      371453 :          brkcnt_list_         .clear();
   23592      371453 :          synthesis_error_     .clear();
   23593      371453 :          immutable_memory_map_.reset();
   23594      371453 :          immutable_symtok_map_.clear();
   23595      371453 :          current_state_stack_ .clear();
   23596      371453 :          sem_                 .cleanup();
   23597             : 
   23598      371453 :          return_cleanup();
   23599             : 
   23600      371453 :          expression_generator_.set_allocator(node_allocator_);
   23601             : 
   23602      371453 :          if (expression_string.empty())
   23603             :          {
   23604           0 :             set_error(make_error(
   23605             :                parser_error::e_syntax,
   23606             :                "ERR001 - Empty expression!",
   23607             :                exprtk_error_location));
   23608             : 
   23609           0 :             return false;
   23610             :          }
   23611             : 
   23612      371453 :          if (!init(expression_string))
   23613             :          {
   23614         788 :             process_lexer_errors();
   23615         788 :             return false;
   23616             :          }
   23617             : 
   23618      370665 :          if (lexer().empty())
   23619             :          {
   23620           3 :             set_error(make_error(
   23621             :                parser_error::e_syntax,
   23622             :                "ERR002 - Empty expression!",
   23623             :                exprtk_error_location));
   23624             : 
   23625           1 :             return false;
   23626             :          }
   23627             : 
   23628      370664 :          if (halt_compilation_check())
   23629             :          {
   23630           0 :             return false;
   23631             :          }
   23632             : 
   23633      370664 :          if (!run_assemblies())
   23634             :          {
   23635        9739 :             return false;
   23636             :          }
   23637             : 
   23638      360925 :          if (halt_compilation_check())
   23639             :          {
   23640           0 :             return false;
   23641             :          }
   23642             : 
   23643      360925 :          symtab_store_.symtab_list_ = expr.get_symbol_table_list();
   23644      360925 :          dec_.clear();
   23645             : 
   23646      360925 :          lexer().begin();
   23647             : 
   23648      360925 :          next_token();
   23649             : 
   23650      360925 :          expression_node_ptr e = parse_corpus();
   23651             : 
   23652      360925 :          if ((0 != e) && (token_t::e_eof == current_token().type))
   23653             :          {
   23654      349926 :             bool* retinvk_ptr = 0;
   23655             : 
   23656      349926 :             if (state_.return_stmt_present)
   23657             :             {
   23658         111 :                dec_.return_present_ = true;
   23659             : 
   23660         111 :                e = expression_generator_
   23661         111 :                      .return_envelope(e, results_context_, retinvk_ptr);
   23662             :             }
   23663             : 
   23664      349926 :             expr.set_expression(e);
   23665      349926 :             expr.set_retinvk(retinvk_ptr);
   23666             : 
   23667      349926 :             register_local_vars(expr);
   23668      349926 :             register_return_results(expr);
   23669             : 
   23670      349926 :             return !(!expr);
   23671             :          }
   23672             :          else
   23673             :          {
   23674       10999 :             if (error_list_.empty())
   23675             :             {
   23676           0 :                set_error(make_error(
   23677             :                   parser_error::e_syntax,
   23678           0 :                   current_token(),
   23679             :                   "ERR003 - Invalid expression encountered",
   23680             :                   exprtk_error_location));
   23681             :             }
   23682             : 
   23683       10999 :             if ((0 != e) && branch_deletable(e))
   23684             :             {
   23685           0 :                destroy_node(e);
   23686             :             }
   23687             : 
   23688       10999 :             dec_.clear    ();
   23689       10999 :             sem_.cleanup  ();
   23690       10999 :             return_cleanup();
   23691             : 
   23692       10999 :             return false;
   23693             :          }
   23694             :       }
   23695             : 
   23696             :       inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
   23697             :       {
   23698             :          expression_t expression;
   23699             :          expression.register_symbol_table(symtab);
   23700             :          compile(expression_string,expression);
   23701             :          return expression;
   23702             :       }
   23703             : 
   23704         788 :       void process_lexer_errors()
   23705             :       {
   23706       78215 :          for (std::size_t i = 0; i < lexer().size(); ++i)
   23707             :          {
   23708       77427 :             if (lexer()[i].is_error())
   23709             :             {
   23710         788 :                std::string diagnostic = "ERR004 - ";
   23711             : 
   23712         788 :                switch (lexer()[i].type)
   23713             :                {
   23714         491 :                   case lexer::token::e_error      : diagnostic += "General token error";
   23715         491 :                                                     break;
   23716             : 
   23717           0 :                   case lexer::token::e_err_symbol : diagnostic += "Symbol error";
   23718           0 :                                                     break;
   23719             : 
   23720          60 :                   case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
   23721          60 :                                                     break;
   23722             : 
   23723         237 :                   case lexer::token::e_err_string : diagnostic += "Invalid string token";
   23724         237 :                                                     break;
   23725             : 
   23726           0 :                   case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
   23727           0 :                                                     break;
   23728             : 
   23729           0 :                   default                         : diagnostic += "Unknown compiler error";
   23730             :                }
   23731             : 
   23732        2364 :                set_error(make_error(
   23733             :                   parser_error::e_lexer,
   23734         788 :                   lexer()[i],
   23735         788 :                   diagnostic + ": " + lexer()[i].value,
   23736             :                   exprtk_error_location));
   23737         788 :             }
   23738             :          }
   23739         788 :       }
   23740             : 
   23741      370664 :       inline bool run_assemblies()
   23742             :       {
   23743      370664 :          if (settings_.commutative_check_enabled())
   23744             :          {
   23745      370654 :             helper_assembly_.run_inserters(lexer());
   23746             :          }
   23747             : 
   23748      370664 :          if (settings_.joiner_enabled())
   23749             :          {
   23750      370664 :             helper_assembly_.run_joiners(lexer());
   23751             :          }
   23752             : 
   23753      370664 :          if (settings_.replacer_enabled())
   23754             :          {
   23755      370664 :             helper_assembly_.run_modifiers(lexer());
   23756             :          }
   23757             : 
   23758      370664 :          if (
   23759      370664 :               settings_.numeric_check_enabled () ||
   23760      370664 :               settings_.bracket_check_enabled () ||
   23761           0 :               settings_.sequence_check_enabled()
   23762             :             )
   23763             :          {
   23764      370664 :             if (!helper_assembly_.run_scanners(lexer()))
   23765             :             {
   23766        9739 :                if (helper_assembly_.error_token_scanner)
   23767             :                {
   23768        9739 :                   lexer::helper::bracket_checker*            bracket_checker_ptr     = 0;
   23769        9739 :                   lexer::helper::numeric_checker<T>*         numeric_checker_ptr     = 0;
   23770        9739 :                   lexer::helper::sequence_validator*         sequence_validator_ptr  = 0;
   23771        9739 :                   lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
   23772             : 
   23773        9739 :                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
   23774             :                   {
   23775       26682 :                      set_error(make_error(
   23776             :                         parser_error::e_token,
   23777             :                         bracket_checker_ptr->error_token(),
   23778       17788 :                         "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
   23779             :                         exprtk_error_location));
   23780             :                   }
   23781         845 :                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner)))
   23782             :                   {
   23783          28 :                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
   23784             :                      {
   23785          14 :                         lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
   23786             : 
   23787          14 :                         set_error(make_error(
   23788             :                            parser_error::e_token,
   23789             :                            error_token,
   23790             :                            "ERR006 - Invalid numeric token: '" + error_token.value + "'",
   23791             :                            exprtk_error_location));
   23792             :                      }
   23793             : 
   23794          14 :                      if (numeric_checker_ptr->error_count())
   23795             :                      {
   23796          14 :                         numeric_checker_ptr->clear_errors();
   23797             :                      }
   23798             :                   }
   23799         831 :                   else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
   23800             :                   {
   23801        1831 :                      for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
   23802             :                      {
   23803        1002 :                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
   23804             : 
   23805        1002 :                         set_error(make_error(
   23806             :                            parser_error::e_token,
   23807             :                            error_token.first,
   23808             :                            "ERR007 - Invalid token sequence: '" +
   23809             :                            error_token.first.value  + "' and '" +
   23810             :                            error_token.second.value + "'",
   23811             :                            exprtk_error_location));
   23812             :                      }
   23813             : 
   23814         829 :                      if (sequence_validator_ptr->error_count())
   23815             :                      {
   23816         829 :                         sequence_validator_ptr->clear_errors();
   23817             :                      }
   23818             :                   }
   23819           2 :                   else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
   23820             :                   {
   23821           6 :                      for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
   23822             :                      {
   23823           4 :                         std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
   23824             : 
   23825           4 :                         set_error(make_error(
   23826             :                            parser_error::e_token,
   23827             :                            error_token.first,
   23828             :                            "ERR008 - Invalid token sequence: '" +
   23829             :                            error_token.first.value  + "' and '" +
   23830             :                            error_token.second.value + "'",
   23831             :                            exprtk_error_location));
   23832             :                      }
   23833             : 
   23834           2 :                      if (sequence_validator3_ptr->error_count())
   23835             :                      {
   23836           2 :                         sequence_validator3_ptr->clear_errors();
   23837             :                      }
   23838             :                   }
   23839             :                }
   23840             : 
   23841        9739 :                return false;
   23842             :             }
   23843             :          }
   23844             : 
   23845      360925 :          return true;
   23846             :       }
   23847             : 
   23848        1600 :       inline settings_store& settings()
   23849             :       {
   23850        1600 :          return settings_;
   23851             :       }
   23852             : 
   23853           0 :       inline parser_error::type get_error(const std::size_t& index) const
   23854             :       {
   23855           0 :          if (index < error_list_.size())
   23856           0 :             return error_list_[index];
   23857             :          else
   23858           0 :             throw std::invalid_argument("parser::get_error() - Invalid error index specified");
   23859             :       }
   23860             : 
   23861           0 :       inline std::string error() const
   23862             :       {
   23863           0 :          if (!error_list_.empty())
   23864             :          {
   23865           0 :             return error_list_[0].diagnostic;
   23866             :          }
   23867             :          else
   23868           0 :             return std::string("No Error");
   23869             :       }
   23870             : 
   23871           0 :       inline std::size_t error_count() const
   23872             :       {
   23873           0 :          return error_list_.size();
   23874             :       }
   23875             : 
   23876        1495 :       inline dependent_entity_collector& dec()
   23877             :       {
   23878        1495 :          return dec_;
   23879             :       }
   23880             : 
   23881        3200 :       inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
   23882             :       {
   23883        3200 :          if (!settings_.replacer_enabled())
   23884           0 :             return false;
   23885        3200 :          else if (details::is_reserved_word(old_symbol))
   23886           0 :             return false;
   23887             :          else
   23888        3200 :             return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
   23889             :       }
   23890             : 
   23891             :       inline bool remove_replace_symbol(const std::string& symbol)
   23892             :       {
   23893             :          if (!settings_.replacer_enabled())
   23894             :             return false;
   23895             :          else if (details::is_reserved_word(symbol))
   23896             :             return false;
   23897             :          else
   23898             :             return symbol_replacer_.remove(symbol);
   23899             :       }
   23900             : 
   23901         204 :       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
   23902             :       {
   23903         204 :          resolve_unknown_symbol_ = true;
   23904             : 
   23905         204 :          if (usr)
   23906         202 :             unknown_symbol_resolver_ = usr;
   23907             :          else
   23908           2 :             unknown_symbol_resolver_ = &default_usr_;
   23909         204 :       }
   23910             : 
   23911             :       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
   23912             :       {
   23913             :          enable_unknown_symbol_resolver(&usr);
   23914             :       }
   23915             : 
   23916             :       inline void disable_unknown_symbol_resolver()
   23917             :       {
   23918             :          resolve_unknown_symbol_  = false;
   23919             :          unknown_symbol_resolver_ = &default_usr_;
   23920             :       }
   23921             : 
   23922             :       inline void register_loop_runtime_check(loop_runtime_check& lrtchk)
   23923             :       {
   23924             :          loop_runtime_check_ = &lrtchk;
   23925             :       }
   23926             : 
   23927          70 :       inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk)
   23928             :       {
   23929          70 :          vector_access_runtime_check_ = &vartchk;
   23930          70 :       }
   23931             : 
   23932             :       inline void register_compilation_timeout_check(compilation_check& compchk)
   23933             :       {
   23934             :          compilation_check_ptr_ = &compchk;
   23935             :       }
   23936             : 
   23937             :       inline void clear_loop_runtime_check()
   23938             :       {
   23939             :          loop_runtime_check_ = loop_runtime_check_ptr(0);
   23940             :       }
   23941             : 
   23942             :       inline void clear_vector_access_runtime_check()
   23943             :       {
   23944             :          vector_access_runtime_check_ = vector_access_runtime_check_ptr(0);
   23945             :       }
   23946             : 
   23947             :       inline void clear_compilation_timeout_check()
   23948             :       {
   23949             :          compilation_check_ptr_ = compilation_check_ptr(0);
   23950             :       }
   23951             : 
   23952             :    private:
   23953             : 
   23954     2449993 :       inline bool valid_base_operation(const std::string& symbol) const
   23955             :       {
   23956     2449993 :          const std::size_t length = symbol.size();
   23957             : 
   23958     2449993 :          if (
   23959      513175 :               (length < 3) || // Shortest base op symbol length
   23960             :               (length > 9)    // Longest base op symbol length
   23961             :             )
   23962     1938168 :             return false;
   23963             :          else
   23964     1021250 :             return settings_.function_enabled(symbol) &&
   23965     1021250 :                    (base_ops_map_.end() != base_ops_map_.find(symbol));
   23966             :       }
   23967             : 
   23968     2469123 :       inline bool valid_vararg_operation(const std::string& symbol) const
   23969             :       {
   23970     2469125 :          static const std::string s_sum     = "sum" ;
   23971     2469125 :          static const std::string s_mul     = "mul" ;
   23972     2469125 :          static const std::string s_avg     = "avg" ;
   23973     2469125 :          static const std::string s_min     = "min" ;
   23974     2469125 :          static const std::string s_max     = "max" ;
   23975     2469125 :          static const std::string s_mand    = "mand";
   23976     2469125 :          static const std::string s_mor     = "mor" ;
   23977     2469125 :          static const std::string s_multi   = "~"   ;
   23978     2469125 :          static const std::string s_mswitch = "[*]" ;
   23979             : 
   23980             :          return
   23981             :                (
   23982     4936567 :                   details::imatch(symbol,s_sum    ) ||
   23983     4934694 :                   details::imatch(symbol,s_mul    ) ||
   23984     4934187 :                   details::imatch(symbol,s_avg    ) ||
   23985     4929507 :                   details::imatch(symbol,s_min    ) ||
   23986     4924796 :                   details::imatch(symbol,s_max    ) ||
   23987     4924196 :                   details::imatch(symbol,s_mand   ) ||
   23988     4923683 :                   details::imatch(symbol,s_mor    ) ||
   23989     4912624 :                   details::imatch(symbol,s_multi  ) ||
   23990     2450911 :                   details::imatch(symbol,s_mswitch)
   23991     4938246 :                ) &&
   23992     2487525 :                settings_.function_enabled(symbol);
   23993             :       }
   23994             : 
   23995     2771581 :       bool is_invalid_logic_operation(const details::operator_type operation) const
   23996             :       {
   23997     2771581 :          return settings_.logic_disabled(operation);
   23998             :       }
   23999             : 
   24000     2771581 :       bool is_invalid_arithmetic_operation(const details::operator_type operation) const
   24001             :       {
   24002     2771581 :          return settings_.arithmetic_disabled(operation);
   24003             :       }
   24004             : 
   24005     2771581 :       bool is_invalid_assignment_operation(const details::operator_type operation) const
   24006             :       {
   24007     2771581 :          return settings_.assignment_disabled(operation);
   24008             :       }
   24009             : 
   24010     2771581 :       bool is_invalid_inequality_operation(const details::operator_type operation) const
   24011             :       {
   24012     2771581 :          return settings_.inequality_disabled(operation);
   24013             :       }
   24014             : 
   24015             :       #ifdef exprtk_enable_debugging
   24016             :       inline void next_token()
   24017             :       {
   24018             :          const std::string ct_str = current_token().value;
   24019             :          const std::size_t ct_pos = current_token().position;
   24020             :          parser_helper::next_token();
   24021             :          const std::string depth(2 * state_.scope_depth,' ');
   24022             :          exprtk_debug(("%s"
   24023             :                        "prev[%s | %04d] --> curr[%s | %04d]  stack_level: %3d\n",
   24024             :                        depth.c_str(),
   24025             :                        ct_str.c_str(),
   24026             :                        static_cast<unsigned int>(ct_pos),
   24027             :                        current_token().value.c_str(),
   24028             :                        static_cast<unsigned int>(current_token().position),
   24029             :                        static_cast<unsigned int>(state_.stack_depth)));
   24030             :       }
   24031             :       #endif
   24032             : 
   24033      360925 :       inline expression_node_ptr parse_corpus()
   24034             :       {
   24035      360925 :          std::vector<expression_node_ptr> arg_list;
   24036      360925 :          std::vector<bool> side_effect_list;
   24037             : 
   24038      360925 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   24039             : 
   24040      360925 :          lexer::token begin_token;
   24041      360925 :          lexer::token end_token;
   24042             : 
   24043       55088 :          for ( ; ; )
   24044             :          {
   24045      416013 :             state_.side_effect_present = false;
   24046             : 
   24047      416013 :             begin_token = current_token();
   24048             : 
   24049      416013 :             expression_node_ptr arg = parse_expression();
   24050             : 
   24051      416013 :             if (0 == arg)
   24052             :             {
   24053       10999 :                if (error_list_.empty())
   24054             :                {
   24055           0 :                   set_error(make_error(
   24056             :                      parser_error::e_syntax,
   24057           0 :                      current_token(),
   24058             :                      "ERR009 - Invalid expression encountered",
   24059             :                      exprtk_error_location));
   24060             :                }
   24061             : 
   24062       10999 :                return error_node();
   24063             :             }
   24064             :             else
   24065             :             {
   24066      405014 :                arg_list.push_back(arg);
   24067             : 
   24068      405014 :                side_effect_list.push_back(state_.side_effect_present);
   24069             : 
   24070      405014 :                end_token = current_token();
   24071             : 
   24072      405014 :                const std::string sub_expr = construct_subexpr(begin_token, end_token);
   24073             : 
   24074             :                exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
   24075             :                              static_cast<int>(arg_list.size() - 1),
   24076             :                              sub_expr.c_str()));
   24077             : 
   24078             :                exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
   24079             :                              static_cast<int>(arg_list.size() - 1),
   24080             :                              state_.side_effect_present ? "true" : "false"));
   24081             : 
   24082             :                exprtk_debug(("-------------------------------------------------\n"));
   24083      405014 :             }
   24084             : 
   24085      405014 :             if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
   24086             :             {
   24087      391824 :                if (lexer().finished())
   24088      349926 :                   break;
   24089             :                else
   24090       41898 :                   next_token();
   24091             :             }
   24092             :          }
   24093             : 
   24094      349926 :          if (
   24095      699852 :               !arg_list.empty() &&
   24096      349926 :               is_return_node(arg_list.back())
   24097             :             )
   24098             :          {
   24099           2 :             dec_.final_stmt_return_ = true;
   24100             :          }
   24101             : 
   24102      349926 :          const expression_node_ptr result = simplify(arg_list,side_effect_list);
   24103             : 
   24104      349926 :          sdd.delete_ptr = (0 == result);
   24105             : 
   24106      349926 :          return result;
   24107      360925 :       }
   24108             : 
   24109      405014 :       std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
   24110             :       {
   24111      405014 :          std::string result = lexer().substr(begin_token.position,end_token.position);
   24112             : 
   24113    29802571 :          for (std::size_t i = 0; i < result.size(); ++i)
   24114             :          {
   24115    29397557 :             if (details::is_whitespace(result[i])) result[i] = ' ';
   24116             :          }
   24117             : 
   24118      405014 :          return result;
   24119           0 :       }
   24120             : 
   24121             :       static const precedence_level default_precedence = e_level00;
   24122             : 
   24123             :       struct state_t
   24124             :       {
   24125     3971976 :          inline void set(const precedence_level& l,
   24126             :                          const precedence_level& r,
   24127             :                          const details::operator_type& o,
   24128             :                          const token_t tkn = token_t())
   24129             :          {
   24130     3971976 :             left  = l;
   24131     3971976 :             right = r;
   24132     3971976 :             operation = o;
   24133     3971976 :             token = tkn;
   24134     3971976 :          }
   24135             : 
   24136     8699449 :          inline void reset()
   24137             :          {
   24138     8699449 :             left      = e_level00;
   24139     8699449 :             right     = e_level00;
   24140     8699449 :             operation = details::e_default;
   24141     8699449 :          }
   24142             : 
   24143             :          precedence_level left;
   24144             :          precedence_level right;
   24145             :          details::operator_type operation;
   24146             :          token_t token;
   24147             :       };
   24148             : 
   24149     2657583 :       inline void push_current_state(const state_t current_state)
   24150             :       {
   24151     2657583 :          current_state_stack_.push_back(current_state);
   24152     2657583 :       }
   24153             : 
   24154     2657583 :       inline void pop_current_state()
   24155             :       {
   24156     2657583 :          if (!current_state_stack_.empty())
   24157             :          {
   24158     2657583 :             current_state_stack_.pop_back();
   24159             :          }
   24160     2657583 :       }
   24161             : 
   24162           3 :       inline state_t current_state() const
   24163             :       {
   24164           3 :          return (!current_state_stack_.empty()) ?
   24165           3 :                 current_state_stack_.back()     :
   24166           3 :                 state_t();
   24167             :       }
   24168             : 
   24169     6927025 :       inline bool halt_compilation_check()
   24170             :       {
   24171     6927025 :          compilation_check::compilation_context context;
   24172             : 
   24173     6927025 :          if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context))
   24174             :          {
   24175           0 :             const std::string error_message =
   24176           0 :                !context.error_message.empty() ? " Details: " + context.error_message : "";
   24177             : 
   24178           0 :             set_error(make_error(
   24179             :                parser_error::e_parser,
   24180           0 :                token_t(),
   24181             :                "ERR010 - Internal compilation check failed." + error_message,
   24182             :                exprtk_error_location));
   24183             : 
   24184           0 :             return true;
   24185           0 :          }
   24186             : 
   24187     6927025 :          return false;
   24188     6927025 :       }
   24189             : 
   24190     6195436 :       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
   24191             :       {
   24192     6195436 :          if (halt_compilation_check())
   24193             :          {
   24194           0 :             return error_node();
   24195             :          }
   24196             : 
   24197     6195436 :          stack_limit_handler slh(*this);
   24198             : 
   24199     6195436 :          if (!slh)
   24200             :          {
   24201           0 :             return error_node();
   24202             :          }
   24203             : 
   24204     6195436 :          expression_node_ptr expression = parse_branch(precedence);
   24205             : 
   24206     6195436 :          if (0 == expression)
   24207             :          {
   24208      153527 :             return error_node();
   24209             :          }
   24210             : 
   24211     6041909 :          bool break_loop = false;
   24212             : 
   24213     6041909 :          state_t current_state;
   24214             : 
   24215     5429121 :          for ( ; ; )
   24216             :          {
   24217     8699449 :             current_state.reset();
   24218             : 
   24219     8699449 :             switch (current_token().type)
   24220             :             {
   24221       11033 :                case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break;
   24222        9905 :                case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break;
   24223        1038 :                case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break;
   24224         330 :                case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break;
   24225         331 :                case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break;
   24226           0 :                case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break;
   24227        2728 :                case token_t::e_swap   : current_state.set(e_level00, e_level00, details::e_swap  , current_token()); break;
   24228        7305 :                case token_t::e_lt     : current_state.set(e_level05, e_level06, details::e_lt    , current_token()); break;
   24229        2256 :                case token_t::e_lte    : current_state.set(e_level05, e_level06, details::e_lte   , current_token()); break;
   24230       67805 :                case token_t::e_eq     : current_state.set(e_level05, e_level06, details::e_eq    , current_token()); break;
   24231        3045 :                case token_t::e_ne     : current_state.set(e_level05, e_level06, details::e_ne    , current_token()); break;
   24232         690 :                case token_t::e_gte    : current_state.set(e_level05, e_level06, details::e_gte   , current_token()); break;
   24233        7191 :                case token_t::e_gt     : current_state.set(e_level05, e_level06, details::e_gt    , current_token()); break;
   24234     1412602 :                case token_t::e_add    : current_state.set(e_level07, e_level08, details::e_add   , current_token()); break;
   24235      811914 :                case token_t::e_sub    : current_state.set(e_level07, e_level08, details::e_sub   , current_token()); break;
   24236      638532 :                case token_t::e_div    : current_state.set(e_level10, e_level11, details::e_div   , current_token()); break;
   24237      879356 :                case token_t::e_mul    : current_state.set(e_level10, e_level11, details::e_mul   , current_token()); break;
   24238         328 :                case token_t::e_mod    : current_state.set(e_level10, e_level11, details::e_mod   , current_token()); break;
   24239       94163 :                case token_t::e_pow    : current_state.set(e_level12, e_level12, details::e_pow   , current_token()); break;
   24240     4748897 :                default                :
   24241     4748897 :                   if (token_t::e_symbol == current_token().type)
   24242             :                   {
   24243       37429 :                      static const std::string s_and   = "and"  ;
   24244       37429 :                      static const std::string s_nand  = "nand" ;
   24245       37429 :                      static const std::string s_or    = "or"   ;
   24246       37429 :                      static const std::string s_nor   = "nor"  ;
   24247       37429 :                      static const std::string s_xor   = "xor"  ;
   24248       37429 :                      static const std::string s_xnor  = "xnor" ;
   24249       37429 :                      static const std::string s_in    = "in"   ;
   24250       37429 :                      static const std::string s_like  = "like" ;
   24251       37429 :                      static const std::string s_ilike = "ilike";
   24252       37429 :                      static const std::string s_and1  = "&"    ;
   24253       37429 :                      static const std::string s_or1   = "|"    ;
   24254       37429 :                      static const std::string s_not   = "not"  ;
   24255             : 
   24256       37427 :                      if (details::imatch(current_token().value,s_and))
   24257             :                      {
   24258       11555 :                         current_state.set(e_level03, e_level04, details::e_and, current_token());
   24259       11555 :                         break;
   24260             :                      }
   24261       25872 :                      else if (details::imatch(current_token().value,s_and1))
   24262             :                      {
   24263             :                         #ifndef exprtk_disable_sc_andor
   24264         463 :                         current_state.set(e_level03, e_level04, details::e_scand, current_token());
   24265             :                         #else
   24266             :                         current_state.set(e_level03, e_level04, details::e_and, current_token());
   24267             :                         #endif
   24268         463 :                         break;
   24269             :                      }
   24270       25409 :                      else if (details::imatch(current_token().value,s_nand))
   24271             :                      {
   24272         604 :                         current_state.set(e_level03, e_level04, details::e_nand, current_token());
   24273         604 :                         break;
   24274             :                      }
   24275       24805 :                      else if (details::imatch(current_token().value,s_or))
   24276             :                      {
   24277         723 :                         current_state.set(e_level01, e_level02, details::e_or, current_token());
   24278         723 :                         break;
   24279             :                      }
   24280       24082 :                      else if (details::imatch(current_token().value,s_or1))
   24281             :                      {
   24282             :                         #ifndef exprtk_disable_sc_andor
   24283         420 :                         current_state.set(e_level01, e_level02, details::e_scor, current_token());
   24284             :                         #else
   24285             :                         current_state.set(e_level01, e_level02, details::e_or, current_token());
   24286             :                         #endif
   24287         420 :                         break;
   24288             :                      }
   24289       23662 :                      else if (details::imatch(current_token().value,s_nor))
   24290             :                      {
   24291         604 :                         current_state.set(e_level01, e_level02, details::e_nor, current_token());
   24292         604 :                         break;
   24293             :                      }
   24294       23058 :                      else if (details::imatch(current_token().value,s_xor))
   24295             :                      {
   24296         265 :                         current_state.set(e_level01, e_level02, details::e_xor, current_token());
   24297         265 :                         break;
   24298             :                      }
   24299       22793 :                      else if (details::imatch(current_token().value,s_xnor))
   24300             :                      {
   24301          80 :                         current_state.set(e_level01, e_level02, details::e_xnor, current_token());
   24302          80 :                         break;
   24303             :                      }
   24304       22713 :                      else if (details::imatch(current_token().value,s_in))
   24305             :                      {
   24306         780 :                         current_state.set(e_level04, e_level04, details::e_in, current_token());
   24307         780 :                         break;
   24308             :                      }
   24309       21933 :                      else if (details::imatch(current_token().value,s_like))
   24310             :                      {
   24311        2965 :                         current_state.set(e_level04, e_level04, details::e_like, current_token());
   24312        2965 :                         break;
   24313             :                      }
   24314       18968 :                      else if (details::imatch(current_token().value,s_ilike))
   24315             :                      {
   24316        2965 :                         current_state.set(e_level04, e_level04, details::e_ilike, current_token());
   24317        2965 :                         break;
   24318             :                      }
   24319       16003 :                      else if (details::imatch(current_token().value,s_not))
   24320             :                      {
   24321           0 :                         break;
   24322             :                      }
   24323             :                   }
   24324             : 
   24325     4727473 :                   break_loop = true;
   24326             :             }
   24327             : 
   24328     8699449 :             if (break_loop)
   24329             :             {
   24330     4727473 :                parse_pending_string_rangesize(expression);
   24331     4727473 :                break;
   24332             :             }
   24333     3971976 :             else if (current_state.left < precedence)
   24334     1200395 :                break;
   24335             : 
   24336     2771581 :             const lexer::token prev_token = current_token();
   24337             : 
   24338     2771581 :             next_token();
   24339             : 
   24340     2771581 :             expression_node_ptr right_branch   = error_node();
   24341     2771581 :             expression_node_ptr new_expression = error_node();
   24342             : 
   24343     2771581 :             if (is_invalid_logic_operation(current_state.operation))
   24344             :             {
   24345           0 :                free_node(node_allocator_,expression);
   24346             : 
   24347           0 :                set_error(make_error(
   24348             :                   parser_error::e_syntax,
   24349             :                   prev_token,
   24350             :                   "ERR011 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
   24351             :                   exprtk_error_location));
   24352             : 
   24353           0 :                return error_node();
   24354             :             }
   24355     2771581 :             else if (is_invalid_arithmetic_operation(current_state.operation))
   24356             :             {
   24357           0 :                free_node(node_allocator_,expression);
   24358             : 
   24359           0 :                set_error(make_error(
   24360             :                   parser_error::e_syntax,
   24361             :                   prev_token,
   24362             :                   "ERR012 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
   24363             :                   exprtk_error_location));
   24364             : 
   24365           0 :                return error_node();
   24366             :             }
   24367     2771581 :             else if (is_invalid_inequality_operation(current_state.operation))
   24368             :             {
   24369           0 :                free_node(node_allocator_,expression);
   24370             : 
   24371           0 :                set_error(make_error(
   24372             :                   parser_error::e_syntax,
   24373             :                   prev_token,
   24374             :                   "ERR013 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
   24375             :                   exprtk_error_location));
   24376             : 
   24377           0 :                return error_node();
   24378             :             }
   24379     2771581 :             else if (is_invalid_assignment_operation(current_state.operation))
   24380             :             {
   24381           0 :                free_node(node_allocator_,expression);
   24382             : 
   24383           0 :                set_error(make_error(
   24384             :                   parser_error::e_syntax,
   24385             :                   prev_token,
   24386             :                   "ERR014 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
   24387             :                   exprtk_error_location));
   24388             : 
   24389           0 :                return error_node();
   24390             :             }
   24391             : 
   24392     2771581 :             if (0 != (right_branch = parse_expression(current_state.right)))
   24393             :             {
   24394     2657583 :                if (
   24395     5315166 :                     details::is_return_node(expression  ) ||
   24396     2657583 :                     details::is_return_node(right_branch)
   24397             :                   )
   24398             :                {
   24399           0 :                   free_node(node_allocator_, expression  );
   24400           0 :                   free_node(node_allocator_, right_branch);
   24401             : 
   24402           0 :                   set_error(make_error(
   24403             :                      parser_error::e_syntax,
   24404             :                      prev_token,
   24405             :                      "ERR015 - Return statements cannot be part of sub-expressions",
   24406             :                      exprtk_error_location));
   24407             : 
   24408           0 :                   return error_node();
   24409             :                }
   24410             : 
   24411     2657583 :                push_current_state(current_state);
   24412             : 
   24413             :                new_expression = expression_generator_
   24414     2657583 :                                   (
   24415             :                                     current_state.operation,
   24416             :                                     expression,
   24417             :                                     right_branch
   24418             :                                   );
   24419             : 
   24420     2657583 :                pop_current_state();
   24421             :             }
   24422             : 
   24423     2771581 :             if (0 == new_expression)
   24424             :             {
   24425      114041 :                if (error_list_.empty())
   24426             :                {
   24427          36 :                   set_error(make_error(
   24428             :                      parser_error::e_syntax,
   24429             :                      prev_token,
   24430          24 :                      !synthesis_error_.empty() ?
   24431           0 :                      synthesis_error_ :
   24432             :                      "ERR016 - General parsing error at token: '" + prev_token.value + "'",
   24433             :                      exprtk_error_location));
   24434             :                }
   24435             : 
   24436      114041 :                free_node(node_allocator_, expression  );
   24437      114041 :                free_node(node_allocator_, right_branch);
   24438             : 
   24439      114041 :                return error_node();
   24440             :             }
   24441             :             else
   24442             :             {
   24443     2657540 :                if (
   24444     2657540 :                     token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
   24445             :                     (e_level00 == precedence)
   24446             :                   )
   24447             :                {
   24448        2111 :                   expression = parse_ternary_conditional_statement(new_expression);
   24449             :                }
   24450             :                else
   24451     2655429 :                   expression = new_expression;
   24452             : 
   24453     2657540 :                parse_pending_string_rangesize(expression);
   24454             :             }
   24455             :          }
   24456             : 
   24457     5927868 :          if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
   24458             :          {
   24459           0 :             set_error(make_error(
   24460             :                parser_error::e_syntax,
   24461           0 :                current_token(),
   24462           0 :                "ERR017 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
   24463           0 :                " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
   24464             :                exprtk_error_location));
   24465             : 
   24466           0 :             free_node(node_allocator_,expression);
   24467             : 
   24468           0 :             return error_node();
   24469             :          }
   24470             : 
   24471     5927868 :          return expression;
   24472     6195436 :       }
   24473             : 
   24474        1780 :       bool simplify_unary_negation_branch(expression_node_ptr& node)
   24475             :       {
   24476             :          {
   24477             :             typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
   24478        1780 :             ubn_t* n = dynamic_cast<ubn_t*>(node);
   24479             : 
   24480        1780 :             if (n)
   24481             :             {
   24482        1460 :                expression_node_ptr un_r = n->branch(0);
   24483        1460 :                n->release();
   24484        1460 :                free_node(node_allocator_,node);
   24485        1460 :                node = un_r;
   24486             : 
   24487        1460 :                return true;
   24488             :             }
   24489             :          }
   24490             : 
   24491             :          {
   24492             :             typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
   24493             : 
   24494         320 :             uvn_t* n = dynamic_cast<uvn_t*>(node);
   24495             : 
   24496         320 :             if (n)
   24497             :             {
   24498         320 :                const T& v = n->v();
   24499         320 :                expression_node_ptr return_node = error_node();
   24500             : 
   24501         320 :                if (
   24502         640 :                     (0 != (return_node = symtab_store_.get_variable(v))) ||
   24503         320 :                     (0 != (return_node = sem_         .get_variable(v)))
   24504             :                   )
   24505             :                {
   24506         320 :                   free_node(node_allocator_,node);
   24507         320 :                   node = return_node;
   24508             : 
   24509         320 :                   return true;
   24510             :                }
   24511             :                else
   24512             :                {
   24513           0 :                   set_error(make_error(
   24514             :                      parser_error::e_syntax,
   24515           0 :                      current_token(),
   24516             :                      "ERR018 - Failed to find variable node in symbol table",
   24517             :                      exprtk_error_location));
   24518             : 
   24519           0 :                   free_node(node_allocator_,node);
   24520             : 
   24521           0 :                   return false;
   24522             :                }
   24523             :             }
   24524             :          }
   24525             : 
   24526           0 :          return false;
   24527             :       }
   24528             : 
   24529    23139342 :       static inline expression_node_ptr error_node()
   24530             :       {
   24531    23139342 :          return reinterpret_cast<expression_node_ptr>(0);
   24532             :       }
   24533             : 
   24534             :       struct scoped_expression_delete
   24535             :       {
   24536        1195 :          scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
   24537        1195 :          : delete_ptr(true)
   24538        1195 :          , parser_(pr)
   24539        1195 :          , expression_(expression)
   24540        1195 :          {}
   24541             : 
   24542        1195 :         ~scoped_expression_delete()
   24543             :          {
   24544        1195 :             if (delete_ptr)
   24545             :             {
   24546           0 :                free_node(parser_.node_allocator_, expression_);
   24547             :             }
   24548        1195 :          }
   24549             : 
   24550             :          bool delete_ptr;
   24551             :          parser<T>& parser_;
   24552             :          expression_node_ptr& expression_;
   24553             : 
   24554             :       private:
   24555             : 
   24556             :          scoped_expression_delete(const scoped_expression_delete&) exprtk_delete;
   24557             :          scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete;
   24558             :       };
   24559             : 
   24560             :       template <typename Type, std::size_t N>
   24561             :       struct scoped_delete
   24562             :       {
   24563             :          typedef Type* ptr_t;
   24564             : 
   24565             :          scoped_delete(parser<T>& pr, ptr_t& p)
   24566             :          : delete_ptr(true)
   24567             :          , parser_(pr)
   24568             :          , p_(&p)
   24569             :          {}
   24570             : 
   24571      415799 :          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
   24572      415799 :          : delete_ptr(true)
   24573      415799 :          , parser_(pr)
   24574      415799 :          , p_(&p[0])
   24575      415799 :          {}
   24576             : 
   24577      415799 :         ~scoped_delete()
   24578             :          {
   24579      415799 :             if (delete_ptr)
   24580             :             {
   24581      109625 :                for (std::size_t i = 0; i < N; ++i)
   24582             :                {
   24583       87700 :                   free_node(parser_.node_allocator_, p_[i]);
   24584             :                }
   24585             :             }
   24586      415799 :          }
   24587             : 
   24588             :          bool delete_ptr;
   24589             :          parser<T>& parser_;
   24590             :          ptr_t* p_;
   24591             : 
   24592             :       private:
   24593             : 
   24594             :          scoped_delete(const scoped_delete<Type,N>&) exprtk_delete;
   24595             :          scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete;
   24596             :       };
   24597             : 
   24598             :       template <typename Type>
   24599             :       struct scoped_deq_delete
   24600             :       {
   24601             :          typedef Type* ptr_t;
   24602             : 
   24603             :          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
   24604             :          : delete_ptr(true)
   24605             :          , parser_(pr)
   24606             :          , deq_(deq)
   24607             :          {}
   24608             : 
   24609             :         ~scoped_deq_delete()
   24610             :          {
   24611             :             if (delete_ptr && !deq_.empty())
   24612             :             {
   24613             :                for (std::size_t i = 0; i < deq_.size(); ++i)
   24614             :                {
   24615             :                   free_node(parser_.node_allocator_,deq_[i]);
   24616             :                }
   24617             : 
   24618             :                deq_.clear();
   24619             :             }
   24620             :          }
   24621             : 
   24622             :          bool delete_ptr;
   24623             :          parser<T>& parser_;
   24624             :          std::deque<ptr_t>& deq_;
   24625             : 
   24626             :       private:
   24627             : 
   24628             :          scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete;
   24629             :          scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete;
   24630             :       };
   24631             : 
   24632             :       template <typename Type>
   24633             :       struct scoped_vec_delete
   24634             :       {
   24635             :          typedef Type* ptr_t;
   24636             : 
   24637      409184 :          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
   24638      409184 :          : delete_ptr(true)
   24639      409184 :          , parser_(pr)
   24640      409184 :          , vec_(vec)
   24641      409184 :          {}
   24642             : 
   24643      409184 :         ~scoped_vec_delete()
   24644             :          {
   24645      409184 :             if (delete_ptr && !vec_.empty())
   24646             :             {
   24647         177 :                for (std::size_t i = 0; i < vec_.size(); ++i)
   24648             :                {
   24649         111 :                   free_node(parser_.node_allocator_,vec_[i]);
   24650             :                }
   24651             : 
   24652          66 :                vec_.clear();
   24653             :             }
   24654      409184 :          }
   24655             : 
   24656             :          bool delete_ptr;
   24657             :          parser<T>& parser_;
   24658             :          std::vector<ptr_t>& vec_;
   24659             : 
   24660             :       private:
   24661             : 
   24662             :          scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete;
   24663             :          scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete;
   24664             :       };
   24665             : 
   24666             :       struct scoped_bool_negator
   24667             :       {
   24668         599 :          explicit scoped_bool_negator(bool& bb)
   24669         599 :          : b(bb)
   24670         599 :          { b = !b; }
   24671             : 
   24672         599 :         ~scoped_bool_negator()
   24673         599 :          { b = !b; }
   24674             : 
   24675             :          bool& b;
   24676             :       };
   24677             : 
   24678             :       struct scoped_bool_or_restorer
   24679             :       {
   24680       17589 :          explicit scoped_bool_or_restorer(bool& bb)
   24681       17589 :          : b(bb)
   24682       17589 :          , original_value_(bb)
   24683       17589 :          {}
   24684             : 
   24685       17589 :         ~scoped_bool_or_restorer()
   24686             :          {
   24687       17589 :             b = b || original_value_;
   24688       17589 :          }
   24689             : 
   24690             :          bool& b;
   24691             :          bool original_value_;
   24692             :       };
   24693             : 
   24694             :       struct scoped_inc_dec
   24695             :       {
   24696        2777 :          explicit scoped_inc_dec(std::size_t& v)
   24697        2777 :          : v_(v)
   24698        2777 :          { ++v_; }
   24699             : 
   24700        2777 :         ~scoped_inc_dec()
   24701             :          {
   24702        2777 :            assert(v_ > 0);
   24703        2777 :            --v_;
   24704        2777 :          }
   24705             : 
   24706             :          std::size_t& v_;
   24707             :       };
   24708             : 
   24709       60611 :       inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
   24710             :       {
   24711       60611 :          expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
   24712             : 
   24713       60611 :          switch (function->param_count)
   24714             :          {
   24715         231 :             case  0 : func_node = parse_function_call_0  (function,function_name); break;
   24716        5250 :             case  1 : func_node = parse_function_call< 1>(function,function_name); break;
   24717       40616 :             case  2 : func_node = parse_function_call< 2>(function,function_name); break;
   24718        1626 :             case  3 : func_node = parse_function_call< 3>(function,function_name); break;
   24719        1727 :             case  4 : func_node = parse_function_call< 4>(function,function_name); break;
   24720        1725 :             case  5 : func_node = parse_function_call< 5>(function,function_name); break;
   24721        1316 :             case  6 : func_node = parse_function_call< 6>(function,function_name); break;
   24722        1015 :             case  7 : func_node = parse_function_call< 7>(function,function_name); break;
   24723        1015 :             case  8 : func_node = parse_function_call< 8>(function,function_name); break;
   24724        1015 :             case  9 : func_node = parse_function_call< 9>(function,function_name); break;
   24725        1015 :             case 10 : func_node = parse_function_call<10>(function,function_name); break;
   24726        1015 :             case 11 : func_node = parse_function_call<11>(function,function_name); break;
   24727        1015 :             case 12 : func_node = parse_function_call<12>(function,function_name); break;
   24728        1015 :             case 13 : func_node = parse_function_call<13>(function,function_name); break;
   24729        1015 :             case 14 : func_node = parse_function_call<14>(function,function_name); break;
   24730           0 :             case 15 : func_node = parse_function_call<15>(function,function_name); break;
   24731           0 :             case 16 : func_node = parse_function_call<16>(function,function_name); break;
   24732           0 :             case 17 : func_node = parse_function_call<17>(function,function_name); break;
   24733           0 :             case 18 : func_node = parse_function_call<18>(function,function_name); break;
   24734           0 :             case 19 : func_node = parse_function_call<19>(function,function_name); break;
   24735           0 :             case 20 : func_node = parse_function_call<20>(function,function_name); break;
   24736           0 :             default : {
   24737           0 :                          set_error(make_error(
   24738             :                            parser_error::e_syntax,
   24739           0 :                            current_token(),
   24740             :                            "ERR019 - Invalid number of parameters for function: '" + function_name + "'",
   24741             :                            exprtk_error_location));
   24742             : 
   24743           0 :                          return error_node();
   24744             :                       }
   24745             :          }
   24746             : 
   24747       60611 :          if (func_node)
   24748       60611 :             return func_node;
   24749             :          else
   24750             :          {
   24751           0 :             set_error(make_error(
   24752             :                parser_error::e_syntax,
   24753           0 :                current_token(),
   24754             :                "ERR020 - Failed to generate call to function: '" + function_name + "'",
   24755             :                exprtk_error_location));
   24756             : 
   24757           0 :             return error_node();
   24758             :          }
   24759             :       }
   24760             : 
   24761             :       template <std::size_t NumberofParameters>
   24762       60380 :       inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
   24763             :       {
   24764             :          #ifdef _MSC_VER
   24765             :             #pragma warning(push)
   24766             :             #pragma warning(disable: 4127)
   24767             :          #endif
   24768             :          if (0 == NumberofParameters)
   24769             :          {
   24770             :             set_error(make_error(
   24771             :                parser_error::e_syntax,
   24772             :                current_token(),
   24773             :                "ERR021 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
   24774             :                exprtk_error_location));
   24775             : 
   24776             :             return error_node();
   24777             :          }
   24778             :          #ifdef _MSC_VER
   24779             :             #pragma warning(pop)
   24780             :          #endif
   24781             : 
   24782             :          expression_node_ptr branch[NumberofParameters];
   24783       60380 :          expression_node_ptr result  = error_node();
   24784             : 
   24785       60380 :          std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
   24786             : 
   24787       60380 :          scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
   24788             : 
   24789       60380 :          next_token();
   24790             : 
   24791       60380 :          if (!token_is(token_t::e_lbracket))
   24792             :          {
   24793           0 :             set_error(make_error(
   24794             :                parser_error::e_syntax,
   24795           0 :                current_token(),
   24796             :                "ERR022 - Expecting argument list for function: '" + function_name + "'",
   24797             :                exprtk_error_location));
   24798             : 
   24799           0 :             return error_node();
   24800             :          }
   24801             : 
   24802      260429 :          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
   24803             :          {
   24804      200049 :             branch[i] = parse_expression();
   24805             : 
   24806      200049 :             if (0 == branch[i])
   24807             :             {
   24808           0 :                set_error(make_error(
   24809             :                   parser_error::e_syntax,
   24810           0 :                   current_token(),
   24811             :                   "ERR023 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
   24812             :                   exprtk_error_location));
   24813             : 
   24814           0 :                return error_node();
   24815             :             }
   24816      200049 :             else if (i < static_cast<int>(NumberofParameters - 1))
   24817             :             {
   24818      139669 :                if (!token_is(token_t::e_comma))
   24819             :                {
   24820           0 :                   set_error(make_error(
   24821             :                      parser_error::e_syntax,
   24822           0 :                      current_token(),
   24823             :                      "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
   24824             :                      exprtk_error_location));
   24825             : 
   24826           0 :                   return error_node();
   24827             :                }
   24828             :             }
   24829             :          }
   24830             : 
   24831       60380 :          if (!token_is(token_t::e_rbracket))
   24832             :          {
   24833           0 :             set_error(make_error(
   24834             :                parser_error::e_syntax,
   24835           0 :                current_token(),
   24836             :                "ERR025 - Invalid number of arguments for function: '" + function_name + "'",
   24837             :                exprtk_error_location));
   24838             : 
   24839           0 :             return error_node();
   24840             :          }
   24841             :          else
   24842       60380 :             result = expression_generator_.function(function,branch);
   24843             : 
   24844       60380 :          sd.delete_ptr = (0 == result);
   24845             : 
   24846       60380 :          return result;
   24847       60380 :       }
   24848             : 
   24849         231 :       inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
   24850             :       {
   24851         231 :          expression_node_ptr result = expression_generator_.function(function);
   24852             : 
   24853         231 :          state_.side_effect_present = function->has_side_effects();
   24854             : 
   24855         231 :          next_token();
   24856             : 
   24857         231 :          if (
   24858         347 :                token_is(token_t::e_lbracket) &&
   24859         347 :               !token_is(token_t::e_rbracket)
   24860             :             )
   24861             :          {
   24862           0 :             set_error(make_error(
   24863             :                parser_error::e_syntax,
   24864           0 :                current_token(),
   24865             :                "ERR026 - Expecting '()' to proceed call to function: '" + function_name + "'",
   24866             :                exprtk_error_location));
   24867             : 
   24868           0 :             free_node(node_allocator_,result);
   24869             : 
   24870           0 :             return error_node();
   24871             :          }
   24872             :          else
   24873         231 :             return result;
   24874             :       }
   24875             : 
   24876             :       template <std::size_t MaxNumberofParameters>
   24877      351174 :       inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
   24878             :       {
   24879      351174 :          std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
   24880             : 
   24881      351174 :          scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
   24882             : 
   24883      351174 :          next_token();
   24884             : 
   24885      351174 :          if (!token_is(token_t::e_lbracket))
   24886             :          {
   24887           0 :             set_error(make_error(
   24888             :                parser_error::e_syntax,
   24889           0 :                current_token(),
   24890             :                "ERR027 - Expected a '(' at start of function call to '" + function_name  +
   24891           0 :                "', instead got: '" + current_token().value + "'",
   24892             :                exprtk_error_location));
   24893             : 
   24894           0 :             return 0;
   24895             :          }
   24896             : 
   24897      351174 :          if (token_is(token_t::e_rbracket, e_hold))
   24898             :          {
   24899           0 :             set_error(make_error(
   24900             :                parser_error::e_syntax,
   24901           0 :                current_token(),
   24902             :                "ERR028 - Expected at least one input parameter for function call '" + function_name + "'",
   24903             :                exprtk_error_location));
   24904             : 
   24905           0 :             return 0;
   24906             :          }
   24907             : 
   24908      351174 :          std::size_t param_index = 0;
   24909             : 
   24910      613522 :          for (; param_index < MaxNumberofParameters; ++param_index)
   24911             :          {
   24912      613522 :             param_list[param_index] = parse_expression();
   24913             : 
   24914      613522 :             if (0 == param_list[param_index])
   24915       21919 :                return 0;
   24916      591603 :             else if (token_is(token_t::e_rbracket))
   24917             :             {
   24918      329249 :                sd.delete_ptr = false;
   24919      329249 :                break;
   24920             :             }
   24921      262354 :             else if (token_is(token_t::e_comma))
   24922      262348 :                continue;
   24923             :             else
   24924             :             {
   24925          18 :                set_error(make_error(
   24926             :                   parser_error::e_syntax,
   24927           6 :                   current_token(),
   24928           6 :                   "ERR029 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
   24929             :                   exprtk_error_location));
   24930             : 
   24931           6 :                return 0;
   24932             :             }
   24933             :          }
   24934             : 
   24935      329249 :          if (sd.delete_ptr)
   24936             :          {
   24937           0 :             set_error(make_error(
   24938             :                parser_error::e_syntax,
   24939           0 :                current_token(),
   24940             :                "ERR030 - Invalid number of input parameters passed to function '" + function_name  + "'",
   24941             :                exprtk_error_location));
   24942             : 
   24943           0 :             return 0;
   24944             :          }
   24945             : 
   24946      329249 :          return (param_index + 1);
   24947      351174 :       }
   24948             : 
   24949      351174 :       inline expression_node_ptr parse_base_operation()
   24950             :       {
   24951             :          typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
   24952             : 
   24953      351174 :          const std::string operation_name   = current_token().value;
   24954      351174 :          const token_t     diagnostic_token = current_token();
   24955             : 
   24956      351174 :          map_range_t itr_range = base_ops_map_.equal_range(operation_name);
   24957             : 
   24958      351174 :          if (0 == std::distance(itr_range.first,itr_range.second))
   24959             :          {
   24960           0 :             set_error(make_error(
   24961             :                parser_error::e_syntax,
   24962             :                diagnostic_token,
   24963             :                "ERR031 - No entry found for base operation: " + operation_name,
   24964             :                exprtk_error_location));
   24965             : 
   24966           0 :             return error_node();
   24967             :          }
   24968             : 
   24969             :          static const std::size_t MaxNumberofParameters = 4;
   24970      351174 :          expression_node_ptr param_list[MaxNumberofParameters] = {0};
   24971             : 
   24972      351174 :          const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
   24973             : 
   24974      351174 :          if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
   24975             :          {
   24976      329249 :             for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
   24977             :             {
   24978      329249 :                const details::base_operation_t& operation = itr->second;
   24979             : 
   24980      329249 :                if (operation.num_params == parameter_count)
   24981             :                {
   24982      329249 :                   switch (parameter_count)
   24983             :                   {
   24984             :                      #define base_opr_case(N)                                         \
   24985             :                      case N : {                                                       \
   24986             :                                  expression_node_ptr pl##N[N] = {0};                  \
   24987             :                                  std::copy(param_list, param_list + N, pl##N);        \
   24988             :                                  lodge_symbol(operation_name, e_st_function);         \
   24989             :                                  return expression_generator_(operation.type, pl##N); \
   24990             :                               }                                                       \
   24991             : 
   24992       67372 :                      base_opr_case(1)
   24993      261406 :                      base_opr_case(2)
   24994         471 :                      base_opr_case(3)
   24995           0 :                      base_opr_case(4)
   24996             :                      #undef base_opr_case
   24997             :                   }
   24998             :                }
   24999             :             }
   25000             :          }
   25001             : 
   25002      109625 :          for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
   25003             :          {
   25004       87700 :             free_node(node_allocator_, param_list[i]);
   25005             :          }
   25006             : 
   25007       21925 :          set_error(make_error(
   25008             :             parser_error::e_syntax,
   25009             :             diagnostic_token,
   25010             :             "ERR032 - Invalid number of input parameters for call to function: '" + operation_name + "'",
   25011             :             exprtk_error_location));
   25012             : 
   25013       21925 :          return error_node();
   25014      351174 :       }
   25015             : 
   25016        1276 :       inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
   25017             :       {
   25018             :          // Parse: [if][(][condition][,][consequent][,][alternative][)]
   25019             : 
   25020        1276 :          expression_node_ptr consequent  = error_node();
   25021        1276 :          expression_node_ptr alternative = error_node();
   25022             : 
   25023        1276 :          bool result = true;
   25024             : 
   25025        1276 :          if (!token_is(token_t::e_comma))
   25026             :          {
   25027           0 :             set_error(make_error(
   25028             :                parser_error::e_syntax,
   25029           0 :                current_token(),
   25030             :                "ERR033 - Expected ',' between if-statement condition and consequent",
   25031             :                exprtk_error_location));
   25032             : 
   25033           0 :             result = false;
   25034             :          }
   25035        1276 :          else if (0 == (consequent = parse_expression()))
   25036             :          {
   25037           0 :             set_error(make_error(
   25038             :                parser_error::e_syntax,
   25039           0 :                current_token(),
   25040             :                "ERR034 - Failed to parse consequent for if-statement",
   25041             :                exprtk_error_location));
   25042             : 
   25043           0 :             result = false;
   25044             :          }
   25045        1276 :          else if (!token_is(token_t::e_comma))
   25046             :          {
   25047           0 :             set_error(make_error(
   25048             :                parser_error::e_syntax,
   25049           0 :                current_token(),
   25050             :                "ERR035 - Expected ',' between if-statement consequent and alternative",
   25051             :                exprtk_error_location));
   25052             : 
   25053           0 :             result = false;
   25054             :          }
   25055        1276 :          else if (0 == (alternative = parse_expression()))
   25056             :          {
   25057           0 :             set_error(make_error(
   25058             :                parser_error::e_syntax,
   25059           0 :                current_token(),
   25060             :                "ERR036 - Failed to parse alternative for if-statement",
   25061             :                exprtk_error_location));
   25062             : 
   25063           0 :             result = false;
   25064             :          }
   25065        1276 :          else if (!token_is(token_t::e_rbracket))
   25066             :          {
   25067           0 :             set_error(make_error(
   25068             :                parser_error::e_syntax,
   25069           0 :                current_token(),
   25070             :                "ERR037 - Expected ')' at the end of if-statement",
   25071             :                exprtk_error_location));
   25072             : 
   25073           0 :             result = false;
   25074             :          }
   25075             : 
   25076             :          #ifndef exprtk_disable_string_capabilities
   25077        1276 :          if (result)
   25078             :          {
   25079        1276 :             const bool consq_is_str = is_generally_string_node(consequent );
   25080        1276 :             const bool alter_is_str = is_generally_string_node(alternative);
   25081             : 
   25082        1276 :             if (consq_is_str || alter_is_str)
   25083             :             {
   25084           0 :                if (consq_is_str && alter_is_str)
   25085             :                {
   25086           0 :                   expression_node_ptr result_node =
   25087             :                      expression_generator_
   25088           0 :                         .conditional_string(condition, consequent, alternative);
   25089             : 
   25090           0 :                   if (result_node && result_node->valid())
   25091             :                   {
   25092           0 :                      return result_node;
   25093             :                   }
   25094             : 
   25095           0 :                   set_error(make_error(
   25096             :                      parser_error::e_synthesis,
   25097           0 :                      current_token(),
   25098             :                      "ERR038 - Failed to synthesize node: conditional_string",
   25099             :                      exprtk_error_location));
   25100             : 
   25101           0 :                   free_node(node_allocator_, result_node);
   25102           0 :                   return error_node();
   25103             :                }
   25104             : 
   25105           0 :                set_error(make_error(
   25106             :                   parser_error::e_syntax,
   25107           0 :                   current_token(),
   25108             :                   "ERR039 - Return types of if-statement differ: string/non-string",
   25109             :                   exprtk_error_location));
   25110             : 
   25111           0 :                result = false;
   25112             :             }
   25113             :          }
   25114             :          #endif
   25115             : 
   25116        1276 :          if (result)
   25117             :          {
   25118        1276 :             const bool consq_is_vec = is_ivector_node(consequent );
   25119        1276 :             const bool alter_is_vec = is_ivector_node(alternative);
   25120             : 
   25121        1276 :             if (consq_is_vec || alter_is_vec)
   25122             :             {
   25123         720 :                if (consq_is_vec && alter_is_vec)
   25124             :                {
   25125             :                   return expression_generator_
   25126         720 :                            .conditional_vector(condition, consequent, alternative);
   25127             :                }
   25128             : 
   25129           0 :                set_error(make_error(
   25130             :                   parser_error::e_syntax,
   25131           0 :                   current_token(),
   25132             :                   "ERR040 - Return types of if-statement differ: vector/non-vector",
   25133             :                   exprtk_error_location));
   25134             : 
   25135           0 :                result = false;
   25136             :             }
   25137             :          }
   25138             : 
   25139         556 :          if (!result)
   25140             :          {
   25141           0 :             free_node(node_allocator_, condition  );
   25142           0 :             free_node(node_allocator_, consequent );
   25143           0 :             free_node(node_allocator_, alternative);
   25144             : 
   25145           0 :             return error_node();
   25146             :          }
   25147             :          else
   25148             :             return expression_generator_
   25149         556 :                       .conditional(condition, consequent, alternative);
   25150             :       }
   25151             : 
   25152        4329 :       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
   25153             :       {
   25154        4329 :          expression_node_ptr consequent  = error_node();
   25155        4329 :          expression_node_ptr alternative = error_node();
   25156             : 
   25157        4329 :          bool result = true;
   25158             : 
   25159        4329 :          if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
   25160             :          {
   25161        5838 :             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
   25162             :             {
   25163           0 :                set_error(make_error(
   25164             :                   parser_error::e_syntax,
   25165           0 :                   current_token(),
   25166             :                   "ERR041 - Failed to parse body of consequent for if-statement",
   25167             :                   exprtk_error_location));
   25168             : 
   25169           0 :                result = false;
   25170             :             }
   25171        2919 :             else if
   25172             :             (
   25173        5864 :               !settings_.commutative_check_enabled()           &&
   25174        2958 :               !token_is("else",prsrhlpr_t::e_hold)             &&
   25175          10 :               !token_is_loop(prsrhlpr_t::e_hold)               &&
   25176          10 :               !token_is_arithmetic_opr(prsrhlpr_t::e_hold)     &&
   25177          10 :               !token_is_right_bracket (prsrhlpr_t::e_hold)     &&
   25178          10 :               !token_is_ineq_opr      (prsrhlpr_t::e_hold)     &&
   25179        2942 :               !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
   25180        2929 :               !token_is(token_t::e_eof)
   25181             :             )
   25182             :             {
   25183          32 :                set_error(make_error(
   25184             :                   parser_error::e_syntax,
   25185           8 :                   current_token(),
   25186             :                   "ERR042 - Expected ';' at the end of the consequent for if-statement (1)",
   25187             :                   exprtk_error_location));
   25188             : 
   25189           8 :                result = false;
   25190             :             }
   25191             :          }
   25192             :          else
   25193             :          {
   25194        1410 :             if (
   25195        2818 :                  settings_.commutative_check_enabled() &&
   25196        2818 :                  token_is(token_t::e_mul,prsrhlpr_t::e_hold)
   25197             :                )
   25198             :             {
   25199        1282 :                next_token();
   25200             :             }
   25201             : 
   25202        1410 :             if (0 != (consequent = parse_expression()))
   25203             :             {
   25204        1410 :                if (!token_is(token_t::e_eof))
   25205             :                {
   25206           8 :                   set_error(make_error(
   25207             :                      parser_error::e_syntax,
   25208           2 :                      current_token(),
   25209             :                      "ERR043 - Expected ';' at the end of the consequent for if-statement (2)",
   25210             :                      exprtk_error_location));
   25211             : 
   25212           2 :                   result = false;
   25213             :                }
   25214             :             }
   25215             :             else
   25216             :             {
   25217           0 :                set_error(make_error(
   25218             :                   parser_error::e_syntax,
   25219           0 :                   current_token(),
   25220             :                   "ERR044 - Failed to parse body of consequent for if-statement",
   25221             :                   exprtk_error_location));
   25222             : 
   25223           0 :                result = false;
   25224             :             }
   25225             :          }
   25226             : 
   25227        4329 :          if (result)
   25228             :          {
   25229        8638 :             if (details::imatch(current_token().value,"else"))
   25230             :             {
   25231        2877 :                next_token();
   25232             : 
   25233        2877 :                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
   25234             :                {
   25235        1800 :                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
   25236             :                   {
   25237           0 :                      set_error(make_error(
   25238             :                         parser_error::e_syntax,
   25239           0 :                         current_token(),
   25240             :                         "ERR045 - Failed to parse body of the 'else' for if-statement",
   25241             :                         exprtk_error_location));
   25242             : 
   25243           0 :                      result = false;
   25244             :                   }
   25245             :                }
   25246        3954 :                else if (details::imatch(current_token().value,"if"))
   25247             :                {
   25248         553 :                   if (0 == (alternative = parse_conditional_statement()))
   25249             :                   {
   25250          12 :                      set_error(make_error(
   25251             :                         parser_error::e_syntax,
   25252           3 :                         current_token(),
   25253             :                         "ERR046 - Failed to parse body of if-else statement",
   25254             :                         exprtk_error_location));
   25255             : 
   25256           3 :                      result = false;
   25257             :                   }
   25258             :                }
   25259        1424 :                else if (0 != (alternative = parse_expression()))
   25260             :                {
   25261        1424 :                   if (
   25262        2848 :                        !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
   25263        2848 :                        !token_is(token_t::e_eof)
   25264             :                      )
   25265             :                   {
   25266           0 :                      set_error(make_error(
   25267             :                         parser_error::e_syntax,
   25268           0 :                         current_token(),
   25269             :                         "ERR047 - Expected ';' at the end of the 'else-if' for the if-statement",
   25270             :                         exprtk_error_location));
   25271             : 
   25272           0 :                      result = false;
   25273             :                   }
   25274             :                }
   25275             :                else
   25276             :                {
   25277           0 :                   set_error(make_error(
   25278             :                      parser_error::e_syntax,
   25279           0 :                      current_token(),
   25280             :                      "ERR048 - Failed to parse body of the 'else' for if-statement",
   25281             :                      exprtk_error_location));
   25282             : 
   25283           0 :                   result = false;
   25284             :                }
   25285             :             }
   25286             :          }
   25287             : 
   25288             :          #ifndef exprtk_disable_string_capabilities
   25289        4329 :          if (result)
   25290             :          {
   25291        4316 :             const bool consq_is_str = is_generally_string_node(consequent );
   25292        4316 :             const bool alter_is_str = is_generally_string_node(alternative);
   25293             : 
   25294        4316 :             if (consq_is_str || alter_is_str)
   25295             :             {
   25296          45 :                if (consq_is_str && alter_is_str)
   25297             :                {
   25298             :                   return expression_generator_
   25299          45 :                            .conditional_string(condition, consequent, alternative);
   25300             :                }
   25301             : 
   25302           0 :                set_error(make_error(
   25303             :                   parser_error::e_syntax,
   25304           0 :                   current_token(),
   25305             :                   "ERR049 - Return types of if-statement differ: string/non-string",
   25306             :                   exprtk_error_location));
   25307             : 
   25308           0 :                result = false;
   25309             :             }
   25310             :          }
   25311             :          #endif
   25312             : 
   25313        4284 :          if (result)
   25314             :          {
   25315        4271 :             const bool consq_is_vec = is_ivector_node(consequent );
   25316        4271 :             const bool alter_is_vec = is_ivector_node(alternative);
   25317             : 
   25318        4271 :             if (consq_is_vec || alter_is_vec)
   25319             :             {
   25320         728 :                if (consq_is_vec && alter_is_vec)
   25321             :                {
   25322             :                   return expression_generator_
   25323         728 :                            .conditional_vector(condition, consequent, alternative);
   25324             :                }
   25325             : 
   25326           0 :                set_error(make_error(
   25327             :                   parser_error::e_syntax,
   25328           0 :                   current_token(),
   25329             :                   "ERR050 - Return types of if-statement differ: vector/non-vector",
   25330             :                   exprtk_error_location));
   25331             : 
   25332           0 :                result = false;
   25333             :             }
   25334             :          }
   25335             : 
   25336        3556 :          if (!result)
   25337             :          {
   25338          13 :             free_node(node_allocator_, condition  );
   25339          13 :             free_node(node_allocator_, consequent );
   25340          13 :             free_node(node_allocator_, alternative);
   25341             : 
   25342          13 :             return error_node();
   25343             :          }
   25344             :          else
   25345             :             return expression_generator_
   25346        3543 :                       .conditional(condition, consequent, alternative);
   25347             :       }
   25348             : 
   25349        5605 :       inline expression_node_ptr parse_conditional_statement()
   25350             :       {
   25351        5605 :          expression_node_ptr condition = error_node();
   25352             : 
   25353        5605 :          next_token();
   25354             : 
   25355        5605 :          if (!token_is(token_t::e_lbracket))
   25356             :          {
   25357           0 :             set_error(make_error(
   25358             :                parser_error::e_syntax,
   25359           0 :                current_token(),
   25360           0 :                "ERR051 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
   25361             :                exprtk_error_location));
   25362             : 
   25363           0 :             return error_node();
   25364             :          }
   25365        5605 :          else if (0 == (condition = parse_expression()))
   25366             :          {
   25367           0 :             set_error(make_error(
   25368             :                parser_error::e_syntax,
   25369           0 :                current_token(),
   25370             :                "ERR052 - Failed to parse condition for if-statement",
   25371             :                exprtk_error_location));
   25372             : 
   25373           0 :             return error_node();
   25374             :          }
   25375        5605 :          else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
   25376             :          {
   25377             :             // if (x,y,z)
   25378        1276 :             return parse_conditional_statement_01(condition);
   25379             :          }
   25380        4329 :          else if (token_is(token_t::e_rbracket))
   25381             :          {
   25382             :             /*
   25383             :                00. if (x) y;
   25384             :                01. if (x) y; else z;
   25385             :                02. if (x) y; else {z0; ... zn;}
   25386             :                03. if (x) y; else if (z) w;
   25387             :                04. if (x) y; else if (z) w; else u;
   25388             :                05. if (x) y; else if (z) w; else {u0; ... un;}
   25389             :                06. if (x) y; else if (z) {w0; ... wn;}
   25390             :                07. if (x) {y0; ... yn;}
   25391             :                08. if (x) {y0; ... yn;} else z;
   25392             :                09. if (x) {y0; ... yn;} else {z0; ... zn;};
   25393             :                10. if (x) {y0; ... yn;} else if (z) w;
   25394             :                11. if (x) {y0; ... yn;} else if (z) w; else u;
   25395             :                12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
   25396             :                13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
   25397             :             */
   25398        4329 :             return parse_conditional_statement_02(condition);
   25399             :          }
   25400             : 
   25401           0 :          set_error(make_error(
   25402             :             parser_error::e_syntax,
   25403           0 :             current_token(),
   25404             :             "ERR053 - Invalid if-statement",
   25405             :             exprtk_error_location));
   25406             : 
   25407           0 :          free_node(node_allocator_,condition);
   25408             : 
   25409           0 :          return error_node();
   25410             :       }
   25411             : 
   25412        2725 :       inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
   25413             :       {
   25414             :          // Parse: [condition][?][consequent][:][alternative]
   25415        2725 :          expression_node_ptr consequent  = error_node();
   25416        2725 :          expression_node_ptr alternative = error_node();
   25417             : 
   25418        2725 :          bool result = true;
   25419             : 
   25420        2725 :          if (0 == condition)
   25421             :          {
   25422           0 :             set_error(make_error(
   25423             :                parser_error::e_syntax,
   25424           0 :                current_token(),
   25425             :                "ERR054 - Encountered invalid condition branch for ternary if-statement",
   25426             :                exprtk_error_location));
   25427             : 
   25428           0 :             return error_node();
   25429             :          }
   25430        2725 :          else if (!token_is(token_t::e_ternary))
   25431             :          {
   25432           0 :             set_error(make_error(
   25433             :                parser_error::e_syntax,
   25434           0 :                current_token(),
   25435             :                "ERR055 - Expected '?' after condition of ternary if-statement",
   25436             :                exprtk_error_location));
   25437             : 
   25438           0 :             result = false;
   25439             :          }
   25440        2725 :          else if (0 == (consequent = parse_expression()))
   25441             :          {
   25442          56 :             set_error(make_error(
   25443             :                parser_error::e_syntax,
   25444          14 :                current_token(),
   25445             :                "ERR056 - Failed to parse consequent for ternary if-statement",
   25446             :                exprtk_error_location));
   25447             : 
   25448          14 :             result = false;
   25449             :          }
   25450        2711 :          else if (!token_is(token_t::e_colon))
   25451             :          {
   25452          64 :             set_error(make_error(
   25453             :                parser_error::e_syntax,
   25454          16 :                current_token(),
   25455             :                "ERR057 - Expected ':' between ternary if-statement consequent and alternative",
   25456             :                exprtk_error_location));
   25457             : 
   25458          16 :             result = false;
   25459             :          }
   25460        2695 :          else if (0 == (alternative = parse_expression()))
   25461             :          {
   25462           0 :             set_error(make_error(
   25463             :                parser_error::e_syntax,
   25464           0 :                current_token(),
   25465             :                "ERR058 - Failed to parse alternative for ternary if-statement",
   25466             :                exprtk_error_location));
   25467             : 
   25468           0 :             result = false;
   25469             :          }
   25470             : 
   25471             :          #ifndef exprtk_disable_string_capabilities
   25472        2725 :          if (result)
   25473             :          {
   25474        2695 :             const bool consq_is_str = is_generally_string_node(consequent );
   25475        2695 :             const bool alter_is_str = is_generally_string_node(alternative);
   25476             : 
   25477        2695 :             if (consq_is_str || alter_is_str)
   25478             :             {
   25479        1100 :                if (consq_is_str && alter_is_str)
   25480             :                {
   25481             :                   return expression_generator_
   25482        1100 :                            .conditional_string(condition, consequent, alternative);
   25483             :                }
   25484             : 
   25485           0 :                set_error(make_error(
   25486             :                   parser_error::e_syntax,
   25487           0 :                   current_token(),
   25488             :                   "ERR059 - Return types of ternary differ: string/non-string",
   25489             :                   exprtk_error_location));
   25490             : 
   25491           0 :                result = false;
   25492             :             }
   25493             :          }
   25494             :          #endif
   25495             : 
   25496        1625 :          if (result)
   25497             :          {
   25498        1595 :             const bool consq_is_vec = is_ivector_node(consequent );
   25499        1595 :             const bool alter_is_vec = is_ivector_node(alternative);
   25500             : 
   25501        1595 :             if (consq_is_vec || alter_is_vec)
   25502             :             {
   25503          80 :                if (consq_is_vec && alter_is_vec)
   25504             :                {
   25505             :                   return expression_generator_
   25506          80 :                            .conditional_vector(condition, consequent, alternative);
   25507             :                }
   25508             : 
   25509           0 :                set_error(make_error(
   25510             :                   parser_error::e_syntax,
   25511           0 :                   current_token(),
   25512             :                   "ERR060 - Return types of ternary differ: vector/non-vector",
   25513             :                   exprtk_error_location));
   25514             : 
   25515           0 :                result = false;
   25516             :             }
   25517             :          }
   25518             : 
   25519        1545 :          if (!result)
   25520             :          {
   25521          30 :             free_node(node_allocator_, condition  );
   25522          30 :             free_node(node_allocator_, consequent );
   25523          30 :             free_node(node_allocator_, alternative);
   25524             : 
   25525          30 :             return error_node();
   25526             :          }
   25527             :          else
   25528             :             return expression_generator_
   25529        1515 :                       .conditional(condition, consequent, alternative);
   25530             :       }
   25531             : 
   25532         728 :       inline expression_node_ptr parse_not_statement()
   25533             :       {
   25534        2184 :          if (settings_.logic_disabled("not"))
   25535             :          {
   25536           0 :             set_error(make_error(
   25537             :                parser_error::e_syntax,
   25538           0 :                current_token(),
   25539             :                "ERR061 - Invalid or disabled logic operation 'not'",
   25540             :                exprtk_error_location));
   25541             : 
   25542           0 :             return error_node();
   25543             :          }
   25544             : 
   25545         728 :          return parse_base_operation();
   25546             :       }
   25547             : 
   25548        2767 :       void handle_brkcnt_scope_exit()
   25549             :       {
   25550        2767 :          assert(!brkcnt_list_.empty());
   25551        2767 :          brkcnt_list_.pop_front();
   25552        2767 :       }
   25553             : 
   25554          22 :       inline expression_node_ptr parse_while_loop()
   25555             :       {
   25556             :          // Parse: [while][(][test expr][)][{][expression][}]
   25557          22 :          expression_node_ptr condition   = error_node();
   25558          22 :          expression_node_ptr branch      = error_node();
   25559          22 :          expression_node_ptr result_node = error_node();
   25560             : 
   25561          22 :          bool result = true;
   25562             : 
   25563          22 :          next_token();
   25564             : 
   25565          22 :          if (!token_is(token_t::e_lbracket))
   25566             :          {
   25567           0 :             set_error(make_error(
   25568             :                parser_error::e_syntax,
   25569           0 :                current_token(),
   25570             :                "ERR062 - Expected '(' at start of while-loop condition statement",
   25571             :                exprtk_error_location));
   25572             : 
   25573           0 :             return error_node();
   25574             :          }
   25575          22 :          else if (0 == (condition = parse_expression()))
   25576             :          {
   25577           0 :             set_error(make_error(
   25578             :                parser_error::e_syntax,
   25579           0 :                current_token(),
   25580             :                "ERR063 - Failed to parse condition for while-loop",
   25581             :                exprtk_error_location));
   25582             : 
   25583           0 :             return error_node();
   25584             :          }
   25585          22 :          else if (!token_is(token_t::e_rbracket))
   25586             :          {
   25587           0 :             set_error(make_error(
   25588             :                parser_error::e_syntax,
   25589           0 :                current_token(),
   25590             :                "ERR064 - Expected ')' at end of while-loop condition statement",
   25591             :                exprtk_error_location));
   25592             : 
   25593           0 :             result = false;
   25594             :          }
   25595             : 
   25596          22 :          brkcnt_list_.push_front(false);
   25597             : 
   25598          22 :          if (result)
   25599             :          {
   25600          22 :             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
   25601             : 
   25602          44 :             if (0 == (branch = parse_multi_sequence("while-loop", true)))
   25603             :             {
   25604           0 :                set_error(make_error(
   25605             :                   parser_error::e_syntax,
   25606           0 :                   current_token(),
   25607             :                   "ERR065 - Failed to parse body of while-loop"));
   25608           0 :                result = false;
   25609             :             }
   25610          22 :             else if (0 == (result_node = expression_generator_.while_loop(condition,
   25611             :                                                                           branch,
   25612          22 :                                                                           brkcnt_list_.front())))
   25613             :             {
   25614           0 :                set_error(make_error(
   25615             :                   parser_error::e_syntax,
   25616           0 :                   current_token(),
   25617             :                   "ERR066 - Failed to synthesize while-loop",
   25618             :                   exprtk_error_location));
   25619             : 
   25620           0 :                result = false;
   25621             :             }
   25622          22 :          }
   25623             : 
   25624          22 :          handle_brkcnt_scope_exit();
   25625             : 
   25626          22 :          if (!result)
   25627             :          {
   25628           0 :             free_node(node_allocator_, branch     );
   25629           0 :             free_node(node_allocator_, condition  );
   25630           0 :             free_node(node_allocator_, result_node);
   25631             : 
   25632           0 :             return error_node();
   25633             :          }
   25634             : 
   25635          22 :          if (result_node && result_node->valid())
   25636             :          {
   25637          22 :             return result_node;
   25638             :          }
   25639             : 
   25640           0 :          set_error(make_error(
   25641             :             parser_error::e_synthesis,
   25642           0 :             current_token(),
   25643             :             "ERR067 - Failed to synthesize 'valid' while-loop",
   25644             :             exprtk_error_location));
   25645             : 
   25646           0 :          free_node(node_allocator_, result_node);
   25647             : 
   25648           0 :          return error_node();
   25649             :       }
   25650             : 
   25651          92 :       inline expression_node_ptr parse_repeat_until_loop()
   25652             :       {
   25653             :          // Parse: [repeat][{][expression][}][until][(][test expr][)]
   25654          92 :          expression_node_ptr condition = error_node();
   25655          92 :          expression_node_ptr branch    = error_node();
   25656          92 :          next_token();
   25657             : 
   25658          92 :          std::vector<expression_node_ptr> arg_list;
   25659          92 :          std::vector<bool> side_effect_list;
   25660             : 
   25661          92 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   25662             : 
   25663          92 :          brkcnt_list_.push_front(false);
   25664             : 
   25665         184 :          if (details::imatch(current_token().value,"until"))
   25666             :          {
   25667           0 :             next_token();
   25668           0 :             branch = node_allocator_.allocate<details::null_node<T> >();
   25669             :          }
   25670             :          else
   25671             :          {
   25672          92 :             const token_t::token_type separator = token_t::e_eof;
   25673             : 
   25674          92 :             scope_handler sh(*this);
   25675             : 
   25676          92 :             scoped_bool_or_restorer sbr(state_.side_effect_present);
   25677             : 
   25678          92 :             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
   25679             : 
   25680         101 :             for ( ; ; )
   25681             :             {
   25682         193 :                state_.side_effect_present = false;
   25683             : 
   25684         193 :                expression_node_ptr arg = parse_expression();
   25685             : 
   25686         193 :                if (0 == arg)
   25687          10 :                   return error_node();
   25688             :                else
   25689             :                {
   25690         183 :                   arg_list.push_back(arg);
   25691         183 :                   side_effect_list.push_back(state_.side_effect_present);
   25692             :                }
   25693             : 
   25694         366 :                if (details::imatch(current_token().value,"until"))
   25695             :                {
   25696          42 :                   next_token();
   25697          42 :                   break;
   25698             :                }
   25699             : 
   25700         196 :                const bool is_next_until = peek_token_is(token_t::e_symbol) &&
   25701         251 :                                           peek_token_is("until");
   25702             : 
   25703         141 :                if (!token_is(separator) && is_next_until)
   25704             :                {
   25705           0 :                   set_error(make_error(
   25706             :                      parser_error::e_syntax,
   25707           0 :                      current_token(),
   25708             :                      "ERR068 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop",
   25709             :                      exprtk_error_location));
   25710             : 
   25711           0 :                   return error_node();
   25712             :                }
   25713             : 
   25714         282 :                if (details::imatch(current_token().value,"until"))
   25715             :                {
   25716          40 :                   next_token();
   25717          40 :                   break;
   25718             :                }
   25719             :             }
   25720             : 
   25721          82 :             branch = simplify(arg_list,side_effect_list);
   25722             : 
   25723          82 :             sdd.delete_ptr = (0 == branch);
   25724             : 
   25725          82 :             if (sdd.delete_ptr)
   25726             :             {
   25727           0 :                set_error(make_error(
   25728             :                   parser_error::e_syntax,
   25729           0 :                   current_token(),
   25730             :                   "ERR069 - Failed to parse body of repeat until loop",
   25731             :                   exprtk_error_location));
   25732             : 
   25733           0 :                return error_node();
   25734             :             }
   25735         112 :          }
   25736             : 
   25737          82 :          if (!token_is(token_t::e_lbracket))
   25738             :          {
   25739           0 :             set_error(make_error(
   25740             :                parser_error::e_syntax,
   25741           0 :                current_token(),
   25742             :                "ERR070 - Expected '(' before condition statement of repeat until loop",
   25743             :                exprtk_error_location));
   25744             : 
   25745           0 :             free_node(node_allocator_,branch);
   25746           0 :             return error_node();
   25747             :          }
   25748          82 :          else if (0 == (condition = parse_expression()))
   25749             :          {
   25750           0 :             set_error(make_error(
   25751             :                parser_error::e_syntax,
   25752           0 :                current_token(),
   25753             :                "ERR071 - Failed to parse condition for repeat until loop",
   25754             :                exprtk_error_location));
   25755             : 
   25756           0 :             free_node(node_allocator_,branch);
   25757           0 :             return error_node();
   25758             :          }
   25759          82 :          else if (!token_is(token_t::e_rbracket))
   25760             :          {
   25761           0 :             set_error(make_error(
   25762             :                parser_error::e_syntax,
   25763           0 :                current_token(),
   25764             :                "ERR072 - Expected ')' after condition of repeat until loop",
   25765             :                exprtk_error_location));
   25766             : 
   25767           0 :             free_node(node_allocator_, branch   );
   25768           0 :             free_node(node_allocator_, condition);
   25769             : 
   25770           0 :             return error_node();
   25771             :          }
   25772             : 
   25773          82 :          expression_node_ptr result_node =
   25774             :             expression_generator_
   25775          82 :                .repeat_until_loop(
   25776             :                   condition,
   25777             :                   branch,
   25778          82 :                   brkcnt_list_.front());
   25779             : 
   25780          82 :          if (0 == result_node)
   25781             :          {
   25782           0 :             set_error(make_error(
   25783             :                parser_error::e_syntax,
   25784           0 :                current_token(),
   25785             :                "ERR073 - Failed to synthesize repeat until loop",
   25786             :                exprtk_error_location));
   25787             : 
   25788           0 :             free_node(node_allocator_,condition);
   25789             : 
   25790           0 :             return error_node();
   25791             :          }
   25792             : 
   25793          82 :          handle_brkcnt_scope_exit();
   25794             : 
   25795          82 :          if (result_node && result_node->valid())
   25796             :          {
   25797          82 :             return result_node;
   25798             :          }
   25799             : 
   25800           0 :          set_error(make_error(
   25801             :             parser_error::e_synthesis,
   25802           0 :             current_token(),
   25803             :             "ERR074 - Failed to synthesize 'valid' repeat until loop",
   25804             :             exprtk_error_location));
   25805             : 
   25806           0 :          free_node(node_allocator_, result_node);
   25807             : 
   25808           0 :          return error_node();
   25809          92 :       }
   25810             : 
   25811        2675 :       inline expression_node_ptr parse_for_loop()
   25812             :       {
   25813        2675 :          expression_node_ptr initialiser = error_node();
   25814        2675 :          expression_node_ptr condition   = error_node();
   25815        2675 :          expression_node_ptr incrementor = error_node();
   25816        2675 :          expression_node_ptr loop_body   = error_node();
   25817             : 
   25818        2675 :          scope_element* se = 0;
   25819        2675 :          bool result       = true;
   25820             : 
   25821        2675 :          next_token();
   25822             : 
   25823        2675 :          scope_handler sh(*this);
   25824             : 
   25825        2675 :          if (!token_is(token_t::e_lbracket))
   25826             :          {
   25827           0 :             set_error(make_error(
   25828             :                parser_error::e_syntax,
   25829           0 :                current_token(),
   25830             :                "ERR075 - Expected '(' at start of for-loop",
   25831             :                exprtk_error_location));
   25832             : 
   25833           0 :             return error_node();
   25834             :          }
   25835             : 
   25836        2675 :          if (!token_is(token_t::e_eof))
   25837             :          {
   25838        2675 :             if (
   25839        2685 :                  !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
   25840        2695 :                  details::imatch(current_token().value,"var")
   25841             :                )
   25842             :             {
   25843           0 :                next_token();
   25844             : 
   25845           0 :                if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
   25846             :                {
   25847           0 :                   set_error(make_error(
   25848             :                      parser_error::e_syntax,
   25849           0 :                      current_token(),
   25850             :                      "ERR076 - Expected a variable at the start of initialiser section of for-loop",
   25851             :                      exprtk_error_location));
   25852             : 
   25853           0 :                   return error_node();
   25854             :                }
   25855           0 :                else if (!peek_token_is(token_t::e_assign))
   25856             :                {
   25857           0 :                   set_error(make_error(
   25858             :                      parser_error::e_syntax,
   25859           0 :                      current_token(),
   25860             :                      "ERR077 - Expected variable assignment of initialiser section of for-loop",
   25861             :                      exprtk_error_location));
   25862             : 
   25863           0 :                   return error_node();
   25864             :                }
   25865             : 
   25866           0 :                const std::string loop_counter_symbol = current_token().value;
   25867             : 
   25868           0 :                se = &sem_.get_element(loop_counter_symbol);
   25869             : 
   25870           0 :                if ((se->name == loop_counter_symbol) && se->active)
   25871             :                {
   25872           0 :                   set_error(make_error(
   25873             :                      parser_error::e_syntax,
   25874           0 :                      current_token(),
   25875             :                      "ERR078 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
   25876             :                      exprtk_error_location));
   25877             : 
   25878           0 :                   return error_node();
   25879             :                }
   25880           0 :                else if (!symtab_store_.is_variable(loop_counter_symbol))
   25881             :                {
   25882           0 :                   if (
   25883           0 :                        !se->active &&
   25884           0 :                        (se->name == loop_counter_symbol) &&
   25885           0 :                        (se->type == scope_element::e_variable)
   25886             :                      )
   25887             :                   {
   25888           0 :                      se->active = true;
   25889           0 :                      se->ref_count++;
   25890             :                   }
   25891             :                   else
   25892             :                   {
   25893           0 :                      scope_element nse;
   25894           0 :                      nse.name      = loop_counter_symbol;
   25895           0 :                      nse.active    = true;
   25896           0 :                      nse.ref_count = 1;
   25897           0 :                      nse.type      = scope_element::e_variable;
   25898           0 :                      nse.depth     = state_.scope_depth;
   25899           0 :                      nse.data      = new T(T(0));
   25900           0 :                      nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
   25901             : 
   25902           0 :                      if (!sem_.add_element(nse))
   25903             :                      {
   25904           0 :                         set_error(make_error(
   25905             :                            parser_error::e_syntax,
   25906           0 :                            current_token(),
   25907             :                            "ERR079 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
   25908             :                            exprtk_error_location));
   25909             : 
   25910           0 :                         sem_.free_element(nse);
   25911             : 
   25912           0 :                         result = false;
   25913             :                      }
   25914             :                      else
   25915             :                      {
   25916             :                         exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str()));
   25917             : 
   25918           0 :                         state_.activate_side_effect("parse_for_loop()");
   25919             :                      }
   25920           0 :                   }
   25921             :                }
   25922           0 :             }
   25923             : 
   25924        2675 :             if (0 == (initialiser = parse_expression()))
   25925             :             {
   25926          40 :                set_error(make_error(
   25927             :                   parser_error::e_syntax,
   25928          10 :                   current_token(),
   25929             :                   "ERR080 - Failed to parse initialiser of for-loop",
   25930             :                   exprtk_error_location));
   25931             : 
   25932          10 :                result = false;
   25933             :             }
   25934        2665 :             else if (!token_is(token_t::e_eof))
   25935             :             {
   25936           0 :                set_error(make_error(
   25937             :                   parser_error::e_syntax,
   25938           0 :                   current_token(),
   25939             :                   "ERR081 - Expected ';' after initialiser of for-loop",
   25940             :                   exprtk_error_location));
   25941             : 
   25942           0 :                result = false;
   25943             :             }
   25944             :          }
   25945             : 
   25946        2675 :          if (!token_is(token_t::e_eof))
   25947             :          {
   25948        2675 :             if (0 == (condition = parse_expression()))
   25949             :             {
   25950          48 :                set_error(make_error(
   25951             :                   parser_error::e_syntax,
   25952          12 :                   current_token(),
   25953             :                   "ERR082 - Failed to parse condition of for-loop",
   25954             :                   exprtk_error_location));
   25955             : 
   25956          12 :                result = false;
   25957             :             }
   25958        2663 :             else if (!token_is(token_t::e_eof))
   25959             :             {
   25960           0 :                set_error(make_error(
   25961             :                   parser_error::e_syntax,
   25962           0 :                   current_token(),
   25963             :                   "ERR083 - Expected ';' after condition section of for-loop",
   25964             :                   exprtk_error_location));
   25965             : 
   25966           0 :                result = false;
   25967             :             }
   25968             :          }
   25969             : 
   25970        2675 :          if (!token_is(token_t::e_rbracket))
   25971             :          {
   25972        2545 :             if (0 == (incrementor = parse_expression()))
   25973             :             {
   25974           8 :                set_error(make_error(
   25975             :                   parser_error::e_syntax,
   25976           2 :                   current_token(),
   25977             :                   "ERR084 - Failed to parse incrementor of for-loop",
   25978             :                   exprtk_error_location));
   25979             : 
   25980           2 :                result = false;
   25981             :             }
   25982        2543 :             else if (!token_is(token_t::e_rbracket))
   25983             :             {
   25984           0 :                set_error(make_error(
   25985             :                   parser_error::e_syntax,
   25986           0 :                   current_token(),
   25987             :                   "ERR085 - Expected ')' after incrementor section of for-loop",
   25988             :                   exprtk_error_location));
   25989             : 
   25990           0 :                result = false;
   25991             :             }
   25992             :          }
   25993             : 
   25994        2675 :          if (result)
   25995             :          {
   25996        2663 :             brkcnt_list_.push_front(false);
   25997             : 
   25998        2663 :             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
   25999             : 
   26000        5326 :             if (0 == (loop_body = parse_multi_sequence("for-loop", true)))
   26001             :             {
   26002           0 :                set_error(make_error(
   26003             :                   parser_error::e_syntax,
   26004           0 :                   current_token(),
   26005             :                   "ERR086 - Failed to parse body of for-loop",
   26006             :                   exprtk_error_location));
   26007             : 
   26008           0 :                result = false;
   26009             :             }
   26010        2663 :          }
   26011             : 
   26012        2675 :          if (!result)
   26013             :          {
   26014          12 :             if (se)
   26015             :             {
   26016           0 :                se->ref_count--;
   26017             :             }
   26018             : 
   26019          12 :             free_node(node_allocator_, initialiser);
   26020          12 :             free_node(node_allocator_, condition  );
   26021          12 :             free_node(node_allocator_, incrementor);
   26022          12 :             free_node(node_allocator_, loop_body  );
   26023          12 :             return error_node();
   26024             :          }
   26025             : 
   26026        2663 :          expression_node_ptr result_node =
   26027        2663 :             expression_generator_.for_loop(initialiser,
   26028             :                                            condition,
   26029             :                                            incrementor,
   26030             :                                            loop_body,
   26031        2663 :                                            brkcnt_list_.front());
   26032        2663 :          handle_brkcnt_scope_exit();
   26033             : 
   26034        2663 :          if (result_node && result_node->valid())
   26035             :          {
   26036        2663 :             return result_node;
   26037             :          }
   26038             : 
   26039           0 :          set_error(make_error(
   26040             :             parser_error::e_synthesis,
   26041           0 :             current_token(),
   26042             :             "ERR087 - Failed to synthesize 'valid' for-loop",
   26043             :             exprtk_error_location));
   26044             : 
   26045           0 :          free_node(node_allocator_, result_node);
   26046             : 
   26047           0 :          return error_node();
   26048        2675 :       }
   26049             : 
   26050        1195 :       inline expression_node_ptr parse_switch_statement()
   26051             :       {
   26052        1195 :          std::vector<expression_node_ptr> arg_list;
   26053        1195 :          expression_node_ptr result = error_node();
   26054             : 
   26055        2390 :          if (!details::imatch(current_token().value,"switch"))
   26056             :          {
   26057           0 :             set_error(make_error(
   26058             :                parser_error::e_syntax,
   26059           0 :                current_token(),
   26060             :                "ERR088 - Expected keyword 'switch'",
   26061             :                exprtk_error_location));
   26062             : 
   26063           0 :             return error_node();
   26064             :          }
   26065             : 
   26066        1195 :          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
   26067             : 
   26068        1195 :          next_token();
   26069             : 
   26070        1195 :          if (!token_is(token_t::e_lcrlbracket))
   26071             :          {
   26072           0 :             set_error(make_error(
   26073             :                parser_error::e_syntax,
   26074           0 :                current_token(),
   26075             :                "ERR089 - Expected '{' for call to switch statement",
   26076             :                exprtk_error_location));
   26077             : 
   26078           0 :             return error_node();
   26079             :          }
   26080             : 
   26081        1195 :          expression_node_ptr default_statement = error_node();
   26082             : 
   26083        1195 :          scoped_expression_delete defstmt_delete((*this), default_statement);
   26084             : 
   26085        2730 :          for ( ; ; )
   26086             :          {
   26087       11775 :             if (details::imatch("case",current_token().value))
   26088             :             {
   26089        1535 :                next_token();
   26090             : 
   26091        1535 :                expression_node_ptr condition = parse_expression();
   26092             : 
   26093        1535 :                if (0 == condition)
   26094           0 :                   return error_node();
   26095        1535 :                else if (!token_is(token_t::e_colon))
   26096             :                {
   26097           0 :                   set_error(make_error(
   26098             :                      parser_error::e_syntax,
   26099           0 :                      current_token(),
   26100             :                      "ERR090 - Expected ':' for case of switch statement",
   26101             :                      exprtk_error_location));
   26102             : 
   26103           0 :                   free_node(node_allocator_, condition);
   26104             : 
   26105           0 :                   return error_node();
   26106             :                }
   26107             : 
   26108        1535 :                expression_node_ptr consequent =
   26109        1535 :                   (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
   26110        1535 :                   parse_multi_sequence("switch-consequent") :
   26111        1345 :                   parse_expression();
   26112             : 
   26113        1535 :                if (0 == consequent)
   26114             :                {
   26115           0 :                   free_node(node_allocator_, condition);
   26116             : 
   26117           0 :                   return error_node();
   26118             :                }
   26119        1535 :                else if (!token_is(token_t::e_eof))
   26120             :                {
   26121           0 :                   set_error(make_error(
   26122             :                      parser_error::e_syntax,
   26123           0 :                      current_token(),
   26124             :                      "ERR091 - Expected ';' at end of case for switch statement",
   26125             :                      exprtk_error_location));
   26126             : 
   26127           0 :                   free_node(node_allocator_, condition );
   26128           0 :                   free_node(node_allocator_, consequent);
   26129             : 
   26130           0 :                   return error_node();
   26131             :                }
   26132             : 
   26133             :                // Can we optimise away the case statement?
   26134        1535 :                if (is_constant_node(condition) && is_false(condition))
   26135             :                {
   26136          80 :                   free_node(node_allocator_, condition );
   26137          80 :                   free_node(node_allocator_, consequent);
   26138             :                }
   26139             :                else
   26140             :                {
   26141        1455 :                   arg_list.push_back(condition );
   26142        1455 :                   arg_list.push_back(consequent);
   26143             :                }
   26144             : 
   26145             :             }
   26146        7170 :             else if (details::imatch("default",current_token().value))
   26147             :             {
   26148        1195 :                if (0 != default_statement)
   26149             :                {
   26150           0 :                   set_error(make_error(
   26151             :                      parser_error::e_syntax,
   26152           0 :                      current_token(),
   26153             :                      "ERR092 - Multiple default cases for switch statement",
   26154             :                      exprtk_error_location));
   26155             : 
   26156           0 :                   return error_node();
   26157             :                }
   26158             : 
   26159        1195 :                next_token();
   26160             : 
   26161        1195 :                if (!token_is(token_t::e_colon))
   26162             :                {
   26163           0 :                   set_error(make_error(
   26164             :                      parser_error::e_syntax,
   26165           0 :                      current_token(),
   26166             :                      "ERR093 - Expected ':' for default of switch statement",
   26167             :                      exprtk_error_location));
   26168             : 
   26169           0 :                   return error_node();
   26170             :                }
   26171             : 
   26172        1195 :                default_statement =
   26173        1195 :                   (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
   26174        1195 :                   parse_multi_sequence("switch-default"):
   26175        1194 :                   parse_expression();
   26176             : 
   26177        1195 :                if (0 == default_statement)
   26178           0 :                   return error_node();
   26179        1195 :                else if (!token_is(token_t::e_eof))
   26180             :                {
   26181           0 :                   set_error(make_error(
   26182             :                      parser_error::e_syntax,
   26183           0 :                      current_token(),
   26184             :                      "ERR094 - Expected ';' at end of default for switch statement",
   26185             :                      exprtk_error_location));
   26186             : 
   26187           0 :                   return error_node();
   26188             :                }
   26189             :             }
   26190        1195 :             else if (token_is(token_t::e_rcrlbracket))
   26191        1195 :                break;
   26192             :             else
   26193             :             {
   26194           0 :                set_error(make_error(
   26195             :                   parser_error::e_syntax,
   26196           0 :                   current_token(),
   26197             :                   "ERR095 - Expected '}' at end of switch statement",
   26198             :                   exprtk_error_location));
   26199             : 
   26200           0 :                return error_node();
   26201             :             }
   26202             :          }
   26203             : 
   26204        1195 :          const bool default_statement_present = (0 != default_statement);
   26205             : 
   26206        1195 :          if (default_statement_present)
   26207             :          {
   26208        1195 :             arg_list.push_back(default_statement);
   26209             :          }
   26210             :          else
   26211             :          {
   26212           0 :             arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN()));
   26213             :          }
   26214             : 
   26215        1195 :          result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
   26216             : 
   26217        1195 :          svd.delete_ptr = (0 == result);
   26218        1195 :          defstmt_delete.delete_ptr = (0 == result);
   26219             : 
   26220        1195 :          return result;
   26221        1195 :       }
   26222             : 
   26223         190 :       inline expression_node_ptr parse_multi_switch_statement()
   26224             :       {
   26225         190 :          std::vector<expression_node_ptr> arg_list;
   26226             : 
   26227         380 :          if (!details::imatch(current_token().value,"[*]"))
   26228             :          {
   26229           0 :             set_error(make_error(
   26230             :                parser_error::e_syntax,
   26231           0 :                current_token(),
   26232             :                "ERR096 - Expected token '[*]'",
   26233             :                exprtk_error_location));
   26234             : 
   26235           0 :             return error_node();
   26236             :          }
   26237             : 
   26238         190 :          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
   26239             : 
   26240         190 :          next_token();
   26241             : 
   26242         190 :          if (!token_is(token_t::e_lcrlbracket))
   26243             :          {
   26244           0 :             set_error(make_error(
   26245             :                parser_error::e_syntax,
   26246           0 :                current_token(),
   26247             :                "ERR097 - Expected '{' for call to [*] statement",
   26248             :                exprtk_error_location));
   26249             : 
   26250           0 :             return error_node();
   26251             :          }
   26252             : 
   26253         210 :          for ( ; ; )
   26254             :          {
   26255        1200 :             if (!details::imatch("case",current_token().value))
   26256             :             {
   26257           0 :                set_error(make_error(
   26258             :                   parser_error::e_syntax,
   26259           0 :                   current_token(),
   26260             :                   "ERR098 - Expected a 'case' statement for multi-switch",
   26261             :                   exprtk_error_location));
   26262             : 
   26263           0 :                return error_node();
   26264             :             }
   26265             : 
   26266         400 :             next_token();
   26267             : 
   26268         400 :             expression_node_ptr condition = parse_expression();
   26269             : 
   26270         400 :             if (0 == condition)
   26271           0 :                return error_node();
   26272             : 
   26273         400 :             if (!token_is(token_t::e_colon))
   26274             :             {
   26275           0 :                set_error(make_error(
   26276             :                   parser_error::e_syntax,
   26277           0 :                   current_token(),
   26278             :                   "ERR099 - Expected ':' for case of [*] statement",
   26279             :                   exprtk_error_location));
   26280             : 
   26281           0 :                return error_node();
   26282             :             }
   26283             : 
   26284         400 :             expression_node_ptr consequent =
   26285         400 :                (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
   26286         400 :                parse_multi_sequence("multi-switch-consequent") :
   26287         400 :                parse_expression();
   26288             : 
   26289         400 :             if (0 == consequent)
   26290           0 :                return error_node();
   26291             : 
   26292         400 :             if (!token_is(token_t::e_eof))
   26293             :             {
   26294           0 :                set_error(make_error(
   26295             :                   parser_error::e_syntax,
   26296           0 :                   current_token(),
   26297             :                   "ERR100 - Expected ';' at end of case for [*] statement",
   26298             :                   exprtk_error_location));
   26299             : 
   26300           0 :                return error_node();
   26301             :             }
   26302             : 
   26303             :             // Can we optimise away the case statement?
   26304         400 :             if (is_constant_node(condition) && is_false(condition))
   26305             :             {
   26306           0 :                free_node(node_allocator_, condition );
   26307           0 :                free_node(node_allocator_, consequent);
   26308             :             }
   26309             :             else
   26310             :             {
   26311         400 :                arg_list.push_back(condition );
   26312         400 :                arg_list.push_back(consequent);
   26313             :             }
   26314             : 
   26315         400 :             if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
   26316             :             {
   26317         190 :                break;
   26318             :             }
   26319             :          }
   26320             : 
   26321         190 :          if (!token_is(token_t::e_rcrlbracket))
   26322             :          {
   26323           0 :             set_error(make_error(
   26324             :                parser_error::e_syntax,
   26325           0 :                current_token(),
   26326             :                "ERR101 - Expected '}' at end of [*] statement",
   26327             :                exprtk_error_location));
   26328             : 
   26329           0 :             return error_node();
   26330             :          }
   26331             : 
   26332         190 :          const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
   26333             : 
   26334         190 :          svd.delete_ptr = (0 == result);
   26335             : 
   26336         190 :          return result;
   26337         190 :       }
   26338             : 
   26339       18402 :       inline expression_node_ptr parse_vararg_function()
   26340             :       {
   26341       18402 :          std::vector<expression_node_ptr> arg_list;
   26342             : 
   26343       18402 :          details::operator_type opt_type = details::e_default;
   26344       18402 :          const std::string symbol = current_token().value;
   26345             : 
   26346       36804 :          if (details::imatch(symbol,"~"))
   26347             :          {
   26348       10802 :             next_token();
   26349       21604 :             return parse_multi_sequence();
   26350             :          }
   26351       15200 :          else if (details::imatch(symbol,"[*]"))
   26352             :          {
   26353         190 :             return parse_multi_switch_statement();
   26354             :          }
   26355       14820 :          else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
   26356       14194 :          else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
   26357       13682 :          else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
   26358       12994 :          else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
   26359        4260 :          else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
   26360        3746 :          else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
   26361        3358 :          else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
   26362             :          else
   26363             :          {
   26364           0 :             set_error(make_error(
   26365             :                parser_error::e_syntax,
   26366           0 :                current_token(),
   26367             :                "ERR102 - Unsupported built-in vararg function: " + symbol,
   26368             :                exprtk_error_location));
   26369             : 
   26370           0 :             return error_node();
   26371             :          }
   26372             : 
   26373        7410 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   26374             : 
   26375        7410 :          lodge_symbol(symbol, e_st_function);
   26376             : 
   26377        7410 :          next_token();
   26378             : 
   26379        7410 :          if (!token_is(token_t::e_lbracket))
   26380             :          {
   26381           0 :             set_error(make_error(
   26382             :                parser_error::e_syntax,
   26383           0 :                current_token(),
   26384             :                "ERR103 - Expected '(' for call to vararg function: " + symbol,
   26385             :                exprtk_error_location));
   26386             : 
   26387           0 :             return error_node();
   26388             :          }
   26389             : 
   26390        7410 :          if (token_is(token_t::e_rbracket))
   26391             :          {
   26392           0 :             set_error(make_error(
   26393             :                parser_error::e_syntax,
   26394           0 :                current_token(),
   26395             :                "ERR104 - vararg function: " + symbol +
   26396             :                " requires at least one input parameter",
   26397             :                exprtk_error_location));
   26398             : 
   26399           0 :             return error_node();
   26400             :          }
   26401             : 
   26402        8024 :          for ( ; ; )
   26403             :          {
   26404       15434 :             expression_node_ptr arg = parse_expression();
   26405             : 
   26406       15434 :             if (0 == arg)
   26407           2 :                return error_node();
   26408             :             else
   26409       15432 :                arg_list.push_back(arg);
   26410             : 
   26411       15432 :             if (token_is(token_t::e_rbracket))
   26412        7408 :                break;
   26413        8024 :             else if (!token_is(token_t::e_comma))
   26414             :             {
   26415           0 :                set_error(make_error(
   26416             :                   parser_error::e_syntax,
   26417           0 :                   current_token(),
   26418             :                   "ERR105 - Expected ',' for call to vararg function: " + symbol,
   26419             :                   exprtk_error_location));
   26420             : 
   26421           0 :                return error_node();
   26422             :             }
   26423             :          }
   26424             : 
   26425        7408 :          const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
   26426             : 
   26427        7408 :          sdd.delete_ptr = (0 == result);
   26428        7408 :          return result;
   26429       18402 :       }
   26430             : 
   26431             :       #ifndef exprtk_disable_string_capabilities
   26432        4852 :       inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
   26433             :       {
   26434        4852 :          if (!token_is(token_t::e_lsqrbracket))
   26435             :          {
   26436           0 :             set_error(make_error(
   26437             :                parser_error::e_syntax,
   26438           0 :                current_token(),
   26439             :                "ERR106 - Expected '[' as start of string range definition",
   26440             :                exprtk_error_location));
   26441             : 
   26442           0 :             free_node(node_allocator_,expression);
   26443             : 
   26444           0 :             return error_node();
   26445             :          }
   26446        4852 :          else if (token_is(token_t::e_rsqrbracket))
   26447             :          {
   26448         750 :             return node_allocator_.allocate<details::string_size_node<T> >(expression);
   26449             :          }
   26450             : 
   26451        4102 :          range_t rp;
   26452             : 
   26453        4102 :          if (!parse_range(rp,true))
   26454             :          {
   26455           0 :             free_node(node_allocator_,expression);
   26456             : 
   26457           0 :             return error_node();
   26458             :          }
   26459             : 
   26460        4102 :          expression_node_ptr result = expression_generator_(expression,rp);
   26461             : 
   26462        4102 :          if (0 == result)
   26463             :          {
   26464           0 :             set_error(make_error(
   26465             :                parser_error::e_syntax,
   26466           0 :                current_token(),
   26467             :                "ERR107 - Failed to generate string range node",
   26468             :                exprtk_error_location));
   26469             : 
   26470           0 :             free_node(node_allocator_,expression);
   26471           0 :             rp.free();
   26472             :          }
   26473             : 
   26474        4102 :          rp.clear();
   26475             : 
   26476        4102 :          if (result && result->valid())
   26477             :          {
   26478        4102 :             return result;
   26479             :          }
   26480             : 
   26481           0 :          set_error(make_error(
   26482             :             parser_error::e_synthesis,
   26483           0 :             current_token(),
   26484             :             "ERR108 - Failed to synthesize node: string_range_node",
   26485             :             exprtk_error_location));
   26486             : 
   26487           0 :          free_node(node_allocator_, result);
   26488           0 :          rp.free();
   26489           0 :          return error_node();
   26490             :       }
   26491             :       #else
   26492             :       inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
   26493             :       {
   26494             :          return error_node();
   26495             :       }
   26496             :       #endif
   26497             : 
   26498    13459708 :       inline bool parse_pending_string_rangesize(expression_node_ptr& expression)
   26499             :       {
   26500             :          // Allow no more than 100 range calls, eg: s[][][]...[][]
   26501    13459708 :          const std::size_t max_rangesize_parses = 100;
   26502             : 
   26503    13459708 :          std::size_t i = 0;
   26504             : 
   26505    13459708 :          while
   26506             :             (
   26507    26896312 :               (0 != expression)                     &&
   26508    26863504 :               (i++ < max_rangesize_parses)          &&
   26509    13431752 :               error_list_.empty()                   &&
   26510    27151175 :               is_generally_string_node(expression)  &&
   26511    13719423 :               token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
   26512             :             )
   26513             :          {
   26514        4852 :             expression = parse_string_range_statement(expression);
   26515             :          }
   26516             : 
   26517    13459708 :          return (i > 1);
   26518             :       }
   26519             : 
   26520     1700852 :       inline void parse_pending_vector_index_operator(expression_node_ptr& expression)
   26521             :       {
   26522     1700852 :          if
   26523             :             (
   26524     1700852 :               (0 != expression)           &&
   26525     3401704 :               error_list_.empty()         &&
   26526     1700852 :               is_ivector_node(expression)
   26527             :             )
   26528             :          {
   26529        5546 :             if (
   26530        5546 :                  settings_.commutative_check_enabled()       &&
   26531        6121 :                  token_is(token_t::e_mul,prsrhlpr_t::e_hold) &&
   26532        6121 :                  peek_token_is(token_t::e_lsqrbracket)
   26533             :                )
   26534             :             {
   26535         375 :                token_is(token_t::e_mul);
   26536         375 :                token_is(token_t::e_lsqrbracket);
   26537             :             }
   26538        5171 :             else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
   26539             :             {
   26540           0 :                token_is(token_t::e_lsqrbracket);
   26541             :             }
   26542        5171 :             else if (
   26543        5340 :                       token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) &&
   26544        5340 :                       peek_token_is(token_t::e_lsqrbracket)
   26545             :                     )
   26546             :             {
   26547           0 :                token_is(token_t::e_rbracket   );
   26548           0 :                token_is(token_t::e_lsqrbracket);
   26549             :             }
   26550             :             else
   26551        5171 :                return;
   26552             : 
   26553         375 :             details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression);
   26554             : 
   26555         375 :             if (vi)
   26556             :             {
   26557         375 :                details::vector_holder<T>& vec = vi->vec()->vec_holder();
   26558         375 :                const std::string vector_name  = sem_.get_vector_name(vec.data());
   26559         375 :                expression_node_ptr index      = parse_vector_index(vector_name);
   26560             : 
   26561         375 :                if (index)
   26562             :                {
   26563         375 :                   expression = synthesize_vector_element(vector_name, &vec, expression, index);
   26564         375 :                   return;
   26565             :                }
   26566         375 :             }
   26567             : 
   26568           0 :             free_node(node_allocator_,expression);
   26569           0 :             expression = error_node();
   26570             :          }
   26571             :       }
   26572             : 
   26573             :       template <typename Allocator1,
   26574             :                 typename Allocator2,
   26575             :                 template <typename, typename> class Sequence>
   26576      367505 :       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
   26577             :                                           Sequence<bool,Allocator2>& side_effect_list,
   26578             :                                           const bool specialise_on_final_type = false)
   26579             :       {
   26580      367505 :          if (expression_list.empty())
   26581           0 :             return error_node();
   26582      367505 :          else if (1 == expression_list.size())
   26583      330998 :             return expression_list[0];
   26584             : 
   26585       36507 :          Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
   26586             : 
   26587       36507 :          bool return_node_present = false;
   26588             : 
   26589      104430 :          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
   26590             :          {
   26591       68260 :             if (is_variable_node(expression_list[i]))
   26592           0 :                continue;
   26593       68260 :             else if (
   26594       68260 :                       is_return_node  (expression_list[i]) ||
   26595      136183 :                       is_break_node   (expression_list[i]) ||
   26596       67923 :                       is_continue_node(expression_list[i])
   26597             :                     )
   26598             :             {
   26599         337 :                tmp_expression_list.push_back(expression_list[i]);
   26600             : 
   26601             :                // Remove all subexpressions after first short-circuit
   26602             :                // node has been encountered.
   26603             : 
   26604        1264 :                for (std::size_t j = i + 1; j < expression_list.size(); ++j)
   26605             :                {
   26606         927 :                   free_node(node_allocator_,expression_list[j]);
   26607             :                }
   26608             : 
   26609         337 :                return_node_present = true;
   26610             : 
   26611         337 :                break;
   26612             :             }
   26613       71926 :             else if (
   26614       67923 :                       is_constant_node(expression_list[i]) ||
   26615      133118 :                       is_null_node    (expression_list[i]) ||
   26616      133118 :                       !side_effect_list[i]
   26617             :                     )
   26618             :             {
   26619        4003 :                free_node(node_allocator_,expression_list[i]);
   26620        4003 :                continue;
   26621             :             }
   26622             :             else
   26623       63920 :                tmp_expression_list.push_back(expression_list[i]);
   26624             :          }
   26625             : 
   26626       36507 :          if (!return_node_present)
   26627             :          {
   26628       36170 :             tmp_expression_list.push_back(expression_list.back());
   26629             :          }
   26630             : 
   26631       36507 :          expression_list.swap(tmp_expression_list);
   26632             : 
   26633       36507 :          if (tmp_expression_list.size() > expression_list.size())
   26634             :          {
   26635             :             exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
   26636             :                           static_cast<int>(tmp_expression_list.size()),
   26637             :                           static_cast<int>(expression_list    .size())));
   26638             :          }
   26639             : 
   26640       36507 :          if (
   26641       36170 :               return_node_present     ||
   26642       72677 :               side_effect_list.back() ||
   26643       30441 :               (expression_list.size() > 1)
   26644             :             )
   26645      105180 :             state_.activate_side_effect("simplify()");
   26646             : 
   26647       36507 :          if (1 == expression_list.size())
   26648        2398 :             return expression_list[0];
   26649       34109 :          else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
   26650          85 :             return expression_generator_.vararg_function(details::e_smulti,expression_list);
   26651             :          else
   26652       34024 :             return expression_generator_.vararg_function(details::e_multi,expression_list);
   26653       36507 :       }
   26654             : 
   26655       17497 :       inline expression_node_ptr parse_multi_sequence(const std::string& source = "",
   26656             :                                                       const bool enforce_crlbrackets = false)
   26657             :       {
   26658       17497 :          token_t::token_type open_bracket  = token_t::e_lcrlbracket;
   26659       17497 :          token_t::token_type close_bracket = token_t::e_rcrlbracket;
   26660       17497 :          token_t::token_type separator     = token_t::e_eof;
   26661             : 
   26662       17497 :          if (!token_is(open_bracket))
   26663             :          {
   26664         322 :             if (!enforce_crlbrackets && token_is(token_t::e_lbracket))
   26665             :             {
   26666         322 :                open_bracket  = token_t::e_lbracket;
   26667         322 :                close_bracket = token_t::e_rbracket;
   26668         322 :                separator     = token_t::e_comma;
   26669             :             }
   26670             :             else
   26671             :             {
   26672           0 :                set_error(make_error(
   26673             :                   parser_error::e_syntax,
   26674           0 :                   current_token(),
   26675             :                   "ERR109 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" +
   26676           0 :                   ((!source.empty()) ? std::string(" section of " + source): ""),
   26677             :                   exprtk_error_location));
   26678             : 
   26679           0 :                return error_node();
   26680             :             }
   26681             :          }
   26682       17175 :          else if (token_is(close_bracket))
   26683             :          {
   26684           0 :             return node_allocator_.allocate<details::null_node<T> >();
   26685             :          }
   26686             : 
   26687       17497 :          std::vector<expression_node_ptr> arg_list;
   26688       17497 :          std::vector<bool> side_effect_list;
   26689             : 
   26690       17497 :          expression_node_ptr result = error_node();
   26691             : 
   26692       17497 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   26693             : 
   26694       17497 :          scope_handler sh(*this);
   26695             : 
   26696       17497 :          scoped_bool_or_restorer sbr(state_.side_effect_present);
   26697             : 
   26698       13772 :          for ( ; ; )
   26699             :          {
   26700       31269 :             state_.side_effect_present = false;
   26701             : 
   26702       31269 :             expression_node_ptr arg = parse_expression();
   26703             : 
   26704       31269 :             if (0 == arg)
   26705           0 :                return error_node();
   26706             :             else
   26707             :             {
   26708       31269 :                arg_list.push_back(arg);
   26709       31269 :                side_effect_list.push_back(state_.side_effect_present);
   26710             :             }
   26711             : 
   26712       31269 :             if (token_is(close_bracket))
   26713       13769 :                break;
   26714             : 
   26715       17500 :             const bool is_next_close = peek_token_is(close_bracket);
   26716             : 
   26717       17500 :             if (!token_is(separator) && is_next_close)
   26718             :             {
   26719           0 :                set_error(make_error(
   26720             :                   parser_error::e_syntax,
   26721           0 :                   current_token(),
   26722             :                   "ERR110 - Expected '" + details::to_str(separator) + "' for call to multi-sequence section of " + source,
   26723             :                   exprtk_error_location));
   26724             : 
   26725           0 :                return error_node();
   26726             :             }
   26727             : 
   26728       17500 :             if (token_is(close_bracket))
   26729        3728 :                break;
   26730             :          }
   26731             : 
   26732       17497 :          result = simplify(arg_list, side_effect_list, source.empty());
   26733             : 
   26734       17497 :          sdd.delete_ptr = (0 == result);
   26735       17497 :          return result;
   26736       17497 :       }
   26737             : 
   26738       31796 :       inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
   26739             :       {
   26740             :          // Examples of valid ranges:
   26741             :          // 1. [1:5]     -> [1,5)
   26742             :          // 2. [ :5]     -> [0,5)
   26743             :          // 3. [1: ]     -> [1,end)
   26744             :          // 4. [x:y]     -> [x,y) where x <= y
   26745             :          // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2
   26746             :          // 6. [ :y]     -> [0,y) where 0 <= y
   26747             :          // 7. [x: ]     -> [x,end) where x <= end
   26748             : 
   26749       31796 :          rp.clear();
   26750             : 
   26751       31796 :          if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
   26752             :          {
   26753           0 :             set_error(make_error(
   26754             :                parser_error::e_syntax,
   26755           0 :                current_token(),
   26756             :                "ERR111 - Expected '[' for start of range",
   26757             :                exprtk_error_location));
   26758             : 
   26759           0 :             return false;
   26760             :          }
   26761             : 
   26762       31796 :          if (token_is(token_t::e_colon))
   26763             :          {
   26764       10150 :             rp.n0_c.first  = true;
   26765       10150 :             rp.n0_c.second = 0;
   26766       10150 :             rp.cache.first = 0;
   26767             :          }
   26768             :          else
   26769             :          {
   26770       21646 :             expression_node_ptr r0 = parse_expression();
   26771             : 
   26772       21646 :             if (0 == r0)
   26773             :             {
   26774           0 :                set_error(make_error(
   26775             :                   parser_error::e_syntax,
   26776           0 :                   current_token(),
   26777             :                   "ERR112 - Failed parse begin section of range",
   26778             :                   exprtk_error_location));
   26779             : 
   26780           0 :                return false;
   26781             :             }
   26782       21646 :             else if (is_constant_node(r0))
   26783             :             {
   26784       16440 :                const T r0_value = r0->value();
   26785             : 
   26786       16440 :                if (r0_value >= T(0))
   26787             :                {
   26788       16440 :                   rp.n0_c.first  = true;
   26789       16440 :                   rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
   26790       16440 :                   rp.cache.first = rp.n0_c.second;
   26791             :                }
   26792             : 
   26793       16440 :                free_node(node_allocator_,r0);
   26794             : 
   26795       16440 :                if (r0_value < T(0))
   26796             :                {
   26797           0 :                   set_error(make_error(
   26798             :                      parser_error::e_syntax,
   26799           0 :                      current_token(),
   26800             :                      "ERR113 - Range lower bound less than zero! Constraint: r0 >= 0",
   26801             :                      exprtk_error_location));
   26802             : 
   26803           0 :                   return false;
   26804             :                }
   26805             :             }
   26806             :             else
   26807             :             {
   26808        5206 :                rp.n0_e.first  = true;
   26809        5206 :                rp.n0_e.second = r0;
   26810             :             }
   26811             : 
   26812       21646 :             if (!token_is(token_t::e_colon))
   26813             :             {
   26814           0 :                set_error(make_error(
   26815             :                   parser_error::e_syntax,
   26816           0 :                   current_token(),
   26817             :                   "ERR114 - Expected ':' for break  in range",
   26818             :                   exprtk_error_location));
   26819             : 
   26820           0 :                rp.free();
   26821             : 
   26822           0 :                return false;
   26823             :             }
   26824             :          }
   26825             : 
   26826       31796 :          if (token_is(token_t::e_rsqrbracket))
   26827             :          {
   26828       11400 :             rp.n1_c.first  = true;
   26829       11400 :             rp.n1_c.second = std::numeric_limits<std::size_t>::max();
   26830             :          }
   26831             :          else
   26832             :          {
   26833       20396 :             expression_node_ptr r1 = parse_expression();
   26834             : 
   26835       20396 :             if (0 == r1)
   26836             :             {
   26837           0 :                set_error(make_error(
   26838             :                   parser_error::e_syntax,
   26839           0 :                   current_token(),
   26840             :                   "ERR115 - Failed parse end section of range",
   26841             :                   exprtk_error_location));
   26842             : 
   26843           0 :                rp.free();
   26844             : 
   26845           0 :                return false;
   26846             :             }
   26847       20396 :             else if (is_constant_node(r1))
   26848             :             {
   26849       13540 :                const T r1_value = r1->value();
   26850             : 
   26851       13540 :                if (r1_value >= T(0))
   26852             :                {
   26853       13540 :                   rp.n1_c.first   = true;
   26854       13540 :                   rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
   26855       13540 :                   rp.cache.second = rp.n1_c.second;
   26856             :                }
   26857             : 
   26858       13540 :                free_node(node_allocator_,r1);
   26859             : 
   26860       13540 :                if (r1_value < T(0))
   26861             :                {
   26862           0 :                   set_error(make_error(
   26863             :                      parser_error::e_syntax,
   26864           0 :                      current_token(),
   26865             :                      "ERR116 - Range upper bound less than zero! Constraint: r1 >= 0",
   26866             :                      exprtk_error_location));
   26867             : 
   26868           0 :                   rp.free();
   26869             : 
   26870           0 :                   return false;
   26871             :                }
   26872             :             }
   26873             :             else
   26874             :             {
   26875        6856 :                rp.n1_e.first  = true;
   26876        6856 :                rp.n1_e.second = r1;
   26877             :             }
   26878             : 
   26879       20396 :             if (!token_is(token_t::e_rsqrbracket))
   26880             :             {
   26881           0 :                set_error(make_error(
   26882             :                   parser_error::e_syntax,
   26883           0 :                   current_token(),
   26884             :                   "ERR117 - Expected ']' for start of range",
   26885             :                   exprtk_error_location));
   26886             : 
   26887           0 :                rp.free();
   26888             : 
   26889           0 :                return false;
   26890             :             }
   26891             :          }
   26892             : 
   26893       31796 :          if (rp.const_range())
   26894             :          {
   26895       21688 :             std::size_t r0 = 0;
   26896       21688 :             std::size_t r1 = 0;
   26897             : 
   26898       21688 :             bool rp_result = false;
   26899             : 
   26900             :             try
   26901             :             {
   26902       21688 :                rp_result = rp(r0, r1);
   26903             :             }
   26904           0 :             catch (std::runtime_error&)
   26905             :             {}
   26906             : 
   26907       21688 :             if (!rp_result || (r0 > r1))
   26908             :             {
   26909           0 :                set_error(make_error(
   26910             :                   parser_error::e_syntax,
   26911           0 :                   current_token(),
   26912             :                   "ERR118 - Invalid range, Constraint: r0 <= r1",
   26913             :                   exprtk_error_location));
   26914             : 
   26915           0 :                return false;
   26916             :             }
   26917             :          }
   26918             : 
   26919       31796 :          return true;
   26920             :       }
   26921             : 
   26922     2375038 :       inline void lodge_symbol(const std::string& symbol,
   26923             :                                const symbol_type st)
   26924             :       {
   26925     2375038 :          dec_.add_symbol(symbol,st);
   26926     2375038 :       }
   26927             : 
   26928             :       #ifndef exprtk_disable_string_capabilities
   26929       68250 :       inline expression_node_ptr parse_string()
   26930             :       {
   26931       68250 :          const std::string symbol = current_token().value;
   26932             : 
   26933             :          typedef details::stringvar_node<T>* strvar_node_t;
   26934             : 
   26935       68250 :          expression_node_ptr result   = error_node();
   26936       68250 :          strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
   26937             : 
   26938       68250 :          scope_element& se = sem_.get_active_element(symbol);
   26939             : 
   26940       68250 :          if (scope_element::e_string == se.type)
   26941             :          {
   26942       18775 :             se.active = true;
   26943       18775 :             result    = se.str_node;
   26944       18775 :             lodge_symbol(symbol, e_st_local_string);
   26945             :          }
   26946             :          else
   26947             :          {
   26948             :             typedef typename symtab_store::string_context str_ctxt_t;
   26949       49475 :             str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol);
   26950             : 
   26951       49475 :             if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol))
   26952             :             {
   26953           0 :                set_error(make_error(
   26954             :                   parser_error::e_syntax,
   26955           0 :                   current_token(),
   26956             :                   "ERR119 - Unknown string symbol",
   26957             :                   exprtk_error_location));
   26958             : 
   26959           0 :                return error_node();
   26960             :             }
   26961             : 
   26962       49475 :             assert(str_ctx.str_var != 0);
   26963       49475 :             assert(str_ctx.symbol_table != 0);
   26964             : 
   26965       49475 :             result = str_ctx.str_var;
   26966             : 
   26967       49475 :             if (symtab_store_.is_constant_string(symbol))
   26968             :             {
   26969           0 :                const_str_node = static_cast<strvar_node_t>(result);
   26970           0 :                result = expression_generator_(const_str_node->str());
   26971             :             }
   26972       49475 :             else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability())
   26973             :             {
   26974          48 :                lodge_immutable_symbol(
   26975          24 :                   current_token(),
   26976          24 :                   make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size()));
   26977             :             }
   26978             : 
   26979       49475 :             lodge_symbol(symbol, e_st_string);
   26980             :          }
   26981             : 
   26982       68250 :          if (peek_token_is(token_t::e_lsqrbracket))
   26983             :          {
   26984       25741 :             next_token();
   26985             : 
   26986       25741 :             if (peek_token_is(token_t::e_rsqrbracket))
   26987             :             {
   26988        3600 :                next_token();
   26989        3600 :                next_token();
   26990             : 
   26991        3600 :                if (const_str_node)
   26992             :                {
   26993           0 :                   free_node(node_allocator_,result);
   26994             : 
   26995           0 :                   return expression_generator_(T(const_str_node->size()));
   26996             :                }
   26997             :                else
   26998             :                   return node_allocator_.allocate<details::stringvar_size_node<T> >
   26999        3600 :                             (static_cast<details::stringvar_node<T>*>(result)->ref());
   27000             :             }
   27001             : 
   27002       22141 :             range_t rp;
   27003             : 
   27004       22141 :             if (!parse_range(rp))
   27005             :             {
   27006           0 :                free_node(node_allocator_,result);
   27007             : 
   27008           0 :                return error_node();
   27009             :             }
   27010       22141 :             else if (const_str_node)
   27011             :             {
   27012           0 :                free_node(node_allocator_,result);
   27013           0 :                result = expression_generator_(const_str_node->ref(),rp);
   27014             :             }
   27015             :             else
   27016       22141 :                result = expression_generator_(static_cast<details::stringvar_node<T>*>
   27017             :                            (result)->ref(), rp);
   27018             : 
   27019       22141 :             if (result)
   27020       22141 :                rp.clear();
   27021             :          }
   27022             :          else
   27023       42509 :             next_token();
   27024             : 
   27025       64650 :          return result;
   27026       68250 :       }
   27027             :       #else
   27028             :       inline expression_node_ptr parse_string()
   27029             :       {
   27030             :          return error_node();
   27031             :       }
   27032             :       #endif
   27033             : 
   27034             :       #ifndef exprtk_disable_string_capabilities
   27035       51318 :       inline expression_node_ptr parse_const_string()
   27036             :       {
   27037       51318 :          const std::string   const_str = current_token().value;
   27038       51318 :          expression_node_ptr result    = expression_generator_(const_str);
   27039             : 
   27040       51318 :          if (peek_token_is(token_t::e_lsqrbracket))
   27041             :          {
   27042        6203 :             next_token();
   27043             : 
   27044        6203 :             if (peek_token_is(token_t::e_rsqrbracket))
   27045             :             {
   27046         650 :                next_token();
   27047         650 :                next_token();
   27048             : 
   27049         650 :                free_node(node_allocator_,result);
   27050             : 
   27051         650 :                return expression_generator_(T(const_str.size()));
   27052             :             }
   27053             : 
   27054        5553 :             range_t rp;
   27055             : 
   27056        5553 :             if (!parse_range(rp))
   27057             :             {
   27058           0 :                free_node(node_allocator_,result);
   27059           0 :                rp.free();
   27060             : 
   27061           0 :                return error_node();
   27062             :             }
   27063             : 
   27064        5553 :             free_node(node_allocator_,result);
   27065             : 
   27066        5553 :             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
   27067             :             {
   27068        1750 :                rp.n1_c.second  = const_str.size() - 1;
   27069        1750 :                rp.cache.second = rp.n1_c.second;
   27070             :             }
   27071             : 
   27072        5553 :             if (
   27073       11106 :                  (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
   27074        5553 :                  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
   27075             :                )
   27076             :             {
   27077           0 :                set_error(make_error(
   27078             :                   parser_error::e_syntax,
   27079           0 :                   current_token(),
   27080             :                   "ERR120 - Overflow in range for string: '" + const_str + "'[" +
   27081           0 :                   (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
   27082           0 :                   (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
   27083             :                   exprtk_error_location));
   27084             : 
   27085           0 :                rp.free();
   27086             : 
   27087           0 :                return error_node();
   27088             :             }
   27089             : 
   27090        5553 :             result = expression_generator_(const_str,rp);
   27091             : 
   27092        5553 :             if (result)
   27093        5553 :                rp.clear();
   27094             :          }
   27095             :          else
   27096       45115 :             next_token();
   27097             : 
   27098       50668 :          return result;
   27099       51318 :       }
   27100             :       #else
   27101             :       inline expression_node_ptr parse_const_string()
   27102             :       {
   27103             :          return error_node();
   27104             :       }
   27105             :       #endif
   27106             : 
   27107       17612 :       inline expression_node_ptr parse_vector_index(const std::string& vector_name = "")
   27108             :       {
   27109       17612 :          expression_node_ptr index_expr = error_node();
   27110             : 
   27111       17612 :          if (0 == (index_expr = parse_expression()))
   27112             :          {
   27113           0 :             set_error(make_error(
   27114             :                parser_error::e_syntax,
   27115           0 :                current_token(),
   27116             :                "ERR121 - Failed to parse index for vector: '" + vector_name + "'",
   27117             :                exprtk_error_location));
   27118             : 
   27119           0 :             return error_node();
   27120             :          }
   27121       17612 :          else if (!token_is(token_t::e_rsqrbracket))
   27122             :          {
   27123           0 :             set_error(make_error(
   27124             :                parser_error::e_syntax,
   27125           0 :                current_token(),
   27126             :                "ERR122 - Expected ']' for index of vector: '" + vector_name + "'",
   27127             :                exprtk_error_location));
   27128             : 
   27129           0 :             free_node(node_allocator_,index_expr);
   27130             : 
   27131           0 :             return error_node();
   27132             :          }
   27133             : 
   27134       17612 :          return index_expr;
   27135             :       }
   27136             : 
   27137       43217 :       inline expression_node_ptr parse_vector()
   27138             :       {
   27139       43217 :          const std::string vector_name = current_token().value;
   27140             : 
   27141       43217 :          vector_holder_ptr vec = vector_holder_ptr(0);
   27142             : 
   27143       43217 :          const scope_element& se = sem_.get_active_element(vector_name);
   27144             : 
   27145       43217 :          if (
   27146       43217 :               !details::imatch(se.name, vector_name) ||
   27147       79565 :               (se.depth > state_.scope_depth)   ||
   27148       36348 :               (scope_element::e_vector != se.type)
   27149             :             )
   27150             :          {
   27151             :             typedef typename symtab_store::vector_context vec_ctxt_t;
   27152        6869 :             vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name);
   27153             : 
   27154        6869 :             if (0 == vec_ctx.vector_holder)
   27155             :             {
   27156           0 :                set_error(make_error(
   27157             :                   parser_error::e_syntax,
   27158           0 :                   current_token(),
   27159             :                   "ERR123 - Symbol '" + vector_name + " not a vector",
   27160             :                   exprtk_error_location));
   27161             : 
   27162           0 :                return error_node();
   27163             :             }
   27164             : 
   27165        6869 :             assert(0 != vec_ctx.vector_holder);
   27166        6869 :             assert(0 != vec_ctx.symbol_table );
   27167             : 
   27168        6869 :             vec = vec_ctx.vector_holder;
   27169             : 
   27170        6869 :             if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability())
   27171             :             {
   27172          26 :                lodge_immutable_symbol(
   27173          13 :                   current_token(),
   27174          13 :                   make_memory_range(vec->data(), vec->size()));
   27175             :             }
   27176             :          }
   27177             :          else
   27178             :          {
   27179       36348 :             vec = se.vec_node;
   27180             :          }
   27181             : 
   27182       43217 :          assert(0 != vec);
   27183             : 
   27184       43217 :          next_token();
   27185             : 
   27186       43217 :          if (!token_is(token_t::e_lsqrbracket))
   27187             :          {
   27188       24225 :             return node_allocator_.allocate<vector_node_t>(vec);
   27189             :          }
   27190       18992 :          else if (token_is(token_t::e_rsqrbracket))
   27191             :          {
   27192        1755 :             return (vec->rebaseable()) ?
   27193         188 :                node_allocator_.allocate<vector_size_node_t>(vec) :
   27194        1755 :                expression_generator_(T(vec->size()));
   27195             :          }
   27196             : 
   27197       17237 :          expression_node_ptr index_expr = parse_vector_index(vector_name);
   27198             : 
   27199       17237 :          if (index_expr)
   27200             :          {
   27201       17237 :             expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec);
   27202             : 
   27203       17237 :             return synthesize_vector_element(vector_name, vec, vec_node, index_expr);
   27204             :          }
   27205             : 
   27206           0 :          return error_node();
   27207       43217 :       }
   27208             : 
   27209       17612 :       inline expression_node_ptr synthesize_vector_element(const std::string& vector_name,
   27210             :                                                            vector_holder_ptr vec,
   27211             :                                                            expression_node_ptr vec_node,
   27212             :                                                            expression_node_ptr index_expr)
   27213             :       {
   27214             :          // Perform compile-time range check
   27215       17612 :          if (details::is_constant_node(index_expr))
   27216             :          {
   27217       12983 :             const std::size_t index    = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
   27218       12983 :             const std::size_t vec_size = vec->size();
   27219             : 
   27220       12983 :             if (index >= vec_size)
   27221             :             {
   27222           0 :                set_error(make_error(
   27223             :                   parser_error::e_syntax,
   27224           0 :                   current_token(),
   27225             :                   "ERR124 - Index of " + details::to_str(index) + " out of range for "
   27226             :                   "vector '" + vector_name + "' of size " + details::to_str(vec_size),
   27227             :                   exprtk_error_location));
   27228             : 
   27229           0 :                free_node(node_allocator_, vec_node  );
   27230           0 :                free_node(node_allocator_, index_expr);
   27231             : 
   27232           0 :                return error_node();
   27233             :             }
   27234             :          }
   27235             : 
   27236       17612 :          return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr);
   27237             :       }
   27238             : 
   27239          49 :       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
   27240             :       {
   27241          49 :          std::vector<expression_node_ptr> arg_list;
   27242             : 
   27243          49 :          expression_node_ptr result = error_node();
   27244             : 
   27245          49 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   27246             : 
   27247          49 :          next_token();
   27248             : 
   27249          49 :          if (token_is(token_t::e_lbracket))
   27250             :          {
   27251          48 :             if (token_is(token_t::e_rbracket))
   27252             :             {
   27253           1 :                if (!vararg_function->allow_zero_parameters())
   27254             :                {
   27255           0 :                   set_error(make_error(
   27256             :                      parser_error::e_syntax,
   27257           0 :                      current_token(),
   27258             :                      "ERR125 - Zero parameter call to vararg function: "
   27259             :                      + vararg_function_name + " not allowed",
   27260             :                      exprtk_error_location));
   27261             : 
   27262           0 :                   return error_node();
   27263             :                }
   27264             :             }
   27265             :             else
   27266             :             {
   27267          70 :                for ( ; ; )
   27268             :                {
   27269         117 :                   expression_node_ptr arg = parse_expression();
   27270             : 
   27271         117 :                   if (0 == arg)
   27272           0 :                      return error_node();
   27273             :                   else
   27274         117 :                      arg_list.push_back(arg);
   27275             : 
   27276         117 :                   if (token_is(token_t::e_rbracket))
   27277          47 :                      break;
   27278          70 :                   else if (!token_is(token_t::e_comma))
   27279             :                   {
   27280           0 :                      set_error(make_error(
   27281             :                         parser_error::e_syntax,
   27282           0 :                         current_token(),
   27283             :                         "ERR126 - Expected ',' for call to vararg function: "
   27284             :                         + vararg_function_name,
   27285             :                         exprtk_error_location));
   27286             : 
   27287           0 :                      return error_node();
   27288             :                   }
   27289             :                }
   27290             :             }
   27291             :          }
   27292           1 :          else if (!vararg_function->allow_zero_parameters())
   27293             :          {
   27294           0 :             set_error(make_error(
   27295             :                parser_error::e_syntax,
   27296           0 :                current_token(),
   27297             :                "ERR127 - Zero parameter call to vararg function: "
   27298             :                + vararg_function_name + " not allowed",
   27299             :                exprtk_error_location));
   27300             : 
   27301           0 :             return error_node();
   27302             :          }
   27303             : 
   27304          49 :          if (arg_list.size() < vararg_function->min_num_args())
   27305             :          {
   27306           0 :             set_error(make_error(
   27307             :                parser_error::e_syntax,
   27308           0 :                current_token(),
   27309             :                "ERR128 - Invalid number of parameters to call to vararg function: "
   27310             :                + vararg_function_name + ", require at least "
   27311           0 :                + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
   27312             :                exprtk_error_location));
   27313             : 
   27314           0 :             return error_node();
   27315             :          }
   27316          49 :          else if (arg_list.size() > vararg_function->max_num_args())
   27317             :          {
   27318           0 :             set_error(make_error(
   27319             :                parser_error::e_syntax,
   27320           0 :                current_token(),
   27321             :                "ERR129 - Invalid number of parameters to call to vararg function: "
   27322             :                + vararg_function_name + ", require no more than "
   27323           0 :                + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
   27324             :                exprtk_error_location));
   27325             : 
   27326           0 :             return error_node();
   27327             :          }
   27328             : 
   27329          49 :          result = expression_generator_.vararg_function_call(vararg_function,arg_list);
   27330             : 
   27331          49 :          sdd.delete_ptr = (0 == result);
   27332             : 
   27333          49 :          return result;
   27334          49 :       }
   27335             : 
   27336             :       class type_checker
   27337             :       {
   27338             :       public:
   27339             : 
   27340             :          enum return_type_t
   27341             :          {
   27342             :             e_overload = ' ',
   27343             :             e_numeric  = 'T',
   27344             :             e_string   = 'S'
   27345             :          };
   27346             : 
   27347             :          struct function_prototype_t
   27348             :          {
   27349             :              return_type_t return_type;
   27350             :              std::string   param_seq;
   27351             :          };
   27352             : 
   27353             :          typedef parser<T> parser_t;
   27354             :          typedef std::vector<function_prototype_t> function_definition_list_t;
   27355             : 
   27356        1933 :          type_checker(parser_t& p,
   27357             :                       const std::string& func_name,
   27358             :                       const std::string& func_prototypes,
   27359             :                       const return_type_t default_return_type)
   27360        1933 :          : invalid_state_(true)
   27361        1933 :          , parser_(p)
   27362        1933 :          , function_name_(func_name)
   27363        1933 :          , default_return_type_(default_return_type)
   27364             :          {
   27365        1933 :             parse_function_prototypes(func_prototypes);
   27366        1933 :          }
   27367             : 
   27368        1933 :          bool verify(const std::string& param_seq, std::size_t& pseq_index)
   27369             :          {
   27370        1933 :             if (function_definition_list_.empty())
   27371          10 :                return true;
   27372             : 
   27373        1923 :             std::vector<std::pair<std::size_t,char> > error_list;
   27374             : 
   27375        3327 :             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
   27376             :             {
   27377        3327 :                details::char_t diff_value = 0;
   27378        3327 :                std::size_t     diff_index = 0;
   27379             : 
   27380        3327 :                const bool result = details::sequence_match(function_definition_list_[i].param_seq,
   27381             :                                                            param_seq,
   27382             :                                                            diff_index, diff_value);
   27383             : 
   27384        3327 :               if (result)
   27385             :               {
   27386        1923 :                  pseq_index = i;
   27387        1923 :                  return true;
   27388             :               }
   27389             :               else
   27390        1404 :                  error_list.push_back(std::make_pair(diff_index, diff_value));
   27391             :             }
   27392             : 
   27393           0 :             if (1 == error_list.size())
   27394             :             {
   27395           0 :                parser_.set_error(make_error(
   27396             :                   parser_error::e_syntax,
   27397           0 :                   parser_.current_token(),
   27398           0 :                   "ERR130 - Failed parameter type check for function '" + function_name_ + "', "
   27399           0 :                   "Expected '" + function_definition_list_[0].param_seq +
   27400             :                   "' call set: '" + param_seq + "'",
   27401             :                   exprtk_error_location));
   27402             :             }
   27403             :             else
   27404             :             {
   27405             :                // find first with largest diff_index;
   27406           0 :                std::size_t max_diff_index = 0;
   27407             : 
   27408           0 :                for (std::size_t i = 1; i < error_list.size(); ++i)
   27409             :                {
   27410           0 :                   if (error_list[i].first > error_list[max_diff_index].first)
   27411             :                   {
   27412           0 :                      max_diff_index = i;
   27413             :                   }
   27414             :                }
   27415             : 
   27416           0 :                parser_.set_error(make_error(
   27417             :                   parser_error::e_syntax,
   27418           0 :                   parser_.current_token(),
   27419           0 :                   "ERR131 - Failed parameter type check for function '" + function_name_ + "', "
   27420           0 :                   "Best match: '" + function_definition_list_[max_diff_index].param_seq +
   27421             :                   "' call set: '" + param_seq + "'",
   27422             :                   exprtk_error_location));
   27423             :             }
   27424             : 
   27425           0 :             return false;
   27426        1923 :          }
   27427             : 
   27428        2041 :          std::size_t paramseq_count() const
   27429             :          {
   27430        2041 :             return function_definition_list_.size();
   27431             :          }
   27432             : 
   27433             :          std::string paramseq(const std::size_t& index) const
   27434             :          {
   27435             :             return function_definition_list_[index].param_seq;
   27436             :          }
   27437             : 
   27438         108 :          return_type_t return_type(const std::size_t& index) const
   27439             :          {
   27440         108 :             return function_definition_list_[index].return_type;
   27441             :          }
   27442             : 
   27443        1825 :          bool invalid() const
   27444             :          {
   27445        1825 :             return !invalid_state_;
   27446             :          }
   27447             : 
   27448           8 :          bool allow_zero_parameters() const
   27449             :          {
   27450             : 
   27451           8 :             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
   27452             :             {
   27453           8 :                if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
   27454             :                {
   27455           8 :                   return true;
   27456             :                }
   27457             :             }
   27458             : 
   27459           0 :             return false;
   27460             :          }
   27461             : 
   27462             :       private:
   27463             : 
   27464        1923 :          std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
   27465             :          {
   27466        1923 :              std::string::const_iterator current_begin = param_seq.begin();
   27467        1923 :              std::string::const_iterator iter          = param_seq.begin();
   27468             : 
   27469        1923 :              std::vector<std::string> result;
   27470             : 
   27471       24537 :              while (iter != param_seq.end())
   27472             :              {
   27473       22614 :                  if (*iter == delimiter)
   27474             :                  {
   27475        3712 :                      result.push_back(std::string(current_begin, iter));
   27476        3712 :                      current_begin = ++iter;
   27477             :                  }
   27478             :                  else
   27479       18902 :                      ++iter;
   27480             :              }
   27481             : 
   27482        1923 :              if (current_begin != iter)
   27483             :              {
   27484        3846 :                  result.push_back(std::string(current_begin, iter));
   27485             :              }
   27486             : 
   27487        3846 :              return result;
   27488           0 :          }
   27489             : 
   27490        5635 :          inline bool is_valid_token(std::string param_seq,
   27491             :                                     function_prototype_t& funcproto) const
   27492             :          {
   27493             :             // Determine return type
   27494        5635 :             funcproto.return_type = default_return_type_;
   27495             : 
   27496        5635 :             if (param_seq.size() > 2)
   27497             :             {
   27498        3859 :                if (':' == param_seq[1])
   27499             :                {
   27500             :                   // Note: Only overloaded igeneric functions can have return
   27501             :                   // type definitions.
   27502        1296 :                   if (type_checker::e_overload != default_return_type_)
   27503           0 :                      return false;
   27504             : 
   27505        1296 :                   switch (param_seq[0])
   27506             :                   {
   27507         648 :                      case 'T' : funcproto.return_type = type_checker::e_numeric;
   27508         648 :                                 break;
   27509             : 
   27510         648 :                      case 'S' : funcproto.return_type = type_checker::e_string;
   27511         648 :                                 break;
   27512             : 
   27513           0 :                      default  : return false;
   27514             :                   }
   27515             : 
   27516        1296 :                   param_seq.erase(0,2);
   27517             :                }
   27518             :             }
   27519             : 
   27520        5635 :             if (
   27521       11270 :                  (std::string::npos != param_seq.find("?*")) ||
   27522        5635 :                  (std::string::npos != param_seq.find("**"))
   27523             :                )
   27524             :             {
   27525           0 :                return false;
   27526             :             }
   27527        5635 :             else if (
   27528        5664 :                       (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
   27529          29 :                       ("Z" == param_seq)
   27530             :                     )
   27531             :             {
   27532        5635 :                funcproto.param_seq = param_seq;
   27533        5635 :                return true;
   27534             :             }
   27535             : 
   27536           0 :             return false;
   27537             :          }
   27538             : 
   27539        1933 :          void parse_function_prototypes(const std::string& func_prototypes)
   27540             :          {
   27541        1933 :             if (func_prototypes.empty())
   27542          10 :                return;
   27543             : 
   27544        1923 :             std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
   27545             : 
   27546             :             typedef std::map<std::string,std::size_t> param_seq_map_t;
   27547        1923 :             param_seq_map_t param_seq_map;
   27548             : 
   27549       13193 :             for (std::size_t i = 0; i < param_seq_list.size(); ++i)
   27550             :             {
   27551        5635 :                function_prototype_t func_proto;
   27552             : 
   27553        5635 :                if (!is_valid_token(param_seq_list[i], func_proto))
   27554             :                {
   27555           0 :                   invalid_state_ = false;
   27556             : 
   27557           0 :                   parser_.set_error(make_error(
   27558             :                      parser_error::e_syntax,
   27559           0 :                      parser_.current_token(),
   27560           0 :                      "ERR132 - Invalid parameter sequence of '" + param_seq_list[i] +
   27561           0 :                      "' for function: " + function_name_,
   27562             :                      exprtk_error_location));
   27563           0 :                   return;
   27564             :                }
   27565             : 
   27566        5635 :                param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
   27567             : 
   27568        5635 :                if (param_seq_map.end() != seq_itr)
   27569             :                {
   27570           0 :                   invalid_state_ = false;
   27571             : 
   27572           0 :                   parser_.set_error(make_error(
   27573             :                      parser_error::e_syntax,
   27574           0 :                      parser_.current_token(),
   27575           0 :                      "ERR133 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
   27576           0 :                      "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
   27577             :                      "pseq_idx[" + details::to_str(i) + "] " +
   27578           0 :                      "param seq: " + param_seq_list[i],
   27579             :                      exprtk_error_location));
   27580           0 :                   return;
   27581             :                }
   27582             : 
   27583        5635 :                function_definition_list_.push_back(func_proto);
   27584             :             }
   27585        1923 :          }
   27586             : 
   27587             :          type_checker(const type_checker&) exprtk_delete;
   27588             :          type_checker& operator=(const type_checker&) exprtk_delete;
   27589             : 
   27590             :          bool invalid_state_;
   27591             :          parser_t& parser_;
   27592             :          std::string function_name_;
   27593             :          const return_type_t default_return_type_;
   27594             :          function_definition_list_t function_definition_list_;
   27595             :       };
   27596             : 
   27597        1825 :       inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
   27598             :       {
   27599        1825 :          std::vector<expression_node_ptr> arg_list;
   27600             : 
   27601        1825 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   27602             : 
   27603        1825 :          next_token();
   27604             : 
   27605        1825 :          std::string param_type_list;
   27606             : 
   27607        1825 :          type_checker tc(
   27608             :             (*this),
   27609             :             function_name,
   27610        1825 :             function->parameter_sequence,
   27611             :             type_checker::e_string);
   27612             : 
   27613        1825 :          if (tc.invalid())
   27614             :          {
   27615           0 :             set_error(make_error(
   27616             :                parser_error::e_syntax,
   27617           0 :                current_token(),
   27618             :                "ERR134 - Type checker instantiation failure for generic function: " + function_name,
   27619             :                exprtk_error_location));
   27620             : 
   27621           0 :             return error_node();
   27622             :          }
   27623             : 
   27624        1825 :          if (token_is(token_t::e_lbracket))
   27625             :          {
   27626        1818 :             if (token_is(token_t::e_rbracket))
   27627             :             {
   27628           8 :                if (
   27629          16 :                     !function->allow_zero_parameters() &&
   27630           8 :                     !tc       .allow_zero_parameters()
   27631             :                   )
   27632             :                {
   27633           0 :                   set_error(make_error(
   27634             :                      parser_error::e_syntax,
   27635           0 :                      current_token(),
   27636             :                      "ERR135 - Zero parameter call to generic function: "
   27637             :                      + function_name + " not allowed",
   27638             :                      exprtk_error_location));
   27639             : 
   27640           0 :                   return error_node();
   27641             :                }
   27642             :             }
   27643             :             else
   27644             :             {
   27645        2451 :                for ( ; ; )
   27646             :                {
   27647        4261 :                   expression_node_ptr arg = parse_expression();
   27648             : 
   27649        4261 :                   if (0 == arg)
   27650           0 :                      return error_node();
   27651             : 
   27652        4261 :                   if (is_ivector_node(arg))
   27653        2289 :                      param_type_list += 'V';
   27654        1972 :                   else if (is_generally_string_node(arg))
   27655          94 :                      param_type_list += 'S';
   27656             :                   else // Everything else is assumed to be a scalar returning expression
   27657        1878 :                      param_type_list += 'T';
   27658             : 
   27659        4261 :                   arg_list.push_back(arg);
   27660             : 
   27661        4261 :                   if (token_is(token_t::e_rbracket))
   27662        1810 :                      break;
   27663        2451 :                   else if (!token_is(token_t::e_comma))
   27664             :                   {
   27665           0 :                      set_error(make_error(
   27666             :                         parser_error::e_syntax,
   27667           0 :                         current_token(),
   27668             :                         "ERR136 - Expected ',' for call to generic function: " + function_name,
   27669             :                         exprtk_error_location));
   27670             : 
   27671           0 :                      return error_node();
   27672             :                   }
   27673             :                }
   27674             :             }
   27675             :          }
   27676           7 :          else if (
   27677          14 :                    !function->parameter_sequence.empty() &&
   27678          14 :                    function->allow_zero_parameters    () &&
   27679           0 :                    !tc      .allow_zero_parameters    ()
   27680             :                  )
   27681             :          {
   27682           0 :             set_error(make_error(
   27683             :                parser_error::e_syntax,
   27684           0 :                current_token(),
   27685             :                "ERR137 - Zero parameter call to generic function: "
   27686             :                + function_name + " not allowed",
   27687             :                exprtk_error_location));
   27688             : 
   27689           0 :             return error_node();
   27690             :          }
   27691             : 
   27692        1825 :          std::size_t param_seq_index = 0;
   27693             : 
   27694        1825 :          if (
   27695        3650 :               state_.type_check_enabled &&
   27696        1825 :               !tc.verify(param_type_list, param_seq_index)
   27697             :             )
   27698             :          {
   27699           0 :             set_error(make_error(
   27700             :                parser_error::e_syntax,
   27701           0 :                current_token(),
   27702             :                "ERR138 - Invalid input parameter sequence for call to generic function: " + function_name,
   27703             :                exprtk_error_location));
   27704             : 
   27705           0 :             return error_node();
   27706             :          }
   27707             : 
   27708        1825 :          expression_node_ptr result = error_node();
   27709             : 
   27710        1825 :          result = (tc.paramseq_count() <= 1) ?
   27711             :                   expression_generator_
   27712          57 :                        .generic_function_call(function, arg_list) :
   27713             :                   expression_generator_
   27714        1768 :                        .generic_function_call(function, arg_list, param_seq_index);
   27715             : 
   27716        1825 :          sdd.delete_ptr = (0 == result);
   27717             : 
   27718        1825 :          return result;
   27719        1825 :       }
   27720             : 
   27721         108 :       inline bool parse_igeneric_function_params(std::string& param_type_list,
   27722             :                                                  std::vector<expression_node_ptr>& arg_list,
   27723             :                                                  const std::string& function_name,
   27724             :                                                  igeneric_function<T>* function,
   27725             :                                                  const type_checker& tc)
   27726             :       {
   27727         108 :          if (token_is(token_t::e_lbracket))
   27728             :          {
   27729         108 :             if (token_is(token_t::e_rbracket))
   27730             :             {
   27731           0 :                if (
   27732           0 :                     !function->allow_zero_parameters() &&
   27733           0 :                     !tc       .allow_zero_parameters()
   27734             :                   )
   27735             :                {
   27736           0 :                   set_error(make_error(
   27737             :                      parser_error::e_syntax,
   27738           0 :                      current_token(),
   27739             :                      "ERR139 - Zero parameter call to generic function: "
   27740             :                      + function_name + " not allowed",
   27741             :                      exprtk_error_location));
   27742             : 
   27743           0 :                   return false;
   27744             :                }
   27745             :             }
   27746             :             else
   27747             :             {
   27748         144 :                for ( ; ; )
   27749             :                {
   27750         252 :                   expression_node_ptr arg = parse_expression();
   27751             : 
   27752         252 :                   if (0 == arg)
   27753           0 :                      return false;
   27754             : 
   27755         252 :                   if (is_ivector_node(arg))
   27756           0 :                      param_type_list += 'V';
   27757         252 :                   else if (is_generally_string_node(arg))
   27758         144 :                      param_type_list += 'S';
   27759             :                   else // Everything else is a scalar returning expression
   27760         108 :                      param_type_list += 'T';
   27761             : 
   27762         252 :                   arg_list.push_back(arg);
   27763             : 
   27764         252 :                   if (token_is(token_t::e_rbracket))
   27765         108 :                      break;
   27766         144 :                   else if (!token_is(token_t::e_comma))
   27767             :                   {
   27768           0 :                      set_error(make_error(
   27769             :                         parser_error::e_syntax,
   27770           0 :                         current_token(),
   27771             :                         "ERR140 - Expected ',' for call to string function: " + function_name,
   27772             :                         exprtk_error_location));
   27773             : 
   27774           0 :                      return false;
   27775             :                   }
   27776             :                }
   27777             :             }
   27778             : 
   27779         108 :             return true;
   27780             :          }
   27781             :          else
   27782           0 :             return false;
   27783             :       }
   27784             : 
   27785             :       #ifndef exprtk_disable_string_capabilities
   27786          36 :       inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
   27787             :       {
   27788             :          // Move pass the function name
   27789          36 :          next_token();
   27790             : 
   27791          36 :          std::string param_type_list;
   27792             : 
   27793          36 :          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
   27794             : 
   27795          36 :          if (
   27796          72 :               (!function->parameter_sequence.empty()) &&
   27797          36 :               (0 == tc.paramseq_count())
   27798             :             )
   27799             :          {
   27800           0 :             return error_node();
   27801             :          }
   27802             : 
   27803          36 :          std::vector<expression_node_ptr> arg_list;
   27804          36 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   27805             : 
   27806          36 :          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
   27807             :          {
   27808           0 :             return error_node();
   27809             :          }
   27810             : 
   27811          36 :          std::size_t param_seq_index = 0;
   27812             : 
   27813          36 :          if (!tc.verify(param_type_list, param_seq_index))
   27814             :          {
   27815           0 :             set_error(make_error(
   27816             :                parser_error::e_syntax,
   27817           0 :                current_token(),
   27818             :                "ERR141 - Invalid input parameter sequence for call to string function: " + function_name,
   27819             :                exprtk_error_location));
   27820             : 
   27821           0 :             return error_node();
   27822             :          }
   27823             : 
   27824          36 :          expression_node_ptr result = error_node();
   27825             : 
   27826          36 :          result = (tc.paramseq_count() <= 1) ?
   27827             :                   expression_generator_
   27828           0 :                        .string_function_call(function, arg_list) :
   27829             :                   expression_generator_
   27830          36 :                        .string_function_call(function, arg_list, param_seq_index);
   27831             : 
   27832          36 :          sdd.delete_ptr = (0 == result);
   27833             : 
   27834          36 :          return result;
   27835          36 :       }
   27836             : 
   27837          72 :       inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
   27838             :       {
   27839             :          // Move pass the function name
   27840          72 :          next_token();
   27841             : 
   27842          72 :          std::string param_type_list;
   27843             : 
   27844          72 :          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
   27845             : 
   27846          72 :          if (
   27847         144 :               (!function->parameter_sequence.empty()) &&
   27848          72 :               (0 == tc.paramseq_count())
   27849             :             )
   27850             :          {
   27851           0 :             return error_node();
   27852             :          }
   27853             : 
   27854          72 :          std::vector<expression_node_ptr> arg_list;
   27855          72 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   27856             : 
   27857          72 :          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
   27858             :          {
   27859           0 :             return error_node();
   27860             :          }
   27861             : 
   27862          72 :          std::size_t param_seq_index = 0;
   27863             : 
   27864          72 :          if (!tc.verify(param_type_list, param_seq_index))
   27865             :          {
   27866           0 :             set_error(make_error(
   27867             :                parser_error::e_syntax,
   27868           0 :                current_token(),
   27869             :                "ERR142 - Invalid input parameter sequence for call to overloaded function: " + function_name,
   27870             :                exprtk_error_location));
   27871             : 
   27872           0 :             return error_node();
   27873             :          }
   27874             : 
   27875          72 :          expression_node_ptr result = error_node();
   27876             : 
   27877          72 :          if (type_checker::e_numeric == tc.return_type(param_seq_index))
   27878             :          {
   27879          36 :             if (tc.paramseq_count() <= 1)
   27880             :                result = expression_generator_
   27881           0 :                           .generic_function_call(function, arg_list);
   27882             :             else
   27883             :                result = expression_generator_
   27884          36 :                           .generic_function_call(function, arg_list, param_seq_index);
   27885             :          }
   27886          36 :          else if (type_checker::e_string == tc.return_type(param_seq_index))
   27887             :          {
   27888          36 :             if (tc.paramseq_count() <= 1)
   27889             :                result = expression_generator_
   27890           0 :                           .string_function_call(function, arg_list);
   27891             :             else
   27892             :                result = expression_generator_
   27893          36 :                           .string_function_call(function, arg_list, param_seq_index);
   27894             :          }
   27895             :          else
   27896             :          {
   27897           0 :             set_error(make_error(
   27898             :                parser_error::e_syntax,
   27899           0 :                current_token(),
   27900             :                "ERR143 - Invalid return type for call to overloaded function: " + function_name,
   27901             :                exprtk_error_location));
   27902             :          }
   27903             : 
   27904          72 :          sdd.delete_ptr = (0 == result);
   27905          72 :          return result;
   27906          72 :       }
   27907             :       #endif
   27908             : 
   27909             :       template <typename Type, std::size_t NumberOfParameters>
   27910             :       struct parse_special_function_impl
   27911             :       {
   27912        4245 :          static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
   27913             :          {
   27914             :             expression_node_ptr branch[NumberOfParameters];
   27915        4245 :             expression_node_ptr result = error_node();
   27916             : 
   27917        4245 :             std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0));
   27918             : 
   27919        4245 :             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
   27920             : 
   27921        4245 :             p.next_token();
   27922             : 
   27923        4245 :             if (!p.token_is(token_t::e_lbracket))
   27924             :             {
   27925           0 :                p.set_error(make_error(
   27926             :                   parser_error::e_syntax,
   27927           0 :                   p.current_token(),
   27928             :                   "ERR144 - Expected '(' for special function '" + sf_name + "'",
   27929             :                   exprtk_error_location));
   27930             : 
   27931           0 :                return error_node();
   27932             :             }
   27933             : 
   27934       19305 :             for (std::size_t i = 0; i < NumberOfParameters; ++i)
   27935             :             {
   27936       15060 :                branch[i] = p.parse_expression();
   27937             : 
   27938       15060 :                if (0 == branch[i])
   27939             :                {
   27940           0 :                   return p.error_node();
   27941             :                }
   27942       15060 :                else if (i < (NumberOfParameters - 1))
   27943             :                {
   27944       10815 :                   if (!p.token_is(token_t::e_comma))
   27945             :                   {
   27946           0 :                      p.set_error(make_error(
   27947             :                         parser_error::e_syntax,
   27948           0 :                         p.current_token(),
   27949             :                         "ERR145 - Expected ',' before next parameter of special function '" + sf_name + "'",
   27950             :                         exprtk_error_location));
   27951             : 
   27952           0 :                      return p.error_node();
   27953             :                   }
   27954             :                }
   27955             :             }
   27956             : 
   27957        4245 :             if (!p.token_is(token_t::e_rbracket))
   27958             :             {
   27959           0 :                p.set_error(make_error(
   27960             :                   parser_error::e_syntax,
   27961           0 :                   p.current_token(),
   27962             :                   "ERR146 - Invalid number of parameters for special function '" + sf_name + "'",
   27963             :                   exprtk_error_location));
   27964             : 
   27965           0 :                return p.error_node();
   27966             :             }
   27967             :             else
   27968        4245 :                result = p.expression_generator_.special_function(opt_type,branch);
   27969             : 
   27970        4245 :             sd.delete_ptr = (0 == result);
   27971             : 
   27972        4245 :             return result;
   27973        4245 :          }
   27974             :       };
   27975             : 
   27976        4245 :       inline expression_node_ptr parse_special_function()
   27977             :       {
   27978        4245 :          const std::string sf_name = current_token().value;
   27979             : 
   27980             :          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
   27981        4245 :          if (
   27982        8490 :               !details::is_digit(sf_name[2]) ||
   27983        4245 :               !details::is_digit(sf_name[3])
   27984             :             )
   27985             :          {
   27986           0 :             set_error(make_error(
   27987             :                parser_error::e_token,
   27988           0 :                current_token(),
   27989             :                "ERR147 - Invalid special function[1]: " + sf_name,
   27990             :                exprtk_error_location));
   27991             : 
   27992           0 :             return error_node();
   27993             :          }
   27994             : 
   27995        4245 :          const int id = (sf_name[2] - '0') * 10 +
   27996        4245 :                         (sf_name[3] - '0');
   27997             : 
   27998        4245 :          if (id >= details::e_sffinal)
   27999             :          {
   28000           0 :             set_error(make_error(
   28001             :                parser_error::e_token,
   28002           0 :                current_token(),
   28003             :                "ERR148 - Invalid special function[2]: " + sf_name,
   28004             :                exprtk_error_location));
   28005             : 
   28006           0 :             return error_node();
   28007             :          }
   28008             : 
   28009        4245 :          const int sf_3_to_4                   = details::e_sf48;
   28010        4245 :          const details::operator_type opt_type = details::operator_type(id + 1000);
   28011        4245 :          const std::size_t NumberOfParameters  = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
   28012             : 
   28013        4245 :          switch (NumberOfParameters)
   28014             :          {
   28015        1920 :             case 3  : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
   28016        2325 :             case 4  : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
   28017           0 :             default : return error_node();
   28018             :          }
   28019        4245 :       }
   28020             : 
   28021         265 :       inline expression_node_ptr parse_null_statement()
   28022             :       {
   28023         265 :          next_token();
   28024         265 :          return node_allocator_.allocate<details::null_node<T> >();
   28025             :       }
   28026             : 
   28027             :       #ifndef exprtk_disable_break_continue
   28028         483 :       inline expression_node_ptr parse_break_statement()
   28029             :       {
   28030         483 :          if (state_.parsing_break_stmt)
   28031             :          {
   28032           0 :             set_error(make_error(
   28033             :                parser_error::e_syntax,
   28034           0 :                current_token(),
   28035             :                "ERR149 - Invoking 'break' within a break call is not allowed",
   28036             :                exprtk_error_location));
   28037             : 
   28038           0 :             return error_node();
   28039             :          }
   28040         483 :          else if (0 == state_.parsing_loop_stmt_count)
   28041             :          {
   28042           0 :             set_error(make_error(
   28043             :                parser_error::e_syntax,
   28044           0 :                current_token(),
   28045             :                "ERR150 - Invalid use of 'break', allowed only in the scope of a loop",
   28046             :                exprtk_error_location));
   28047             : 
   28048           0 :             return error_node();
   28049             :          }
   28050             : 
   28051         483 :          scoped_bool_negator sbn(state_.parsing_break_stmt);
   28052             : 
   28053         483 :          if (!brkcnt_list_.empty())
   28054             :          {
   28055         483 :             next_token();
   28056             : 
   28057         483 :             brkcnt_list_.front() = true;
   28058             : 
   28059         483 :             expression_node_ptr return_expr = error_node();
   28060             : 
   28061         483 :             if (token_is(token_t::e_lsqrbracket))
   28062             :             {
   28063         402 :                if (0 == (return_expr = parse_expression()))
   28064             :                {
   28065           0 :                   set_error(make_error(
   28066             :                      parser_error::e_syntax,
   28067           0 :                      current_token(),
   28068             :                      "ERR151 - Failed to parse return expression for 'break' statement",
   28069             :                      exprtk_error_location));
   28070             : 
   28071           0 :                   return error_node();
   28072             :                }
   28073         402 :                else if (!token_is(token_t::e_rsqrbracket))
   28074             :                {
   28075           0 :                   set_error(make_error(
   28076             :                      parser_error::e_syntax,
   28077           0 :                      current_token(),
   28078             :                      "ERR152 - Expected ']' at the completion of break's return expression",
   28079             :                      exprtk_error_location));
   28080             : 
   28081           0 :                   free_node(node_allocator_,return_expr);
   28082             : 
   28083           0 :                   return error_node();
   28084             :                }
   28085             :             }
   28086             : 
   28087         966 :             state_.activate_side_effect("parse_break_statement()");
   28088             : 
   28089         483 :             return node_allocator_.allocate<details::break_node<T> >(return_expr);
   28090             :          }
   28091             :          else
   28092             :          {
   28093           0 :             set_error(make_error(
   28094             :                parser_error::e_syntax,
   28095           0 :                current_token(),
   28096             :                "ERR153 - Invalid use of 'break', allowed only in the scope of a loop",
   28097             :                exprtk_error_location));
   28098             :          }
   28099             : 
   28100           0 :          return error_node();
   28101         483 :       }
   28102             : 
   28103         460 :       inline expression_node_ptr parse_continue_statement()
   28104             :       {
   28105         460 :          if (0 == state_.parsing_loop_stmt_count)
   28106             :          {
   28107           0 :             set_error(make_error(
   28108             :                parser_error::e_syntax,
   28109           0 :                current_token(),
   28110             :                "ERR154 - Invalid use of 'continue', allowed only in the scope of a loop",
   28111             :                exprtk_error_location));
   28112             : 
   28113           0 :             return error_node();
   28114             :          }
   28115             :          else
   28116             :          {
   28117         460 :             next_token();
   28118             : 
   28119         460 :             brkcnt_list_.front() = true;
   28120         920 :             state_.activate_side_effect("parse_continue_statement()");
   28121             : 
   28122         460 :             return node_allocator_.allocate<details::continue_node<T> >();
   28123             :          }
   28124             :       }
   28125             :       #endif
   28126             : 
   28127       19777 :       inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
   28128             :       {
   28129       19777 :          expression_node_ptr size_expression_node = error_node();
   28130             : 
   28131       19777 :          if (!token_is(token_t::e_lsqrbracket))
   28132             :          {
   28133           0 :             set_error(make_error(
   28134             :                parser_error::e_syntax,
   28135           0 :                current_token(),
   28136             :                "ERR155 - Expected '[' as part of vector size definition",
   28137             :                exprtk_error_location));
   28138             : 
   28139           0 :             return error_node();
   28140             :          }
   28141       19777 :          else if (0 == (size_expression_node = parse_expression()))
   28142             :          {
   28143           0 :             set_error(make_error(
   28144             :                parser_error::e_syntax,
   28145           0 :                current_token(),
   28146             :                "ERR156 - Failed to determine size of vector '" + vec_name + "'",
   28147             :                exprtk_error_location));
   28148             : 
   28149           0 :             return error_node();
   28150             :          }
   28151       19777 :          else if (!is_constant_node(size_expression_node))
   28152             :          {
   28153           0 :             const bool is_rebaseble_vector =
   28154           0 :                (size_expression_node->type() == details::expression_node<T>::e_vecsize) &&
   28155           0 :                static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable();
   28156             : 
   28157           0 :             free_node(node_allocator_,size_expression_node);
   28158             : 
   28159           0 :             const std::string error_msg = (is_rebaseble_vector) ?
   28160             :                                           std::string("Rebasable/Resizable vector cannot be used to define the size of vector") :
   28161             :                                           std::string("Expected a constant literal number as size of vector");
   28162           0 :             set_error(make_error(
   28163             :                parser_error::e_syntax,
   28164           0 :                current_token(),
   28165             :                "ERR157 - " + error_msg + " '" + vec_name + "'",
   28166             :                exprtk_error_location));
   28167             : 
   28168           0 :             return error_node();
   28169           0 :          }
   28170             : 
   28171       19777 :          const T vector_size = size_expression_node->value();
   28172             : 
   28173       19777 :          free_node(node_allocator_,size_expression_node);
   28174             : 
   28175       19777 :          const std::size_t max_vector_size = settings_.max_local_vector_size();
   28176             : 
   28177       19777 :          if (
   28178       19777 :               (vector_size <= T(0)) ||
   28179           0 :               std::not_equal_to<T>()
   28180       39554 :               (T(0),vector_size - details::numeric::trunc(vector_size)) ||
   28181       19777 :               (static_cast<std::size_t>(vector_size) > max_vector_size)
   28182             :             )
   28183             :          {
   28184           0 :             set_error(make_error(
   28185             :                parser_error::e_syntax,
   28186           0 :                current_token(),
   28187             :                "ERR158 - Invalid vector size. Must be an integer in the "
   28188             :                "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " +
   28189             :                details::to_str(details::numeric::to_int32(vector_size)),
   28190             :                exprtk_error_location));
   28191             : 
   28192           0 :             return error_node();
   28193             :          }
   28194             : 
   28195       19777 :          std::vector<expression_node_ptr> vec_initilizer_list;
   28196             : 
   28197       19777 :          scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
   28198             : 
   28199       19777 :          bool single_value_initialiser = false;
   28200       19777 :          bool vec_to_vec_initialiser   = false;
   28201       19777 :          bool null_initialisation      = false;
   28202             : 
   28203       19777 :          if (!token_is(token_t::e_rsqrbracket))
   28204             :          {
   28205           0 :             set_error(make_error(
   28206             :                parser_error::e_syntax,
   28207           0 :                current_token(),
   28208             :                "ERR159 - Expected ']' as part of vector size definition",
   28209             :                exprtk_error_location));
   28210             : 
   28211           0 :             return error_node();
   28212             :          }
   28213       19777 :          else if (!token_is(token_t::e_eof))
   28214             :          {
   28215       19694 :             if (!token_is(token_t::e_assign))
   28216             :             {
   28217           0 :                set_error(make_error(
   28218             :                   parser_error::e_syntax,
   28219           0 :                   current_token(),
   28220             :                   "ERR160 - Expected ':=' as part of vector definition",
   28221             :                   exprtk_error_location));
   28222             : 
   28223           0 :                return error_node();
   28224             :             }
   28225       19694 :             else if (token_is(token_t::e_lsqrbracket))
   28226             :             {
   28227        6663 :                expression_node_ptr initialiser = parse_expression();
   28228             : 
   28229        6663 :                if (0 == initialiser)
   28230             :                {
   28231           0 :                   set_error(make_error(
   28232             :                      parser_error::e_syntax,
   28233           0 :                      current_token(),
   28234             :                      "ERR161 - Failed to parse single vector initialiser",
   28235             :                      exprtk_error_location));
   28236             : 
   28237           0 :                   return error_node();
   28238             :                }
   28239             : 
   28240        6663 :                vec_initilizer_list.push_back(initialiser);
   28241             : 
   28242        6663 :                if (!token_is(token_t::e_rsqrbracket))
   28243             :                {
   28244           0 :                   set_error(make_error(
   28245             :                      parser_error::e_syntax,
   28246           0 :                      current_token(),
   28247             :                      "ERR162 - Expected ']' to close single value vector initialiser",
   28248             :                      exprtk_error_location));
   28249             : 
   28250           0 :                   return error_node();
   28251             :                }
   28252             : 
   28253        6663 :                single_value_initialiser = true;
   28254             :             }
   28255       13031 :             else if (!token_is(token_t::e_lcrlbracket))
   28256             :             {
   28257         225 :                expression_node_ptr initialiser = error_node();
   28258             : 
   28259             :                // Is this a vector to vector assignment and initialisation?
   28260         225 :                if (token_t::e_symbol == current_token().type)
   28261             :                {
   28262             :                   // Is it a locally defined vector?
   28263         225 :                   const scope_element& se = sem_.get_active_element(current_token().value);
   28264             : 
   28265         225 :                   if (scope_element::e_vector == se.type)
   28266             :                   {
   28267         145 :                      if (0 != (initialiser = parse_expression()))
   28268         145 :                         vec_initilizer_list.push_back(initialiser);
   28269             :                      else
   28270           0 :                         return error_node();
   28271             :                   }
   28272             :                   // Are we dealing with a user defined vector?
   28273          80 :                   else if (symtab_store_.is_vector(current_token().value))
   28274             :                   {
   28275           0 :                      lodge_symbol(current_token().value, e_st_vector);
   28276             : 
   28277           0 :                      if (0 != (initialiser = parse_expression()))
   28278           0 :                         vec_initilizer_list.push_back(initialiser);
   28279             :                      else
   28280           0 :                         return error_node();
   28281             :                   }
   28282             :                   // Are we dealing with a null initialisation vector definition?
   28283         240 :                   else if (token_is(token_t::e_symbol,"null"))
   28284          80 :                      null_initialisation = true;
   28285             :                }
   28286             : 
   28287         225 :                if (!null_initialisation)
   28288             :                {
   28289         145 :                   if (0 == initialiser)
   28290             :                   {
   28291           0 :                      set_error(make_error(
   28292             :                         parser_error::e_syntax,
   28293           0 :                         current_token(),
   28294             :                         "ERR163 - Expected '{' as part of vector initialiser list",
   28295             :                         exprtk_error_location));
   28296             : 
   28297           0 :                      return error_node();
   28298             :                   }
   28299             :                   else
   28300         145 :                      vec_to_vec_initialiser = true;
   28301             :                }
   28302             :             }
   28303       12806 :             else if (!token_is(token_t::e_rcrlbracket))
   28304             :             {
   28305       30031 :                for ( ; ; )
   28306             :                {
   28307       42082 :                   expression_node_ptr initialiser = parse_expression();
   28308             : 
   28309       42082 :                   if (0 == initialiser)
   28310             :                   {
   28311           0 :                      set_error(make_error(
   28312             :                         parser_error::e_syntax,
   28313           0 :                         current_token(),
   28314             :                         "ERR164 - Expected '{' as part of vector initialiser list",
   28315             :                         exprtk_error_location));
   28316             : 
   28317           0 :                      return error_node();
   28318             :                   }
   28319             :                   else
   28320       42082 :                      vec_initilizer_list.push_back(initialiser);
   28321             : 
   28322       42082 :                   if (token_is(token_t::e_rcrlbracket))
   28323       12051 :                      break;
   28324             : 
   28325       30031 :                   const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
   28326             : 
   28327       30031 :                   if (!token_is(token_t::e_comma) && is_next_close)
   28328             :                   {
   28329           0 :                      set_error(make_error(
   28330             :                         parser_error::e_syntax,
   28331           0 :                         current_token(),
   28332             :                         "ERR165 - Expected ',' between vector initialisers",
   28333             :                         exprtk_error_location));
   28334             : 
   28335           0 :                      return error_node();
   28336             :                   }
   28337             : 
   28338       30031 :                   if (token_is(token_t::e_rcrlbracket))
   28339           0 :                      break;
   28340             :                }
   28341             :             }
   28342             : 
   28343       19694 :             if (
   28344       19694 :                  !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
   28345       37068 :                  !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
   28346       37068 :                  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
   28347             :                )
   28348             :             {
   28349       17374 :                if (!token_is(token_t::e_eof))
   28350             :                {
   28351           0 :                   set_error(make_error(
   28352             :                      parser_error::e_syntax,
   28353           0 :                      current_token(),
   28354             :                      "ERR166 - Expected ';' at end of vector definition",
   28355             :                      exprtk_error_location));
   28356             : 
   28357           0 :                   return error_node();
   28358             :                }
   28359             :             }
   28360             : 
   28361       19694 :             if (T(vec_initilizer_list.size()) > vector_size)
   28362             :             {
   28363           0 :                set_error(make_error(
   28364             :                   parser_error::e_syntax,
   28365           0 :                   current_token(),
   28366             :                   "ERR167 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
   28367             :                   exprtk_error_location));
   28368             : 
   28369           0 :                return error_node();
   28370             :             }
   28371             :          }
   28372             : 
   28373       19777 :          typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
   28374             : 
   28375       19777 :          const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
   28376             : 
   28377       19777 :          scope_element& se = sem_.get_element(vec_name);
   28378             : 
   28379       19777 :          if (se.name == vec_name)
   28380             :          {
   28381        1440 :             if (se.active)
   28382             :             {
   28383           0 :                set_error(make_error(
   28384             :                   parser_error::e_syntax,
   28385           0 :                   current_token(),
   28386             :                   "ERR168 - Illegal redefinition of local vector: '" + vec_name + "'",
   28387             :                   exprtk_error_location));
   28388             : 
   28389           0 :                return error_node();
   28390             :             }
   28391        1440 :             else if (
   28392        1440 :                       (se.size == vec_size) &&
   28393        1000 :                       (scope_element::e_vector == se.type)
   28394             :                     )
   28395             :             {
   28396        1000 :                vec_holder = se.vec_node;
   28397        1000 :                se.active  = true;
   28398        1000 :                se.depth   = state_.scope_depth;
   28399        1000 :                se.ref_count++;
   28400             :             }
   28401             :          }
   28402             : 
   28403       19777 :          if (0 == vec_holder)
   28404             :          {
   28405       18777 :             scope_element nse;
   28406       18777 :             nse.name      = vec_name;
   28407       18777 :             nse.active    = true;
   28408       18777 :             nse.ref_count = 1;
   28409       18777 :             nse.type      = scope_element::e_vector;
   28410       18777 :             nse.depth     = state_.scope_depth;
   28411       18777 :             nse.size      = vec_size;
   28412       18777 :             nse.data      = new T[vec_size];
   28413       18777 :             nse.vec_node  = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
   28414             : 
   28415       18777 :             std::memset(nse.data, 0x00, vec_size * sizeof(T));
   28416             : 
   28417       18777 :             if (!sem_.add_element(nse))
   28418             :             {
   28419           0 :                set_error(make_error(
   28420             :                   parser_error::e_syntax,
   28421           0 :                   current_token(),
   28422             :                   "ERR169 - Failed to add new local vector '" + vec_name + "' to SEM",
   28423             :                   exprtk_error_location));
   28424             : 
   28425           0 :                sem_.free_element(nse);
   28426             : 
   28427           0 :                return error_node();
   28428             :             }
   28429             : 
   28430       18777 :             vec_holder = nse.vec_node;
   28431             : 
   28432             :             exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
   28433             :                           nse.name.c_str(),
   28434             :                           static_cast<int>(nse.size)));
   28435       18777 :          }
   28436             : 
   28437       39554 :          state_.activate_side_effect("parse_define_vector_statement()");
   28438             : 
   28439       19777 :          lodge_symbol(vec_name, e_st_local_vector);
   28440             : 
   28441       19777 :          expression_node_ptr result = error_node();
   28442             : 
   28443       19777 :          if (!single_value_initialiser && vec_initilizer_list.empty())
   28444             :          {
   28445         918 :             single_value_initialiser = true;
   28446         918 :             assert(vec_initilizer_list.size() <= 1);
   28447             :          }
   28448             : 
   28449       19777 :          if (null_initialisation)
   28450          80 :             result = expression_generator_(T(0.0));
   28451       19697 :          else if (vec_to_vec_initialiser)
   28452             :          {
   28453         145 :             expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
   28454             : 
   28455         435 :             result = expression_generator_(
   28456         145 :                         details::e_assign,
   28457             :                         vec_node,
   28458         145 :                         vec_initilizer_list[0]);
   28459             :          }
   28460             :          else
   28461             :             result = node_allocator_
   28462       58656 :                         .allocate<details::vector_assignment_node<T> >(
   28463       19552 :                            (*vec_holder)[0],
   28464             :                            vec_size,
   28465             :                            vec_initilizer_list,
   28466             :                            single_value_initialiser);
   28467             : 
   28468       19777 :          svd.delete_ptr = (0 == result);
   28469             : 
   28470       19777 :          return result;
   28471       19777 :       }
   28472             : 
   28473             :       #ifndef exprtk_disable_string_capabilities
   28474        9565 :       inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
   28475             :       {
   28476        9565 :          stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
   28477             : 
   28478        9565 :          scope_element& se = sem_.get_element(str_name);
   28479             : 
   28480        9565 :          if (se.name == str_name)
   28481             :          {
   28482         120 :             if (se.active)
   28483             :             {
   28484           0 :                set_error(make_error(
   28485             :                   parser_error::e_syntax,
   28486           0 :                   current_token(),
   28487             :                   "ERR170 - Illegal redefinition of local variable: '" + str_name + "'",
   28488             :                   exprtk_error_location));
   28489             : 
   28490           0 :                free_node(node_allocator_,initialisation_expression);
   28491             : 
   28492           0 :                return error_node();
   28493             :             }
   28494         120 :             else if (scope_element::e_string == se.type)
   28495             :             {
   28496          80 :                str_node  = se.str_node;
   28497          80 :                se.active = true;
   28498          80 :                se.depth  = state_.scope_depth;
   28499          80 :                se.ref_count++;
   28500             :             }
   28501             :          }
   28502             : 
   28503        9565 :          if (0 == str_node)
   28504             :          {
   28505        9485 :             scope_element nse;
   28506        9485 :             nse.name      = str_name;
   28507        9485 :             nse.active    = true;
   28508        9485 :             nse.ref_count = 1;
   28509        9485 :             nse.type      = scope_element::e_string;
   28510        9485 :             nse.depth     = state_.scope_depth;
   28511        9485 :             nse.data      = new std::string;
   28512        9485 :             nse.str_node  = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data));
   28513             : 
   28514        9485 :             if (!sem_.add_element(nse))
   28515             :             {
   28516           0 :                set_error(make_error(
   28517             :                   parser_error::e_syntax,
   28518           0 :                   current_token(),
   28519             :                   "ERR171 - Failed to add new local string variable '" + str_name + "' to SEM",
   28520             :                   exprtk_error_location));
   28521             : 
   28522           0 :                free_node(node_allocator_,initialisation_expression);
   28523             : 
   28524           0 :                sem_.free_element(nse);
   28525             : 
   28526           0 :                return error_node();
   28527             :             }
   28528             : 
   28529        9485 :             str_node = nse.str_node;
   28530             : 
   28531             :             exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str()));
   28532        9485 :          }
   28533             : 
   28534        9565 :          lodge_symbol(str_name, e_st_local_string);
   28535             : 
   28536       19130 :          state_.activate_side_effect("parse_define_string_statement()");
   28537             : 
   28538        9565 :          expression_node_ptr branch[2] = {0};
   28539             : 
   28540        9565 :          branch[0] = str_node;
   28541        9565 :          branch[1] = initialisation_expression;
   28542             : 
   28543        9565 :          return expression_generator_(details::e_assign,branch);
   28544             :       }
   28545             :       #else
   28546             :       inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
   28547             :       {
   28548             :          return error_node();
   28549             :       }
   28550             :       #endif
   28551             : 
   28552       56410 :       inline bool local_variable_is_shadowed(const std::string& symbol)
   28553             :       {
   28554       56410 :          const scope_element& se = sem_.get_element(symbol);
   28555       56410 :          return (se.name == symbol) && se.active;
   28556             :       }
   28557             : 
   28558       56410 :       inline expression_node_ptr parse_define_var_statement()
   28559             :       {
   28560       56410 :          if (settings_.vardef_disabled())
   28561             :          {
   28562           0 :             set_error(make_error(
   28563             :                parser_error::e_syntax,
   28564           0 :                current_token(),
   28565             :                "ERR172 - Illegal variable definition",
   28566             :                exprtk_error_location));
   28567             : 
   28568           0 :             return error_node();
   28569             :          }
   28570      112820 :          else if (!details::imatch(current_token().value,"var"))
   28571             :          {
   28572           0 :             return error_node();
   28573             :          }
   28574             :          else
   28575       56410 :             next_token();
   28576             : 
   28577       56410 :          const std::string var_name = current_token().value;
   28578             : 
   28579       56410 :          expression_node_ptr initialisation_expression = error_node();
   28580             : 
   28581       56410 :          if (!token_is(token_t::e_symbol))
   28582             :          {
   28583           0 :             set_error(make_error(
   28584             :                parser_error::e_syntax,
   28585           0 :                current_token(),
   28586             :                "ERR173 - Expected a symbol for variable definition",
   28587             :                exprtk_error_location));
   28588             : 
   28589           0 :             return error_node();
   28590             :          }
   28591       56410 :          else if (details::is_reserved_symbol(var_name))
   28592             :          {
   28593           0 :             set_error(make_error(
   28594             :                parser_error::e_syntax,
   28595           0 :                current_token(),
   28596             :                "ERR174 - Illegal redefinition of reserved keyword: '" + var_name + "'",
   28597             :                exprtk_error_location));
   28598             : 
   28599           0 :             return error_node();
   28600             :          }
   28601       56410 :          else if (symtab_store_.symbol_exists(var_name))
   28602             :          {
   28603           0 :             set_error(make_error(
   28604             :                parser_error::e_syntax,
   28605           0 :                current_token(),
   28606             :                "ERR175 - Illegal redefinition of variable '" + var_name + "'",
   28607             :                exprtk_error_location));
   28608             : 
   28609           0 :             return error_node();
   28610             :          }
   28611       56410 :          else if (local_variable_is_shadowed(var_name))
   28612             :          {
   28613           0 :             set_error(make_error(
   28614             :                parser_error::e_syntax,
   28615           0 :                current_token(),
   28616             :                "ERR176 - Illegal redefinition of local variable: '" + var_name + "'",
   28617             :                exprtk_error_location));
   28618             : 
   28619           0 :             return error_node();
   28620             :          }
   28621       56410 :          else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
   28622             :          {
   28623       19777 :             return parse_define_vector_statement(var_name);
   28624             :          }
   28625       36633 :          else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
   28626             :          {
   28627        2140 :             return parse_uninitialised_var_statement(var_name);
   28628             :          }
   28629       34493 :          else if (token_is(token_t::e_assign))
   28630             :          {
   28631       34420 :             if (0 == (initialisation_expression = parse_expression()))
   28632             :             {
   28633           0 :                set_error(make_error(
   28634             :                   parser_error::e_syntax,
   28635           0 :                   current_token(),
   28636             :                   "ERR177 - Failed to parse initialisation expression",
   28637             :                   exprtk_error_location));
   28638             : 
   28639           0 :                return error_node();
   28640             :             }
   28641             :          }
   28642             : 
   28643       34493 :          if (
   28644       34493 :               !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
   28645       67866 :               !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
   28646       67866 :               !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
   28647             :             )
   28648             :          {
   28649       33373 :             if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
   28650             :             {
   28651           0 :                set_error(make_error(
   28652             :                   parser_error::e_syntax,
   28653           0 :                   current_token(),
   28654             :                   "ERR178 - Expected ';' after variable definition",
   28655             :                   exprtk_error_location));
   28656             : 
   28657           0 :                free_node(node_allocator_,initialisation_expression);
   28658             : 
   28659           0 :                return error_node();
   28660             :             }
   28661             :          }
   28662             : 
   28663       34493 :          if (
   28664       68913 :               (0 != initialisation_expression) &&
   28665       34420 :               details::is_generally_string_node(initialisation_expression)
   28666             :             )
   28667             :          {
   28668        9565 :             return parse_define_string_statement(var_name,initialisation_expression);
   28669             :          }
   28670             : 
   28671       24928 :          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
   28672             : 
   28673       24928 :          scope_element& se = sem_.get_element(var_name);
   28674             : 
   28675       24928 :          if (se.name == var_name)
   28676             :          {
   28677        1041 :             if (se.active)
   28678             :             {
   28679           0 :                set_error(make_error(
   28680             :                   parser_error::e_syntax,
   28681           0 :                   current_token(),
   28682             :                   "ERR179 - Illegal redefinition of local variable: '" + var_name + "'",
   28683             :                   exprtk_error_location));
   28684             : 
   28685           0 :                free_node(node_allocator_, initialisation_expression);
   28686             : 
   28687           0 :                return error_node();
   28688             :             }
   28689        1041 :             else if (scope_element::e_variable == se.type)
   28690             :             {
   28691         561 :                var_node  = se.var_node;
   28692         561 :                se.active = true;
   28693         561 :                se.depth  = state_.scope_depth;
   28694         561 :                se.ref_count++;
   28695             :             }
   28696             :          }
   28697             : 
   28698       24928 :          if (0 == var_node)
   28699             :          {
   28700       24367 :             scope_element nse;
   28701       24367 :             nse.name      = var_name;
   28702       24367 :             nse.active    = true;
   28703       24367 :             nse.ref_count = 1;
   28704       24367 :             nse.type      = scope_element::e_variable;
   28705       24367 :             nse.depth     = state_.scope_depth;
   28706       24367 :             nse.data      = new T(T(0));
   28707       24367 :             nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
   28708             : 
   28709       24367 :             if (!sem_.add_element(nse))
   28710             :             {
   28711           0 :                set_error(make_error(
   28712             :                   parser_error::e_syntax,
   28713           0 :                   current_token(),
   28714             :                   "ERR180 - Failed to add new local variable '" + var_name + "' to SEM",
   28715             :                   exprtk_error_location));
   28716             : 
   28717           0 :                free_node(node_allocator_, initialisation_expression);
   28718             : 
   28719           0 :                sem_.free_element(nse);
   28720             : 
   28721           0 :                return error_node();
   28722             :             }
   28723             : 
   28724       24367 :             var_node = nse.var_node;
   28725             : 
   28726             :             exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str()));
   28727       24367 :          }
   28728             : 
   28729       49856 :          state_.activate_side_effect("parse_define_var_statement()");
   28730             : 
   28731       24928 :          lodge_symbol(var_name, e_st_local_variable);
   28732             : 
   28733       24928 :          expression_node_ptr branch[2] = {0};
   28734             : 
   28735       24928 :          branch[0] = var_node;
   28736       24928 :          branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
   28737             : 
   28738       24928 :          return expression_generator_(details::e_assign,branch);
   28739       56410 :       }
   28740             : 
   28741        2140 :       inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
   28742             :       {
   28743        2140 :          if (
   28744        4280 :               !token_is(token_t::e_lcrlbracket) ||
   28745        4280 :               !token_is(token_t::e_rcrlbracket)
   28746             :             )
   28747             :          {
   28748           0 :             set_error(make_error(
   28749             :                parser_error::e_syntax,
   28750           0 :                current_token(),
   28751             :                "ERR181 - Expected a '{}' for uninitialised var definition",
   28752             :                exprtk_error_location));
   28753             : 
   28754           0 :             return error_node();
   28755             :          }
   28756        2140 :          else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
   28757             :          {
   28758           0 :             set_error(make_error(
   28759             :                parser_error::e_syntax,
   28760           0 :                current_token(),
   28761             :                "ERR182 - Expected ';' after uninitialised variable definition",
   28762             :                exprtk_error_location));
   28763             : 
   28764           0 :             return error_node();
   28765             :          }
   28766             : 
   28767        2140 :          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
   28768             : 
   28769        2140 :          scope_element& se = sem_.get_element(var_name);
   28770             : 
   28771        2140 :          if (se.name == var_name)
   28772             :          {
   28773           0 :             if (se.active)
   28774             :             {
   28775           0 :                set_error(make_error(
   28776             :                   parser_error::e_syntax,
   28777           0 :                   current_token(),
   28778             :                   "ERR183 - Illegal redefinition of local variable: '" + var_name + "'",
   28779             :                   exprtk_error_location));
   28780             : 
   28781           0 :                return error_node();
   28782             :             }
   28783           0 :             else if (scope_element::e_variable == se.type)
   28784             :             {
   28785           0 :                var_node  = se.var_node;
   28786           0 :                se.active = true;
   28787           0 :                se.ref_count++;
   28788             :             }
   28789             :          }
   28790             : 
   28791        2140 :          if (0 == var_node)
   28792             :          {
   28793        2140 :             scope_element nse;
   28794        2140 :             nse.name      = var_name;
   28795        2140 :             nse.active    = true;
   28796        2140 :             nse.ref_count = 1;
   28797        2140 :             nse.type      = scope_element::e_variable;
   28798        2140 :             nse.depth     = state_.scope_depth;
   28799        2140 :             nse.ip_index  = sem_.next_ip_index();
   28800        2140 :             nse.data      = new T(T(0));
   28801        2140 :             nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
   28802             : 
   28803        2140 :             if (!sem_.add_element(nse))
   28804             :             {
   28805           0 :                set_error(make_error(
   28806             :                   parser_error::e_syntax,
   28807           0 :                   current_token(),
   28808             :                   "ERR184 - Failed to add new local variable '" + var_name + "' to SEM",
   28809             :                   exprtk_error_location));
   28810             : 
   28811           0 :                sem_.free_element(nse);
   28812             : 
   28813           0 :                return error_node();
   28814             :             }
   28815             : 
   28816             :             exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
   28817             :                           nse.name.c_str()));
   28818        2140 :          }
   28819             : 
   28820        2140 :          lodge_symbol(var_name, e_st_local_variable);
   28821             : 
   28822        4280 :          state_.activate_side_effect("parse_uninitialised_var_statement()");
   28823             : 
   28824        2140 :          return expression_generator_(T(0));
   28825             :       }
   28826             : 
   28827         560 :       inline expression_node_ptr parse_swap_statement()
   28828             :       {
   28829        1120 :          if (!details::imatch(current_token().value,"swap"))
   28830             :          {
   28831           0 :             return error_node();
   28832             :          }
   28833             :          else
   28834         560 :             next_token();
   28835             : 
   28836         560 :          if (!token_is(token_t::e_lbracket))
   28837             :          {
   28838           0 :             set_error(make_error(
   28839             :                parser_error::e_syntax,
   28840           0 :                current_token(),
   28841             :                "ERR185 - Expected '(' at start of swap statement",
   28842             :                exprtk_error_location));
   28843             : 
   28844           0 :             return error_node();
   28845             :          }
   28846             : 
   28847         560 :          expression_node_ptr variable0 = error_node();
   28848         560 :          expression_node_ptr variable1 = error_node();
   28849             : 
   28850         560 :          bool variable0_generated = false;
   28851         560 :          bool variable1_generated = false;
   28852             : 
   28853         560 :          const std::string var0_name = current_token().value;
   28854             : 
   28855         560 :          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
   28856             :          {
   28857           0 :             set_error(make_error(
   28858             :                parser_error::e_syntax,
   28859           0 :                current_token(),
   28860             :                "ERR186 - Expected a symbol for variable or vector element definition",
   28861             :                exprtk_error_location));
   28862             : 
   28863           0 :             return error_node();
   28864             :          }
   28865         560 :          else if (peek_token_is(token_t::e_lsqrbracket))
   28866             :          {
   28867         360 :             if (0 == (variable0 = parse_vector()))
   28868             :             {
   28869           0 :                set_error(make_error(
   28870             :                   parser_error::e_syntax,
   28871           0 :                   current_token(),
   28872             :                   "ERR187 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
   28873             :                   exprtk_error_location));
   28874             : 
   28875           0 :                return error_node();
   28876             :             }
   28877             : 
   28878         360 :             variable0_generated = true;
   28879             :          }
   28880             :          else
   28881             :          {
   28882         200 :             if (symtab_store_.is_variable(var0_name))
   28883             :             {
   28884           0 :                variable0 = symtab_store_.get_variable(var0_name);
   28885             :             }
   28886             : 
   28887         200 :             const scope_element& se = sem_.get_element(var0_name);
   28888             : 
   28889         200 :             if (
   28890         200 :                  (se.active)            &&
   28891         400 :                  (se.name == var0_name) &&
   28892         200 :                  (scope_element::e_variable == se.type)
   28893             :                )
   28894             :             {
   28895         200 :                variable0 = se.var_node;
   28896             :             }
   28897             : 
   28898         200 :             lodge_symbol(var0_name, e_st_variable);
   28899             : 
   28900         200 :             if (0 == variable0)
   28901             :             {
   28902           0 :                set_error(make_error(
   28903             :                   parser_error::e_syntax,
   28904           0 :                   current_token(),
   28905             :                   "ERR188 - First parameter to swap is an invalid variable: '" + var0_name + "'",
   28906             :                   exprtk_error_location));
   28907             : 
   28908           0 :                return error_node();
   28909             :             }
   28910             :             else
   28911         200 :                next_token();
   28912             :          }
   28913             : 
   28914         560 :          if (!token_is(token_t::e_comma))
   28915             :          {
   28916           0 :             set_error(make_error(
   28917             :                parser_error::e_syntax,
   28918           0 :                current_token(),
   28919             :                "ERR189 - Expected ',' between parameters to swap",
   28920             :                exprtk_error_location));
   28921             : 
   28922           0 :             if (variable0_generated)
   28923             :             {
   28924           0 :                free_node(node_allocator_,variable0);
   28925             :             }
   28926             : 
   28927           0 :             return error_node();
   28928             :          }
   28929             : 
   28930         560 :          const std::string var1_name = current_token().value;
   28931             : 
   28932         560 :          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
   28933             :          {
   28934           0 :             set_error(make_error(
   28935             :                parser_error::e_syntax,
   28936           0 :                current_token(),
   28937             :                "ERR190 - Expected a symbol for variable or vector element definition",
   28938             :                exprtk_error_location));
   28939             : 
   28940           0 :             if (variable0_generated)
   28941             :             {
   28942           0 :                free_node(node_allocator_,variable0);
   28943             :             }
   28944             : 
   28945           0 :             return error_node();
   28946             :          }
   28947         560 :          else if (peek_token_is(token_t::e_lsqrbracket))
   28948             :          {
   28949         360 :             if (0 == (variable1 = parse_vector()))
   28950             :             {
   28951           0 :                set_error(make_error(
   28952             :                   parser_error::e_syntax,
   28953           0 :                   current_token(),
   28954             :                   "ERR191 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
   28955             :                   exprtk_error_location));
   28956             : 
   28957           0 :                if (variable0_generated)
   28958             :                {
   28959           0 :                   free_node(node_allocator_,variable0);
   28960             :                }
   28961             : 
   28962           0 :                return error_node();
   28963             :             }
   28964             : 
   28965         360 :             variable1_generated = true;
   28966             :          }
   28967             :          else
   28968             :          {
   28969         200 :             if (symtab_store_.is_variable(var1_name))
   28970             :             {
   28971           0 :                variable1 = symtab_store_.get_variable(var1_name);
   28972             :             }
   28973             : 
   28974         200 :             const scope_element& se = sem_.get_element(var1_name);
   28975             : 
   28976         200 :             if (
   28977         200 :                  (se.active) &&
   28978         400 :                  (se.name == var1_name) &&
   28979         200 :                  (scope_element::e_variable == se.type)
   28980             :                )
   28981             :             {
   28982         200 :                variable1 = se.var_node;
   28983             :             }
   28984             : 
   28985         200 :             lodge_symbol(var1_name, e_st_variable);
   28986             : 
   28987         200 :             if (0 == variable1)
   28988             :             {
   28989           0 :                set_error(make_error(
   28990             :                   parser_error::e_syntax,
   28991           0 :                   current_token(),
   28992             :                   "ERR192 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
   28993             :                   exprtk_error_location));
   28994             : 
   28995           0 :                if (variable0_generated)
   28996             :                {
   28997           0 :                   free_node(node_allocator_,variable0);
   28998             :                }
   28999             : 
   29000           0 :                return error_node();
   29001             :             }
   29002             :             else
   29003         200 :                next_token();
   29004             :          }
   29005             : 
   29006         560 :          if (!token_is(token_t::e_rbracket))
   29007             :          {
   29008           0 :             set_error(make_error(
   29009             :                parser_error::e_syntax,
   29010           0 :                current_token(),
   29011             :                "ERR193 - Expected ')' at end of swap statement",
   29012             :                exprtk_error_location));
   29013             : 
   29014           0 :             if (variable0_generated)
   29015             :             {
   29016           0 :                free_node(node_allocator_,variable0);
   29017             :             }
   29018             : 
   29019           0 :             if (variable1_generated)
   29020             :             {
   29021           0 :                free_node(node_allocator_,variable1);
   29022             :             }
   29023             : 
   29024           0 :             return error_node();
   29025             :          }
   29026             : 
   29027             :          typedef details::variable_node<T>* variable_node_ptr;
   29028             : 
   29029         560 :          variable_node_ptr v0 = variable_node_ptr(0);
   29030         560 :          variable_node_ptr v1 = variable_node_ptr(0);
   29031             : 
   29032         560 :          expression_node_ptr result = error_node();
   29033             : 
   29034         560 :          if (
   29035         880 :               (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
   29036         320 :               (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
   29037             :             )
   29038             :          {
   29039         240 :             result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
   29040             : 
   29041         240 :             if (variable0_generated)
   29042             :             {
   29043         120 :                free_node(node_allocator_,variable0);
   29044             :             }
   29045             : 
   29046         240 :             if (variable1_generated)
   29047             :             {
   29048         120 :                free_node(node_allocator_,variable1);
   29049             :             }
   29050             :          }
   29051             :          else
   29052             :             result = node_allocator_.allocate<details::swap_generic_node<T> >
   29053         320 :                         (variable0, variable1);
   29054             : 
   29055        1120 :          state_.activate_side_effect("parse_swap_statement()");
   29056             : 
   29057         560 :          return result;
   29058         560 :       }
   29059             : 
   29060             :       #ifndef exprtk_disable_return_statement
   29061         116 :       inline expression_node_ptr parse_return_statement()
   29062             :       {
   29063         116 :          if (state_.parsing_return_stmt)
   29064             :          {
   29065           0 :             set_error(make_error(
   29066             :                parser_error::e_syntax,
   29067           0 :                current_token(),
   29068             :                "ERR194 - Return call within a return call is not allowed",
   29069             :                exprtk_error_location));
   29070             : 
   29071           0 :             return error_node();
   29072             :          }
   29073             : 
   29074         116 :          scoped_bool_negator sbn(state_.parsing_return_stmt);
   29075             : 
   29076         116 :          std::vector<expression_node_ptr> arg_list;
   29077             : 
   29078         116 :          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
   29079             : 
   29080         232 :          if (!details::imatch(current_token().value,"return"))
   29081             :          {
   29082           0 :             return error_node();
   29083             :          }
   29084             :          else
   29085         116 :             next_token();
   29086             : 
   29087         116 :          if (!token_is(token_t::e_lsqrbracket))
   29088             :          {
   29089           0 :             set_error(make_error(
   29090             :                parser_error::e_syntax,
   29091           0 :                current_token(),
   29092             :                "ERR195 - Expected '[' at start of return statement",
   29093             :                exprtk_error_location));
   29094             : 
   29095           0 :             return error_node();
   29096             :          }
   29097         116 :          else if (!token_is(token_t::e_rsqrbracket))
   29098             :          {
   29099          32 :             for ( ; ; )
   29100             :             {
   29101         147 :                expression_node_ptr arg = parse_expression();
   29102             : 
   29103         147 :                if (0 == arg)
   29104           0 :                   return error_node();
   29105             : 
   29106         147 :                arg_list.push_back(arg);
   29107             : 
   29108         147 :                if (token_is(token_t::e_rsqrbracket))
   29109         115 :                   break;
   29110          32 :                else if (!token_is(token_t::e_comma))
   29111             :                {
   29112           0 :                   set_error(make_error(
   29113             :                      parser_error::e_syntax,
   29114           0 :                      current_token(),
   29115             :                      "ERR196 - Expected ',' between values during call to return",
   29116             :                      exprtk_error_location));
   29117             : 
   29118           0 :                   return error_node();
   29119             :                }
   29120             :             }
   29121             :          }
   29122           1 :          else if (settings_.zero_return_disabled())
   29123             :          {
   29124           0 :             set_error(make_error(
   29125             :                parser_error::e_syntax,
   29126           0 :                current_token(),
   29127             :                "ERR197 - Zero parameter return statement not allowed",
   29128             :                exprtk_error_location));
   29129             : 
   29130           0 :             return error_node();
   29131             :          }
   29132             : 
   29133         116 :          const lexer::token prev_token = current_token();
   29134             : 
   29135         116 :          if (token_is(token_t::e_rsqrbracket))
   29136             :          {
   29137           0 :             if (!arg_list.empty())
   29138             :             {
   29139           0 :                set_error(make_error(
   29140             :                   parser_error::e_syntax,
   29141             :                   prev_token,
   29142             :                   "ERR198 - Invalid ']' found during return call",
   29143             :                   exprtk_error_location));
   29144             : 
   29145           0 :                return error_node();
   29146             :             }
   29147             :          }
   29148             : 
   29149         116 :          std::string ret_param_type_list;
   29150             : 
   29151         263 :          for (std::size_t i = 0; i < arg_list.size(); ++i)
   29152             :          {
   29153         147 :             if (0 == arg_list[i])
   29154           0 :                return error_node();
   29155         147 :             else if (is_ivector_node(arg_list[i]))
   29156           1 :                ret_param_type_list += 'V';
   29157         146 :             else if (is_generally_string_node(arg_list[i]))
   29158          16 :                ret_param_type_list += 'S';
   29159             :             else
   29160         130 :                ret_param_type_list += 'T';
   29161             :          }
   29162             : 
   29163         116 :          dec_.retparam_list_.push_back(ret_param_type_list);
   29164             : 
   29165         116 :          expression_node_ptr result = expression_generator_.return_call(arg_list);
   29166             : 
   29167         116 :          sdd.delete_ptr = (0 == result);
   29168             : 
   29169         116 :          state_.return_stmt_present = true;
   29170             : 
   29171         232 :          state_.activate_side_effect("parse_return_statement()");
   29172             : 
   29173         116 :          return result;
   29174         116 :       }
   29175             :       #else
   29176             :       inline expression_node_ptr parse_return_statement()
   29177             :       {
   29178             :          return error_node();
   29179             :       }
   29180             :       #endif
   29181             : 
   29182     1843857 :       inline bool post_variable_process(const std::string& symbol)
   29183             :       {
   29184     1843857 :          if (
   29185     3687290 :               peek_token_is(token_t::e_lbracket   ) ||
   29186     3687290 :               peek_token_is(token_t::e_lcrlbracket) ||
   29187     3687290 :               peek_token_is(token_t::e_lsqrbracket)
   29188             :             )
   29189             :          {
   29190         426 :             if (!settings_.commutative_check_enabled())
   29191             :             {
   29192           0 :                set_error(make_error(
   29193             :                   parser_error::e_syntax,
   29194           0 :                   current_token(),
   29195             :                   "ERR199 - Invalid sequence of variable '" + symbol + "' and bracket",
   29196             :                   exprtk_error_location));
   29197             : 
   29198           0 :                return false;
   29199             :             }
   29200             : 
   29201         426 :             lexer().insert_front(token_t::e_mul);
   29202             :          }
   29203             : 
   29204     1843857 :          return true;
   29205             :       }
   29206             : 
   29207     1709652 :       inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
   29208             :       {
   29209     1709652 :          bool implied_mul = false;
   29210             : 
   29211     1709652 :          if (details::is_generally_string_node(branch))
   29212        9863 :             return true;
   29213             : 
   29214     1699789 :          const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
   29215             : 
   29216     1699789 :          switch (token)
   29217             :          {
   29218        2145 :             case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
   29219        3810 :                                                         token_is(token_t::e_lcrlbracket,hold) ||
   29220        1665 :                                                         token_is(token_t::e_lsqrbracket,hold) ;
   29221        2145 :                                           break;
   29222             : 
   29223     1691559 :             case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
   29224     3382638 :                                                         token_is(token_t::e_lcrlbracket,hold) ||
   29225     1691079 :                                                         token_is(token_t::e_lsqrbracket,hold) ;
   29226     1691559 :                                           break;
   29227             : 
   29228        6085 :             case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
   29229       12170 :                                                         token_is(token_t::e_lcrlbracket,hold) ||
   29230        6085 :                                                         token_is(token_t::e_lsqrbracket,hold) ;
   29231        6085 :                                           break;
   29232             : 
   29233           0 :             default                     : return true;
   29234             :          }
   29235             : 
   29236     1699789 :          if (implied_mul)
   29237             :          {
   29238        1815 :             if (!settings_.commutative_check_enabled())
   29239             :             {
   29240           0 :                set_error(make_error(
   29241             :                   parser_error::e_syntax,
   29242           0 :                   current_token(),
   29243             :                   "ERR200 - Invalid sequence of brackets",
   29244             :                   exprtk_error_location));
   29245             : 
   29246           0 :                return false;
   29247             :             }
   29248        1815 :             else if (token_t::e_eof != current_token().type)
   29249             :             {
   29250        1815 :                lexer().insert_front(current_token().type);
   29251        1815 :                lexer().insert_front(token_t::e_mul);
   29252        1815 :                next_token();
   29253             :             }
   29254             :          }
   29255             : 
   29256     1699789 :          return true;
   29257             :       }
   29258             : 
   29259             :       typedef typename interval_container_t<const void*>::interval_t interval_t;
   29260             :       typedef interval_container_t<const void*> immutable_memory_map_t;
   29261             :       typedef std::map<interval_t,token_t> immutable_symtok_map_t;
   29262             : 
   29263          18 :       inline interval_t make_memory_range(const T& t)
   29264             :       {
   29265          18 :          const T* begin = reinterpret_cast<const T*>(&t);
   29266          18 :          const T* end   = begin + 1;
   29267          18 :          return interval_t(begin, end);
   29268             :       }
   29269             : 
   29270          13 :       inline interval_t make_memory_range(const T* begin, const std::size_t size)
   29271             :       {
   29272          13 :          return interval_t(begin, begin + size);
   29273             :       }
   29274             : 
   29275          24 :       inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size)
   29276             :       {
   29277          24 :          return interval_t(begin, begin + size);
   29278             :       }
   29279             : 
   29280          55 :       void lodge_immutable_symbol(const lexer::token& token, const interval_t interval)
   29281             :       {
   29282          55 :          immutable_memory_map_.add_interval(interval);
   29283          55 :          immutable_symtok_map_[interval] = token;
   29284          55 :       }
   29285             : 
   29286     2030084 :       inline expression_node_ptr parse_symtab_symbol()
   29287             :       {
   29288     2030084 :          const std::string symbol = current_token().value;
   29289             : 
   29290             :          // Are we dealing with a variable or a special constant?
   29291             :          typedef typename symtab_store::variable_context var_ctxt_t;
   29292     2030084 :          var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol);
   29293             : 
   29294     2030084 :          if (var_ctx.variable)
   29295             :          {
   29296     1800368 :             assert(var_ctx.symbol_table);
   29297             : 
   29298     1800368 :             expression_node_ptr result_variable = var_ctx.variable;
   29299             : 
   29300     1800368 :             if (symtab_store_.is_constant_node(symbol))
   29301             :             {
   29302       43085 :                result_variable = expression_generator_(var_ctx.variable->value());
   29303             :             }
   29304     1757283 :             else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability())
   29305             :             {
   29306          18 :                lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref()));
   29307          18 :                result_variable = var_ctx.variable;
   29308             :             }
   29309             : 
   29310     1800368 :             if (!post_variable_process(symbol))
   29311           0 :                return error_node();
   29312             : 
   29313     1800368 :             lodge_symbol(symbol, e_st_variable);
   29314             : 
   29315     1800368 :             next_token();
   29316             : 
   29317     1800368 :             return result_variable;
   29318             :          }
   29319             : 
   29320             :          // Are we dealing with a locally defined variable, vector or string?
   29321      229716 :          if (!sem_.empty())
   29322             :          {
   29323      103240 :             scope_element& se = sem_.get_active_element(symbol);
   29324             : 
   29325      103240 :             if (se.active && details::imatch(se.name, symbol))
   29326             :             {
   29327       94890 :                if (scope_element::e_variable == se.type)
   29328             :                {
   29329       40487 :                   se.active = true;
   29330       40487 :                   lodge_symbol(symbol, e_st_local_variable);
   29331             : 
   29332       40487 :                   if (!post_variable_process(symbol))
   29333           0 :                      return error_node();
   29334             : 
   29335       40487 :                   next_token();
   29336             : 
   29337       40487 :                   return se.var_node;
   29338             :                }
   29339       54403 :                else if (scope_element::e_vector == se.type)
   29340             :                {
   29341       35628 :                   return parse_vector();
   29342             :                }
   29343             :                #ifndef exprtk_disable_string_capabilities
   29344       18775 :                else if (scope_element::e_string == se.type)
   29345             :                {
   29346       18775 :                   return parse_string();
   29347             :                }
   29348             :                #endif
   29349             :             }
   29350             :          }
   29351             : 
   29352             :          #ifndef exprtk_disable_string_capabilities
   29353             :          // Are we dealing with a string variable?
   29354      134826 :          if (symtab_store_.is_stringvar(symbol))
   29355             :          {
   29356       49475 :             return parse_string();
   29357             :          }
   29358             :          #endif
   29359             : 
   29360             :          {
   29361             :             // Are we dealing with a function?
   29362       85351 :             ifunction<T>* function = symtab_store_.get_function(symbol);
   29363             : 
   29364       85351 :             if (function)
   29365             :             {
   29366       60611 :                lodge_symbol(symbol, e_st_function);
   29367             : 
   29368             :                expression_node_ptr func_node =
   29369       60611 :                                       parse_function_invocation(function,symbol);
   29370             : 
   29371       60611 :                if (func_node)
   29372       60611 :                   return func_node;
   29373             :                else
   29374             :                {
   29375           0 :                   set_error(make_error(
   29376             :                      parser_error::e_syntax,
   29377           0 :                      current_token(),
   29378             :                      "ERR201 - Failed to generate node for function: '" + symbol + "'",
   29379             :                      exprtk_error_location));
   29380             : 
   29381           0 :                   return error_node();
   29382             :                }
   29383             :             }
   29384             :          }
   29385             : 
   29386             :          {
   29387             :             // Are we dealing with a vararg function?
   29388       24740 :             ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
   29389             : 
   29390       24740 :             if (vararg_function)
   29391             :             {
   29392          49 :                lodge_symbol(symbol, e_st_function);
   29393             : 
   29394             :                expression_node_ptr vararg_func_node =
   29395          49 :                                       parse_vararg_function_call(vararg_function, symbol);
   29396             : 
   29397          49 :                if (vararg_func_node)
   29398          49 :                   return vararg_func_node;
   29399             :                else
   29400             :                {
   29401           0 :                   set_error(make_error(
   29402             :                      parser_error::e_syntax,
   29403           0 :                      current_token(),
   29404             :                      "ERR202 - Failed to generate node for vararg function: '" + symbol + "'",
   29405             :                      exprtk_error_location));
   29406             : 
   29407           0 :                   return error_node();
   29408             :                }
   29409             :             }
   29410             :          }
   29411             : 
   29412             :          {
   29413             :             // Are we dealing with a vararg generic function?
   29414       24691 :             igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
   29415             : 
   29416       24691 :             if (generic_function)
   29417             :             {
   29418        1825 :                lodge_symbol(symbol, e_st_function);
   29419             : 
   29420             :                expression_node_ptr genericfunc_node =
   29421        1825 :                                       parse_generic_function_call(generic_function, symbol);
   29422             : 
   29423        1825 :                if (genericfunc_node)
   29424        1825 :                   return genericfunc_node;
   29425             :                else
   29426             :                {
   29427           0 :                   set_error(make_error(
   29428             :                      parser_error::e_syntax,
   29429           0 :                      current_token(),
   29430             :                      "ERR203 - Failed to generate node for generic function: '" + symbol + "'",
   29431             :                      exprtk_error_location));
   29432             : 
   29433           0 :                   return error_node();
   29434             :                }
   29435             :             }
   29436             :          }
   29437             : 
   29438             :          #ifndef exprtk_disable_string_capabilities
   29439             :          {
   29440             :             // Are we dealing with a vararg string returning function?
   29441       22866 :             igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
   29442             : 
   29443       22866 :             if (string_function)
   29444             :             {
   29445          36 :                lodge_symbol(symbol, e_st_function);
   29446             : 
   29447             :                expression_node_ptr stringfunc_node =
   29448          36 :                                       parse_string_function_call(string_function, symbol);
   29449             : 
   29450          36 :                if (stringfunc_node)
   29451          36 :                   return stringfunc_node;
   29452             :                else
   29453             :                {
   29454           0 :                   set_error(make_error(
   29455             :                      parser_error::e_syntax,
   29456           0 :                      current_token(),
   29457             :                      "ERR204 - Failed to generate node for string function: '" + symbol + "'",
   29458             :                      exprtk_error_location));
   29459             : 
   29460           0 :                   return error_node();
   29461             :                }
   29462             :             }
   29463             :          }
   29464             : 
   29465             :          {
   29466             :             // Are we dealing with a vararg overloaded scalar/string returning function?
   29467       22830 :             igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
   29468             : 
   29469       22830 :             if (overload_function)
   29470             :             {
   29471          72 :                lodge_symbol(symbol, e_st_function);
   29472             : 
   29473             :                expression_node_ptr overloadfunc_node =
   29474          72 :                                       parse_overload_function_call(overload_function, symbol);
   29475             : 
   29476          72 :                if (overloadfunc_node)
   29477          72 :                   return overloadfunc_node;
   29478             :                else
   29479             :                {
   29480           0 :                   set_error(make_error(
   29481             :                      parser_error::e_syntax,
   29482           0 :                      current_token(),
   29483             :                      "ERR205 - Failed to generate node for overload function: '" + symbol + "'",
   29484             :                      exprtk_error_location));
   29485             : 
   29486           0 :                   return error_node();
   29487             :                }
   29488             :             }
   29489             :          }
   29490             :          #endif
   29491             : 
   29492             :          // Are we dealing with a vector?
   29493       22758 :          if (symtab_store_.is_vector(symbol))
   29494             :          {
   29495        6869 :             lodge_symbol(symbol, e_st_vector);
   29496        6869 :             return parse_vector();
   29497             :          }
   29498             : 
   29499       15889 :          if (details::is_reserved_symbol(symbol))
   29500             :          {
   29501          23 :                if (
   29502          23 :                     settings_.function_enabled(symbol) ||
   29503           0 :                     !details::is_base_function(symbol)
   29504             :                   )
   29505             :                {
   29506          46 :                   set_error(make_error(
   29507             :                      parser_error::e_syntax,
   29508          23 :                      current_token(),
   29509             :                      "ERR206 - Invalid use of reserved symbol '" + symbol + "'",
   29510             :                      exprtk_error_location));
   29511             : 
   29512          23 :                   return error_node();
   29513             :                }
   29514             :          }
   29515             : 
   29516             :          // Should we handle unknown symbols?
   29517       15866 :          if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
   29518             :          {
   29519        5208 :             if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
   29520             :             {
   29521        5208 :                symbol_table_t& symtab = symtab_store_.get_symbol_table();
   29522             : 
   29523        5208 :                std::string error_message;
   29524             : 
   29525        5208 :                if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
   29526             :                {
   29527        3002 :                   T default_value = T(0);
   29528             : 
   29529        3002 :                   typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
   29530             : 
   29531        3002 :                   if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
   29532             :                   {
   29533        3002 :                      bool create_result = false;
   29534             : 
   29535        3002 :                      switch (usr_symbol_type)
   29536             :                      {
   29537        1502 :                         case unknown_symbol_resolver::e_usr_variable_type :
   29538        1502 :                            create_result = symtab.create_variable(symbol, default_value);
   29539        1502 :                            break;
   29540             : 
   29541        1500 :                         case unknown_symbol_resolver::e_usr_constant_type :
   29542        1500 :                            create_result = symtab.add_constant(symbol, default_value);
   29543        1500 :                            break;
   29544             : 
   29545           0 :                         default                                           : create_result = false;
   29546             :                      }
   29547             : 
   29548        3002 :                      if (create_result)
   29549             :                      {
   29550        3002 :                         expression_node_ptr var = symtab_store_.get_variable(symbol);
   29551             : 
   29552        3002 :                         if (var)
   29553             :                         {
   29554        3002 :                            if (symtab_store_.is_constant_node(symbol))
   29555             :                            {
   29556        1500 :                               var = expression_generator_(var->value());
   29557             :                            }
   29558             : 
   29559        3002 :                            lodge_symbol(symbol, e_st_variable);
   29560             : 
   29561        3002 :                            if (!post_variable_process(symbol))
   29562        3002 :                               return error_node();
   29563             : 
   29564        3002 :                            next_token();
   29565             : 
   29566        3002 :                            return var;
   29567             :                         }
   29568             :                      }
   29569             :                   }
   29570             : 
   29571           0 :                   set_error(make_error(
   29572             :                      parser_error::e_symtab,
   29573           0 :                      current_token(),
   29574             :                      "ERR207 - Failed to create variable: '" + symbol + "'" +
   29575           0 :                      (error_message.empty() ? "" : " - " + error_message),
   29576             :                      exprtk_error_location));
   29577             : 
   29578             :                }
   29579        2206 :                else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
   29580             :                {
   29581        2206 :                   if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
   29582             :                   {
   29583        2206 :                      expression_node_ptr result = parse_symtab_symbol();
   29584             : 
   29585        2206 :                      if (result)
   29586             :                      {
   29587        2206 :                         return result;
   29588             :                      }
   29589             :                   }
   29590             : 
   29591           0 :                   set_error(make_error(
   29592             :                      parser_error::e_symtab,
   29593           0 :                      current_token(),
   29594             :                      "ERR208 - Failed to resolve symbol: '" + symbol + "'" +
   29595           0 :                      (error_message.empty() ? "" : " - " + error_message),
   29596             :                      exprtk_error_location));
   29597             :                }
   29598             : 
   29599           0 :                return error_node();
   29600        5208 :             }
   29601             :          }
   29602             : 
   29603       21316 :          set_error(make_error(
   29604             :             parser_error::e_syntax,
   29605       10658 :             current_token(),
   29606             :             "ERR209 - Undefined symbol: '" + symbol + "'",
   29607             :             exprtk_error_location));
   29608             : 
   29609       10658 :          return error_node();
   29610     2030084 :       }
   29611             : 
   29612     2469123 :       inline expression_node_ptr parse_symbol()
   29613             :       {
   29614     2469125 :          static const std::string symbol_if       = "if"      ;
   29615     2469125 :          static const std::string symbol_while    = "while"   ;
   29616     2469125 :          static const std::string symbol_repeat   = "repeat"  ;
   29617     2469125 :          static const std::string symbol_for      = "for"     ;
   29618     2469125 :          static const std::string symbol_switch   = "switch"  ;
   29619     2469125 :          static const std::string symbol_null     = "null"    ;
   29620     2469125 :          static const std::string symbol_break    = "break"   ;
   29621     2469125 :          static const std::string symbol_continue = "continue";
   29622     2469125 :          static const std::string symbol_var      = "var"     ;
   29623     2469125 :          static const std::string symbol_swap     = "swap"    ;
   29624     2469125 :          static const std::string symbol_return   = "return"  ;
   29625     2469125 :          static const std::string symbol_not      = "not"     ;
   29626             : 
   29627     2469123 :          const std::string symbol = current_token().value;
   29628             : 
   29629     2469123 :          if (valid_vararg_operation(symbol))
   29630             :          {
   29631       18402 :             return parse_vararg_function();
   29632             :          }
   29633     2450721 :          else if (details::imatch(symbol, symbol_not))
   29634             :          {
   29635         728 :             return parse_not_statement();
   29636             :          }
   29637     2449993 :          else if (valid_base_operation(symbol))
   29638             :          {
   29639      350446 :             return parse_base_operation();
   29640             :          }
   29641     2099547 :          else if (
   29642     2104599 :                    details::imatch(symbol, symbol_if) &&
   29643        5052 :                    settings_.control_struct_enabled(symbol)
   29644             :                  )
   29645             :          {
   29646        5052 :             return parse_conditional_statement();
   29647             :          }
   29648     2094495 :          else if (
   29649     2094517 :                    details::imatch(symbol, symbol_while) &&
   29650          22 :                    settings_.control_struct_enabled(symbol)
   29651             :                  )
   29652             :          {
   29653          22 :             return parse_while_loop();
   29654             :          }
   29655     2094473 :          else if (
   29656     2094565 :                    details::imatch(symbol, symbol_repeat) &&
   29657          92 :                    settings_.control_struct_enabled(symbol)
   29658             :                  )
   29659             :          {
   29660          92 :             return parse_repeat_until_loop();
   29661             :          }
   29662     2094381 :          else if (
   29663     2097056 :                    details::imatch(symbol, symbol_for) &&
   29664        2675 :                    settings_.control_struct_enabled(symbol)
   29665             :                  )
   29666             :          {
   29667        2675 :             return parse_for_loop();
   29668             :          }
   29669     2091706 :          else if (
   29670     2092901 :                    details::imatch(symbol, symbol_switch) &&
   29671        1195 :                    settings_.control_struct_enabled(symbol)
   29672             :                  )
   29673             :          {
   29674        1195 :             return parse_switch_statement();
   29675             :          }
   29676     2090511 :          else if (details::is_valid_sf_symbol(symbol))
   29677             :          {
   29678        4245 :             return parse_special_function();
   29679             :          }
   29680     2086266 :          else if (details::imatch(symbol, symbol_null))
   29681             :          {
   29682         265 :             return parse_null_statement();
   29683             :          }
   29684             :          #ifndef exprtk_disable_break_continue
   29685     2086001 :          else if (details::imatch(symbol, symbol_break))
   29686             :          {
   29687         483 :             return parse_break_statement();
   29688             :          }
   29689     2085518 :          else if (details::imatch(symbol, symbol_continue))
   29690             :          {
   29691         460 :             return parse_continue_statement();
   29692             :          }
   29693             :          #endif
   29694     2085058 :          else if (details::imatch(symbol, symbol_var))
   29695             :          {
   29696       56410 :             return parse_define_var_statement();
   29697             :          }
   29698     2028648 :          else if (details::imatch(symbol, symbol_swap))
   29699             :          {
   29700         560 :             return parse_swap_statement();
   29701             :          }
   29702             :          #ifndef exprtk_disable_return_statement
   29703     2028088 :          else if (
   29704     2028204 :                    details::imatch(symbol, symbol_return) &&
   29705         116 :                    settings_.control_struct_enabled(symbol)
   29706             :                  )
   29707             :          {
   29708         116 :             return parse_return_statement();
   29709             :          }
   29710             :          #endif
   29711     2027972 :          else if (symtab_store_.valid() || !sem_.empty())
   29712             :          {
   29713     2027878 :             return parse_symtab_symbol();
   29714             :          }
   29715             :          else
   29716             :          {
   29717         188 :             set_error(make_error(
   29718             :                parser_error::e_symtab,
   29719          94 :                current_token(),
   29720             :                "ERR210 - Unknown variable or function encountered. Symbol table(s) "
   29721             :                "is either invalid or does not contain symbol: '" + symbol + "'",
   29722             :                exprtk_error_location));
   29723             : 
   29724          94 :             return error_node();
   29725             :          }
   29726     2469123 :       }
   29727             : 
   29728     6195436 :       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
   29729             :       {
   29730     6195436 :          stack_limit_handler slh(*this);
   29731             : 
   29732     6195436 :          if (!slh)
   29733             :          {
   29734           0 :             return error_node();
   29735             :          }
   29736             : 
   29737     6195436 :          expression_node_ptr branch = error_node();
   29738             : 
   29739     6195436 :          if (token_t::e_number == current_token().type)
   29740             :          {
   29741     1739797 :             T numeric_value = T(0);
   29742             : 
   29743     1739797 :             if (details::string_to_real(current_token().value, numeric_value))
   29744             :             {
   29745     1739797 :                expression_node_ptr literal_exp = expression_generator_(numeric_value);
   29746             : 
   29747     1739797 :                if (0 == literal_exp)
   29748             :                {
   29749           0 :                   set_error(make_error(
   29750             :                      parser_error::e_numeric,
   29751           0 :                      current_token(),
   29752           0 :                      "ERR211 - Failed generate node for scalar: '" + current_token().value + "'",
   29753             :                      exprtk_error_location));
   29754             : 
   29755           0 :                   return error_node();
   29756             :                }
   29757             : 
   29758     1739797 :                next_token();
   29759     1739797 :                branch = literal_exp;
   29760             :             }
   29761             :             else
   29762             :             {
   29763           0 :                set_error(make_error(
   29764             :                   parser_error::e_numeric,
   29765           0 :                   current_token(),
   29766           0 :                   "ERR212 - Failed to convert '" + current_token().value + "' to a number",
   29767             :                   exprtk_error_location));
   29768             : 
   29769           0 :                return error_node();
   29770             :             }
   29771             :          }
   29772     4455639 :          else if (token_t::e_symbol == current_token().type)
   29773             :          {
   29774     2469123 :             branch = parse_symbol();
   29775             :          }
   29776             :          #ifndef exprtk_disable_string_capabilities
   29777     1986516 :          else if (token_t::e_string == current_token().type)
   29778             :          {
   29779       51318 :             branch = parse_const_string();
   29780             :          }
   29781             :          #endif
   29782     1935198 :          else if (token_t::e_lbracket == current_token().type)
   29783             :          {
   29784     1821504 :             next_token();
   29785             : 
   29786     1821504 :             if (0 == (branch = parse_expression()))
   29787      120578 :                return error_node();
   29788     1700926 :             else if (token_is(token_t::e_eof))
   29789             :             {}
   29790     1700896 :             else if (!token_is(token_t::e_rbracket))
   29791             :             {
   29792         222 :                set_error(make_error(
   29793             :                   parser_error::e_syntax,
   29794          74 :                   current_token(),
   29795          74 :                   "ERR213 - Expected ')' instead of: '" + current_token().value + "'",
   29796             :                   exprtk_error_location));
   29797             : 
   29798          74 :                details::free_node(node_allocator_,branch);
   29799             : 
   29800          74 :                return error_node();
   29801             :             }
   29802     1700822 :             else if (!post_bracket_process(token_t::e_lbracket,branch))
   29803             :             {
   29804           0 :                details::free_node(node_allocator_,branch);
   29805             : 
   29806           0 :                return error_node();
   29807             :             }
   29808             : 
   29809     1700852 :             parse_pending_vector_index_operator(branch);
   29810             :          }
   29811      113694 :          else if (token_t::e_lsqrbracket == current_token().type)
   29812             :          {
   29813        6387 :             next_token();
   29814             : 
   29815        6387 :             if (0 == (branch = parse_expression()))
   29816           2 :                return error_node();
   29817        6385 :             else if (!token_is(token_t::e_rsqrbracket))
   29818             :             {
   29819           0 :                set_error(make_error(
   29820             :                   parser_error::e_syntax,
   29821           0 :                   current_token(),
   29822           0 :                   "ERR214 - Expected ']' instead of: '" + current_token().value + "'",
   29823             :                   exprtk_error_location));
   29824             : 
   29825           0 :                details::free_node(node_allocator_,branch);
   29826             : 
   29827           0 :                return error_node();
   29828             :             }
   29829        6385 :             else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
   29830             :             {
   29831           0 :                details::free_node(node_allocator_,branch);
   29832             : 
   29833           0 :                return error_node();
   29834             :             }
   29835             :          }
   29836      107307 :          else if (token_t::e_lcrlbracket == current_token().type)
   29837             :          {
   29838        2445 :             next_token();
   29839             : 
   29840        2445 :             if (0 == (branch = parse_expression()))
   29841           0 :                return error_node();
   29842        2445 :             else if (!token_is(token_t::e_rcrlbracket))
   29843             :             {
   29844           0 :                set_error(make_error(
   29845             :                   parser_error::e_syntax,
   29846           0 :                   current_token(),
   29847           0 :                   "ERR215 - Expected '}' instead of: '" + current_token().value + "'",
   29848             :                   exprtk_error_location));
   29849             : 
   29850           0 :                details::free_node(node_allocator_,branch);
   29851             : 
   29852           0 :                return error_node();
   29853             :             }
   29854        2445 :             else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
   29855             :             {
   29856           0 :                details::free_node(node_allocator_,branch);
   29857             : 
   29858           0 :                return error_node();
   29859             :             }
   29860             :          }
   29861      104862 :          else if (token_t::e_sub == current_token().type)
   29862             :          {
   29863       99050 :             next_token();
   29864       99050 :             branch = parse_expression(e_level11);
   29865             : 
   29866       99050 :             if (
   29867      198088 :                  branch &&
   29868             :                  !(
   29869       99038 :                     details::is_neg_unary_node    (branch) &&
   29870         640 :                     simplify_unary_negation_branch(branch)
   29871             :                   )
   29872             :                )
   29873             :             {
   29874       98398 :                expression_node_ptr result = expression_generator_(details::e_neg,branch);
   29875             : 
   29876       98398 :                if (0 == result)
   29877             :                {
   29878           0 :                   details::free_node(node_allocator_,branch);
   29879             : 
   29880           0 :                   return error_node();
   29881             :                }
   29882             :                else
   29883       98398 :                   branch = result;
   29884             :             }
   29885             :          }
   29886        5812 :          else if (token_t::e_add == current_token().type)
   29887             :          {
   29888        5725 :             next_token();
   29889        5725 :             branch = parse_expression(e_level13);
   29890             :          }
   29891          87 :          else if (token_t::e_eof == current_token().type)
   29892             :          {
   29893          64 :             set_error(make_error(
   29894             :                parser_error::e_syntax,
   29895          16 :                current_token(),
   29896             :                "ERR216 - Premature end of expression[1]",
   29897             :                exprtk_error_location));
   29898             : 
   29899          16 :             return error_node();
   29900             :          }
   29901             :          else
   29902             :          {
   29903         284 :             set_error(make_error(
   29904             :                parser_error::e_syntax,
   29905          71 :                current_token(),
   29906             :                "ERR217 - Premature end of expression[2]",
   29907             :                exprtk_error_location));
   29908             : 
   29909          71 :             return error_node();
   29910             :          }
   29911             : 
   29912     6074695 :          if (
   29913     6041928 :               branch                    &&
   29914    12116623 :               (e_level00 == precedence) &&
   29915     9347899 :               token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
   29916             :             )
   29917             :          {
   29918         614 :             branch = parse_ternary_conditional_statement(branch);
   29919             :          }
   29920             : 
   29921     6074695 :          parse_pending_string_rangesize(branch);
   29922             : 
   29923     6074695 :          return branch;
   29924     6195436 :       }
   29925             : 
   29926             :       template <typename Type>
   29927             :       class expression_generator
   29928             :       {
   29929             :       public:
   29930             : 
   29931             :          typedef details::expression_node<Type>* expression_node_ptr;
   29932             :          typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
   29933             :          typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
   29934             :          typedef typename exprtk::parser<Type> parser_t;
   29935             :          typedef const Type& vtype;
   29936             :          typedef const Type  ctype;
   29937             : 
   29938      106542 :          inline void init_synthesize_map()
   29939             :          {
   29940             :             #ifndef exprtk_disable_enhanced_features
   29941      213084 :             synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
   29942      213084 :             synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
   29943      213084 :             synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
   29944             : 
   29945             :             #define register_synthezier(S)                      \
   29946             :             synthesize_map_[S ::node_type::id()] = S ::process; \
   29947             : 
   29948      106542 :             register_synthezier(synthesize_vovov_expression0)
   29949      106542 :             register_synthezier(synthesize_vovov_expression1)
   29950      106542 :             register_synthezier(synthesize_vovoc_expression0)
   29951      106542 :             register_synthezier(synthesize_vovoc_expression1)
   29952      106542 :             register_synthezier(synthesize_vocov_expression0)
   29953      106542 :             register_synthezier(synthesize_vocov_expression1)
   29954      106542 :             register_synthezier(synthesize_covov_expression0)
   29955      106542 :             register_synthezier(synthesize_covov_expression1)
   29956      106542 :             register_synthezier(synthesize_covoc_expression0)
   29957      106542 :             register_synthezier(synthesize_covoc_expression1)
   29958      106542 :             register_synthezier(synthesize_cocov_expression1)
   29959      106542 :             register_synthezier(synthesize_vococ_expression0)
   29960             : 
   29961      106542 :             register_synthezier(synthesize_vovovov_expression0)
   29962      106542 :             register_synthezier(synthesize_vovovoc_expression0)
   29963      106542 :             register_synthezier(synthesize_vovocov_expression0)
   29964      106542 :             register_synthezier(synthesize_vocovov_expression0)
   29965      106542 :             register_synthezier(synthesize_covovov_expression0)
   29966      106542 :             register_synthezier(synthesize_covocov_expression0)
   29967      106542 :             register_synthezier(synthesize_vocovoc_expression0)
   29968      106542 :             register_synthezier(synthesize_covovoc_expression0)
   29969      106542 :             register_synthezier(synthesize_vococov_expression0)
   29970             : 
   29971      106542 :             register_synthezier(synthesize_vovovov_expression1)
   29972      106542 :             register_synthezier(synthesize_vovovoc_expression1)
   29973      106542 :             register_synthezier(synthesize_vovocov_expression1)
   29974      106542 :             register_synthezier(synthesize_vocovov_expression1)
   29975      106542 :             register_synthezier(synthesize_covovov_expression1)
   29976      106542 :             register_synthezier(synthesize_covocov_expression1)
   29977      106542 :             register_synthezier(synthesize_vocovoc_expression1)
   29978      106542 :             register_synthezier(synthesize_covovoc_expression1)
   29979      106542 :             register_synthezier(synthesize_vococov_expression1)
   29980             : 
   29981      106542 :             register_synthezier(synthesize_vovovov_expression2)
   29982      106542 :             register_synthezier(synthesize_vovovoc_expression2)
   29983      106542 :             register_synthezier(synthesize_vovocov_expression2)
   29984      106542 :             register_synthezier(synthesize_vocovov_expression2)
   29985      106542 :             register_synthezier(synthesize_covovov_expression2)
   29986      106542 :             register_synthezier(synthesize_covocov_expression2)
   29987      106542 :             register_synthezier(synthesize_vocovoc_expression2)
   29988      106542 :             register_synthezier(synthesize_covovoc_expression2)
   29989             : 
   29990      106542 :             register_synthezier(synthesize_vovovov_expression3)
   29991      106542 :             register_synthezier(synthesize_vovovoc_expression3)
   29992      106542 :             register_synthezier(synthesize_vovocov_expression3)
   29993      106542 :             register_synthezier(synthesize_vocovov_expression3)
   29994      106542 :             register_synthezier(synthesize_covovov_expression3)
   29995      106542 :             register_synthezier(synthesize_covocov_expression3)
   29996      106542 :             register_synthezier(synthesize_vocovoc_expression3)
   29997      106542 :             register_synthezier(synthesize_covovoc_expression3)
   29998      106542 :             register_synthezier(synthesize_vococov_expression3)
   29999             : 
   30000      106542 :             register_synthezier(synthesize_vovovov_expression4)
   30001      106542 :             register_synthezier(synthesize_vovovoc_expression4)
   30002      106542 :             register_synthezier(synthesize_vovocov_expression4)
   30003      106542 :             register_synthezier(synthesize_vocovov_expression4)
   30004      106542 :             register_synthezier(synthesize_covovov_expression4)
   30005      106542 :             register_synthezier(synthesize_covocov_expression4)
   30006      106542 :             register_synthezier(synthesize_vocovoc_expression4)
   30007      106542 :             register_synthezier(synthesize_covovoc_expression4)
   30008             : 
   30009             :             #undef register_synthezier
   30010             :             #endif
   30011      106542 :          }
   30012             : 
   30013      106542 :          inline void set_parser(parser_t& p)
   30014             :          {
   30015      106542 :             parser_ = &p;
   30016      106542 :          }
   30017             : 
   30018      106542 :          inline void set_uom(unary_op_map_t& unary_op_map)
   30019             :          {
   30020      106542 :             unary_op_map_ = &unary_op_map;
   30021      106542 :          }
   30022             : 
   30023      106542 :          inline void set_bom(binary_op_map_t& binary_op_map)
   30024             :          {
   30025      106542 :             binary_op_map_ = &binary_op_map;
   30026      106542 :          }
   30027             : 
   30028      106542 :          inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
   30029             :          {
   30030      106542 :             inv_binary_op_map_ = &inv_binary_op_map;
   30031      106542 :          }
   30032             : 
   30033      106542 :          inline void set_sf3m(sf3_map_t& sf3_map)
   30034             :          {
   30035      106542 :             sf3_map_ = &sf3_map;
   30036      106542 :          }
   30037             : 
   30038      106542 :          inline void set_sf4m(sf4_map_t& sf4_map)
   30039             :          {
   30040      106542 :             sf4_map_ = &sf4_map;
   30041      106542 :          }
   30042             : 
   30043      371453 :          inline void set_allocator(details::node_allocator& na)
   30044             :          {
   30045      371453 :             node_allocator_ = &na;
   30046      371453 :          }
   30047             : 
   30048      106542 :          inline void set_strength_reduction_state(const bool enabled)
   30049             :          {
   30050      106542 :             strength_reduction_enabled_ = enabled;
   30051      106542 :          }
   30052             : 
   30053             :          inline bool strength_reduction_enabled() const
   30054             :          {
   30055             :             return strength_reduction_enabled_;
   30056             :          }
   30057             : 
   30058       32251 :          inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
   30059             :          {
   30060       32251 :             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
   30061             : 
   30062       32251 :             if (binary_op_map_->end() == bop_itr)
   30063           0 :                return false;
   30064             : 
   30065       32251 :             bop = bop_itr->second;
   30066             : 
   30067       32251 :             return true;
   30068             :          }
   30069             : 
   30070        1620 :          inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
   30071             :          {
   30072        1620 :             typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
   30073             : 
   30074        1620 :             if ((*unary_op_map_).end() == uop_itr)
   30075           0 :                return false;
   30076             : 
   30077        1620 :             uop = uop_itr->second;
   30078             : 
   30079        1620 :             return true;
   30080             :          }
   30081             : 
   30082           0 :          inline details::operator_type get_operator(const binary_functor_t& bop) const
   30083             :          {
   30084           0 :             return (*inv_binary_op_map_).find(bop)->second;
   30085             :          }
   30086             : 
   30087     1790073 :          inline expression_node_ptr operator() (const Type& v) const
   30088             :          {
   30089     1790073 :             return node_allocator_->allocate<literal_node_t>(v);
   30090             :          }
   30091             : 
   30092             :          #ifndef exprtk_disable_string_capabilities
   30093       51318 :          inline expression_node_ptr operator() (const std::string& s) const
   30094             :          {
   30095       51318 :             return node_allocator_->allocate<string_literal_node_t>(s);
   30096             :          }
   30097             : 
   30098       22141 :          inline expression_node_ptr operator() (std::string& s, range_t& rp) const
   30099             :          {
   30100       22141 :             return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
   30101             :          }
   30102             : 
   30103        5553 :          inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
   30104             :          {
   30105        5553 :             return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
   30106             :          }
   30107             : 
   30108        4102 :          inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
   30109             :          {
   30110        4102 :             if (is_generally_string_node(branch))
   30111        4102 :                return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
   30112             :             else
   30113           0 :                return error_node();
   30114             :          }
   30115             :          #endif
   30116             : 
   30117      130373 :          inline bool unary_optimisable(const details::operator_type& operation) const
   30118             :          {
   30119      123167 :             return (details::e_abs   == operation) || (details::e_acos  == operation) ||
   30120      123107 :                    (details::e_acosh == operation) || (details::e_asin  == operation) ||
   30121      122987 :                    (details::e_asinh == operation) || (details::e_atan  == operation) ||
   30122      122867 :                    (details::e_atanh == operation) || (details::e_ceil  == operation) ||
   30123      122807 :                    (details::e_cos   == operation) || (details::e_cosh  == operation) ||
   30124      107042 :                    (details::e_exp   == operation) || (details::e_expm1 == operation) ||
   30125      106922 :                    (details::e_floor == operation) || (details::e_log   == operation) ||
   30126      106748 :                    (details::e_log10 == operation) || (details::e_log2  == operation) ||
   30127      106638 :                    (details::e_log1p == operation) || (details::e_neg   == operation) ||
   30128       98594 :                    (details::e_pos   == operation) || (details::e_round == operation) ||
   30129       98534 :                    (details::e_sin   == operation) || (details::e_sinc  == operation) ||
   30130       18212 :                    (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
   30131       18004 :                    (details::e_tan   == operation) || (details::e_tanh  == operation) ||
   30132         926 :                    (details::e_cot   == operation) || (details::e_sec   == operation) ||
   30133         802 :                    (details::e_csc   == operation) || (details::e_r2d   == operation) ||
   30134         682 :                    (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
   30135         562 :                    (details::e_g2d   == operation) || (details::e_notl  == operation) ||
   30136         486 :                    (details::e_sgn   == operation) || (details::e_erf   == operation) ||
   30137         213 :                    (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
   30138      253540 :                    (details::e_frac  == operation) || (details::e_trunc == operation) ;
   30139             :          }
   30140             : 
   30141             :          inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
   30142             :          {
   30143             :             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
   30144             : 
   30145             :             if (sf3_map_->end() == itr)
   30146             :                return false;
   30147             :             else
   30148             :                tfunc = itr->second.first;
   30149             : 
   30150             :             return true;
   30151             :          }
   30152             : 
   30153             :          inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
   30154             :          {
   30155             :             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
   30156             : 
   30157             :             if (sf4_map_->end() == itr)
   30158             :                return false;
   30159             :             else
   30160             :                qfunc = itr->second.first;
   30161             : 
   30162             :             return true;
   30163             :          }
   30164             : 
   30165      374939 :          inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
   30166             :          {
   30167      374939 :             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
   30168             : 
   30169      374939 :             if (sf3_map_->end() == itr)
   30170        5915 :                return false;
   30171             :             else
   30172      369024 :                operation = itr->second.second;
   30173             : 
   30174      369024 :             return true;
   30175             :          }
   30176             : 
   30177      242740 :          inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
   30178             :          {
   30179      242740 :             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
   30180             : 
   30181      242740 :             if (sf4_map_->end() == itr)
   30182      145456 :                return false;
   30183             :             else
   30184       97284 :                operation = itr->second.second;
   30185             : 
   30186       97284 :             return true;
   30187             :          }
   30188             : 
   30189      166450 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
   30190             :          {
   30191      166450 :             if (0 == branch[0])
   30192             :             {
   30193           0 :                return error_node();
   30194             :             }
   30195      166450 :             else if (details::is_null_node(branch[0]))
   30196             :             {
   30197           0 :                return branch[0];
   30198             :             }
   30199      166450 :             else if (details::is_break_node(branch[0]))
   30200             :             {
   30201           0 :                return error_node();
   30202             :             }
   30203      166450 :             else if (details::is_continue_node(branch[0]))
   30204             :             {
   30205           0 :                return error_node();
   30206             :             }
   30207      166450 :             else if (details::is_constant_node(branch[0]))
   30208             :             {
   30209       97415 :                return synthesize_expression<unary_node_t,1>(operation,branch);
   30210             :             }
   30211       69035 :             else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
   30212             :             {
   30213        7697 :                return synthesize_uv_expression(operation,branch);
   30214             :             }
   30215       61338 :             else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
   30216             :             {
   30217        1430 :                return synthesize_uvec_expression(operation,branch);
   30218             :             }
   30219             :             else
   30220       59908 :                return synthesize_unary_expression(operation,branch);
   30221             :          }
   30222             : 
   30223     5858852 :          inline bool is_assignment_operation(const details::operator_type& operation) const
   30224             :          {
   30225             :             return (
   30226    11697900 :                      (details::e_addass == operation) ||
   30227     5839048 :                      (details::e_subass == operation) ||
   30228     5836977 :                      (details::e_mulass == operation) ||
   30229     5836317 :                      (details::e_divass == operation) ||
   30230     5835657 :                      (details::e_modass == operation)
   30231    11717704 :                    ) &&
   30232     5882047 :                    parser_->settings_.assignment_enabled(operation);
   30233             :          }
   30234             : 
   30235             :          #ifndef exprtk_disable_string_capabilities
   30236     2998195 :          inline bool valid_string_operation(const details::operator_type& operation) const
   30237             :          {
   30238     5251442 :             return (details::e_add    == operation) ||
   30239     2253247 :                    (details::e_lt     == operation) ||
   30240     2245533 :                    (details::e_lte    == operation) ||
   30241     2243162 :                    (details::e_gt     == operation) ||
   30242     2236001 :                    (details::e_gte    == operation) ||
   30243     2235166 :                    (details::e_eq     == operation) ||
   30244     2150626 :                    (details::e_ne     == operation) ||
   30245     2145131 :                    (details::e_in     == operation) ||
   30246     2143599 :                    (details::e_like   == operation) ||
   30247     2137669 :                    (details::e_ilike  == operation) ||
   30248     2131739 :                    (details::e_assign == operation) ||
   30249     7327608 :                    (details::e_addass == operation) ||
   30250     5074361 :                    (details::e_swap   == operation) ;
   30251             :          }
   30252             :          #else
   30253             :          inline bool valid_string_operation(const details::operator_type&) const
   30254             :          {
   30255             :             return false;
   30256             :          }
   30257             :          #endif
   30258             : 
   30259     1033350 :          inline std::string to_str(const details::operator_type& operation) const
   30260             :          {
   30261     1033350 :             switch (operation)
   30262             :             {
   30263      692220 :                case details::e_add  : return "+"      ;
   30264      671568 :                case details::e_sub  : return "-"      ;
   30265     1042677 :                case details::e_mul  : return "*"      ;
   30266      642618 :                case details::e_div  : return "/"      ;
   30267          21 :                case details::e_mod  : return "%"      ;
   30268        2121 :                case details::e_pow  : return "^"      ;
   30269        1533 :                case details::e_lt   : return "<"      ;
   30270         363 :                case details::e_lte  : return "<="     ;
   30271        3030 :                case details::e_gt   : return ">"      ;
   30272           0 :                case details::e_gte  : return ">="     ;
   30273       34860 :                case details::e_eq   : return "=="     ;
   30274         360 :                case details::e_ne   : return "!="     ;
   30275        8676 :                case details::e_and  : return "and"    ;
   30276           0 :                case details::e_nand : return "nand"   ;
   30277           3 :                case details::e_or   : return "or"     ;
   30278           0 :                case details::e_nor  : return "nor"    ;
   30279           0 :                case details::e_xor  : return "xor"    ;
   30280           0 :                case details::e_xnor : return "xnor"   ;
   30281           0 :                default              : return "UNKNOWN";
   30282             :             }
   30283             :          }
   30284             : 
   30285    11077453 :          inline bool operation_optimisable(const details::operator_type& operation) const
   30286             :          {
   30287    18822645 :             return (details::e_add  == operation) ||
   30288     7745192 :                    (details::e_sub  == operation) ||
   30289     5672459 :                    (details::e_mul  == operation) ||
   30290     3790143 :                    (details::e_div  == operation) ||
   30291     2440328 :                    (details::e_mod  == operation) ||
   30292     2439526 :                    (details::e_pow  == operation) ||
   30293     2304063 :                    (details::e_lt   == operation) ||
   30294     2289514 :                    (details::e_lte  == operation) ||
   30295     2284998 :                    (details::e_gt   == operation) ||
   30296     2271324 :                    (details::e_gte  == operation) ||
   30297     2269704 :                    (details::e_eq   == operation) ||
   30298     2156563 :                    (details::e_ne   == operation) ||
   30299     2154110 :                    (details::e_and  == operation) ||
   30300     2107786 :                    (details::e_nand == operation) ||
   30301     2102982 :                    (details::e_or   == operation) ||
   30302     2097773 :                    (details::e_nor  == operation) ||
   30303    20913669 :                    (details::e_xor  == operation) ||
   30304    13168477 :                    (details::e_xnor == operation) ;
   30305             :          }
   30306             : 
   30307     5145840 :          inline std::string branch_to_id(expression_node_ptr branch) const
   30308             :          {
   30309     5145842 :             static const std::string null_str   ("(null)" );
   30310     5145842 :             static const std::string const_str  ("(c)"    );
   30311     5145842 :             static const std::string var_str    ("(v)"    );
   30312     5145842 :             static const std::string vov_str    ("(vov)"  );
   30313     5145842 :             static const std::string cov_str    ("(cov)"  );
   30314     5145842 :             static const std::string voc_str    ("(voc)"  );
   30315     5145842 :             static const std::string str_str    ("(s)"    );
   30316     5145842 :             static const std::string strrng_str ("(rngs)" );
   30317     5145842 :             static const std::string cs_str     ("(cs)"   );
   30318     5145842 :             static const std::string cstrrng_str("(crngs)");
   30319             : 
   30320     5145840 :             if (details::is_null_node(branch))
   30321           0 :                return null_str;
   30322     5145840 :             else if (details::is_constant_node(branch))
   30323     1369547 :                return const_str;
   30324     3776293 :             else if (details::is_variable_node(branch))
   30325     1719914 :                return var_str;
   30326     2056379 :             else if (details::is_vov_node(branch))
   30327      255164 :                return vov_str;
   30328     1801215 :             else if (details::is_cov_node(branch))
   30329      232964 :                return cov_str;
   30330     1568251 :             else if (details::is_voc_node(branch))
   30331      190373 :                return voc_str;
   30332     1377878 :             else if (details::is_string_node(branch))
   30333           0 :                return str_str;
   30334     1377878 :             else if (details::is_const_string_node(branch))
   30335           0 :                return cs_str;
   30336     1377878 :             else if (details::is_string_range_node(branch))
   30337           0 :                return strrng_str;
   30338     1377878 :             else if (details::is_const_string_range_node(branch))
   30339           0 :                return cstrrng_str;
   30340     1377878 :             else if (details::is_t0ot1ot2_node(branch))
   30341      346157 :                return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
   30342     1031721 :             else if (details::is_t0ot1ot2ot3_node(branch))
   30343       88342 :                return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
   30344             :             else
   30345     1886758 :                return "ERROR";
   30346             :          }
   30347             : 
   30348     2572920 :          inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
   30349             :          {
   30350     7718760 :             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
   30351             :          }
   30352             : 
   30353      846538 :          inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30354             :          {
   30355      846538 :             if (!operation_optimisable(operation))
   30356      261298 :                return false;
   30357             :             else
   30358      764623 :                return details::is_constant_node(branch[0]) &&
   30359      764623 :                       details::is_variable_node(branch[1]) ;
   30360             :          }
   30361             : 
   30362             :          inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30363             :          {
   30364             :             if (!operation_optimisable(operation))
   30365             :                return false;
   30366             :             else
   30367             :                return details::is_variable_node(branch[0]) &&
   30368             :                       details::is_constant_node(branch[1]) ;
   30369             :          }
   30370             : 
   30371             :          inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30372             :          {
   30373             :             if (!operation_optimisable(operation))
   30374             :                return false;
   30375             :             else
   30376             :                return details::is_variable_node(branch[0]) &&
   30377             :                       details::is_variable_node(branch[1]) ;
   30378             :          }
   30379             : 
   30380     1091718 :          inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30381             :          {
   30382     1091718 :             if (!operation_optimisable(operation))
   30383      261298 :                return false;
   30384             :             else
   30385     1108745 :                return details::is_constant_node(branch[0]) &&
   30386     1108745 :                      !details::is_constant_node(branch[1]) ;
   30387             :          }
   30388             : 
   30389      992776 :          inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30390             :          {
   30391      992776 :             if (!operation_optimisable(operation))
   30392      261298 :                return false;
   30393             :             else
   30394     1283573 :                return !details::is_constant_node(branch[0]) &&
   30395     1283573 :                        details::is_constant_node(branch[1]) ;
   30396             :          }
   30397             : 
   30398     1533945 :          inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30399             :          {
   30400     1533945 :             if (
   30401     1533945 :                  (details::e_add == operation) ||
   30402     1020932 :                  (details::e_sub == operation) ||
   30403      717073 :                  (details::e_mul == operation) ||
   30404      453093 :                  (details::e_div == operation)
   30405             :                )
   30406             :             {
   30407     2477309 :                return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
   30408     2477309 :                       (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
   30409             :             }
   30410             :             else
   30411      293690 :                return false;
   30412             :          }
   30413             : 
   30414     1526027 :          inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30415             :          {
   30416     1526027 :             if (
   30417     1526027 :                  (details::e_add == operation) ||
   30418     1014807 :                  (details::e_sub == operation) ||
   30419      713523 :                  (details::e_mul == operation) ||
   30420      450903 :                  (details::e_div == operation)
   30421             :                )
   30422             :             {
   30423     2462419 :                return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
   30424     2462419 :                       (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
   30425             :             }
   30426             :             else
   30427      293690 :                return false;
   30428             :          }
   30429             : 
   30430     1506648 :          inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30431             :          {
   30432     1506648 :             if (!operation_optimisable(operation))
   30433      261298 :                return false;
   30434             :             else
   30435     1247459 :                return details::is_uv_node(branch[0]) &&
   30436     1247459 :                       details::is_uv_node(branch[1]) ;
   30437             :          }
   30438             : 
   30439     1505838 :          inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30440             :          {
   30441     1505838 :             if (!operation_optimisable(operation))
   30442      261298 :                return false;
   30443             :             else
   30444     1297199 :                return details::is_variable_node(branch[0]) &&
   30445     1297199 :                      !details::is_variable_node(branch[1]) ;
   30446             :          }
   30447             : 
   30448     1453179 :          inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30449             :          {
   30450     1453179 :             if (!operation_optimisable(operation))
   30451      261298 :                return false;
   30452             :             else
   30453     2383762 :                return !details::is_variable_node(branch[0]) &&
   30454     2383762 :                        details::is_variable_node(branch[1]) ;
   30455             :          }
   30456             : 
   30457      846538 :          inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30458             :          {
   30459      846538 :             if (!operation_optimisable(operation))
   30460      261298 :                return false;
   30461             :             else
   30462      764623 :                return !details::is_constant_node(branch[0]) ||
   30463      764623 :                       !details::is_constant_node(branch[1]) ;
   30464             :          }
   30465             : 
   30466     2953627 :          inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30467             :          {
   30468     2953627 :             if (is_assignment_operation(operation))
   30469             :             {
   30470       11599 :                const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
   30471             : 
   30472       11599 :                if (details::is_string_node(branch[0]))
   30473        2600 :                   return !b1_is_genstring;
   30474             :                else
   30475             :                   return (
   30476        8999 :                            !details::is_variable_node              (branch[0]) &&
   30477        4302 :                            !details::is_vector_elem_node           (branch[0]) &&
   30478        3801 :                            !details::is_vector_celem_node          (branch[0]) &&
   30479        3801 :                            !details::is_vector_elem_rtc_node       (branch[0]) &&
   30480        3789 :                            !details::is_vector_celem_rtc_node      (branch[0]) &&
   30481        3789 :                            !details::is_rebasevector_elem_node     (branch[0]) &&
   30482        3489 :                            !details::is_rebasevector_celem_node    (branch[0]) &&
   30483        3189 :                            !details::is_rebasevector_elem_rtc_node (branch[0]) &&
   30484        3189 :                            !details::is_rebasevector_celem_rtc_node(branch[0]) &&
   30485        3189 :                            !details::is_vector_node                (branch[0])
   30486             :                          )
   30487       13301 :                          || b1_is_genstring;
   30488             :             }
   30489             :             else
   30490     2942028 :                return false;
   30491             :          }
   30492             : 
   30493     2834219 :          inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
   30494             :          {
   30495     2834219 :             if (
   30496     2834219 :                  !details::is_constant_node(branch[1]) ||
   30497      838504 :                   details::is_constant_node(branch[0]) ||
   30498      644791 :                   details::is_variable_node(branch[0]) ||
   30499     3965843 :                   details::is_vector_node  (branch[0]) ||
   30500      293120 :                   details::is_generally_string_node(branch[0])
   30501             :                )
   30502     2541099 :                return false;
   30503             : 
   30504      293120 :             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   30505             : 
   30506      293120 :             return cardinal_pow_optimisable(operation, c);
   30507             :          }
   30508             : 
   30509     2953624 :          inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
   30510             :          {
   30511             :             return (
   30512     2953624 :                      details::is_break_node   (branch[0]) ||
   30513     2953624 :                      details::is_break_node   (branch[1]) ||
   30514     8860872 :                      details::is_continue_node(branch[0]) ||
   30515     2953624 :                      details::is_continue_node(branch[1])
   30516     2953624 :                    );
   30517             :          }
   30518             : 
   30519     2953627 :          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30520             :          {
   30521     2953627 :             const bool b0_string = is_generally_string_node(branch[0]);
   30522     2953627 :             const bool b1_string = is_generally_string_node(branch[1]);
   30523             : 
   30524     2953627 :             bool result = false;
   30525             : 
   30526     2953627 :             if (b0_string != b1_string)
   30527           0 :                result = true;
   30528     2953627 :             else if (!valid_string_operation(operation) && b0_string && b1_string)
   30529           0 :                result = true;
   30530             : 
   30531     2953627 :             if (result)
   30532             :             {
   30533           0 :                parser_->set_synthesis_error("Invalid string operation");
   30534             :             }
   30535             : 
   30536     2953627 :             return result;
   30537             :          }
   30538             : 
   30539         471 :          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
   30540             :          {
   30541         471 :             const bool b0_string = is_generally_string_node(branch[0]);
   30542         471 :             const bool b1_string = is_generally_string_node(branch[1]);
   30543         471 :             const bool b2_string = is_generally_string_node(branch[2]);
   30544             : 
   30545         471 :             bool result = false;
   30546             : 
   30547         471 :             if ((b0_string != b1_string) || (b1_string != b2_string))
   30548           0 :                result = true;
   30549         471 :             else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
   30550           0 :                result = true;
   30551             : 
   30552         471 :             if (result)
   30553             :             {
   30554           0 :                parser_->set_synthesis_error("Invalid string operation");
   30555             :             }
   30556             : 
   30557         471 :             return result;
   30558             :          }
   30559             : 
   30560     2879042 :          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30561             :          {
   30562     2879042 :             const bool b0_string = is_generally_string_node(branch[0]);
   30563     2879042 :             const bool b1_string = is_generally_string_node(branch[1]);
   30564             : 
   30565     2879042 :             return (b0_string && b1_string && valid_string_operation(operation));
   30566             :          }
   30567             : 
   30568         471 :          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
   30569             :          {
   30570         471 :             const bool b0_string = is_generally_string_node(branch[0]);
   30571         471 :             const bool b1_string = is_generally_string_node(branch[1]);
   30572         471 :             const bool b2_string = is_generally_string_node(branch[2]);
   30573             : 
   30574         471 :             return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
   30575             :          }
   30576             : 
   30577             :          #ifndef exprtk_disable_sc_andor
   30578     2879898 :          inline bool is_shortcircuit_expression(const details::operator_type& operation) const
   30579             :          {
   30580             :             return (
   30581     5759360 :                      (details::e_scand == operation) ||
   30582     2879462 :                      (details::e_scor  == operation)
   30583     2879898 :                    );
   30584             :          }
   30585             :          #else
   30586             :          inline bool is_shortcircuit_expression(const details::operator_type&) const
   30587             :          {
   30588             :             return false;
   30589             :          }
   30590             :          #endif
   30591             : 
   30592     2834474 :          inline bool is_null_present(expression_node_ptr (&branch)[2]) const
   30593             :          {
   30594             :             return (
   30595     5668888 :                      details::is_null_node(branch[0]) ||
   30596     2834414 :                      details::is_null_node(branch[1])
   30597     2834474 :                    );
   30598             :          }
   30599             : 
   30600     2893629 :          inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30601             :          {
   30602     2893629 :             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
   30603     2879898 :                return false;
   30604             :             else
   30605             :                return (
   30606       26657 :                         (details::e_lt    == operation) ||
   30607       12926 :                         (details::e_lte   == operation) ||
   30608       12646 :                         (details::e_gt    == operation) ||
   30609       12326 :                         (details::e_gte   == operation) ||
   30610       12126 :                         (details::e_eq    == operation) ||
   30611        8689 :                         (details::e_ne    == operation) ||
   30612        8529 :                         (details::e_equal == operation) ||
   30613        8409 :                         (details::e_and   == operation) ||
   30614        8409 :                         (details::e_nand  == operation) ||
   30615        8409 :                         (details::e_or    == operation) ||
   30616        8409 :                         (details::e_nor   == operation) ||
   30617       35066 :                         (details::e_xor   == operation) ||
   30618        8409 :                         (details::e_xnor  == operation)
   30619       13731 :                       );
   30620             :          }
   30621             : 
   30622     2888307 :          inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
   30623             :          {
   30624     2888307 :             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
   30625     2879898 :                return false;
   30626             :             else
   30627             :                return (
   30628       15304 :                         (details::e_add == operation) ||
   30629        6895 :                         (details::e_sub == operation) ||
   30630        3634 :                         (details::e_mul == operation) ||
   30631       15344 :                         (details::e_div == operation) ||
   30632          40 :                         (details::e_pow == operation)
   30633        8409 :                       );
   30634             :          }
   30635             : 
   30636     2953627 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
   30637             :          {
   30638     2953627 :             if ((0 == branch[0]) || (0 == branch[1]))
   30639             :             {
   30640           0 :                parser_->set_error(parser_error::make_error(
   30641             :                   parser_error::e_syntax,
   30642           0 :                   parser_->current_state().token,
   30643             :                   "ERR218 - Invalid branches received for operator '" + details::to_str(operation) + "'",
   30644             :                   exprtk_error_location));
   30645             : 
   30646           0 :                return error_node();
   30647             :             }
   30648     2953627 :             else if (is_invalid_string_op(operation,branch))
   30649             :             {
   30650           0 :                parser_->set_error(parser_error::make_error(
   30651             :                   parser_error::e_syntax,
   30652           0 :                   parser_->current_state().token,
   30653             :                   "ERR219 - Invalid branch pair for string operator '" + details::to_str(operation) + "'",
   30654             :                   exprtk_error_location));
   30655             : 
   30656           0 :                return error_node();
   30657             :             }
   30658     2953627 :             else if (is_invalid_assignment_op(operation,branch))
   30659             :             {
   30660           9 :                parser_->set_error(parser_error::make_error(
   30661             :                   parser_error::e_syntax,
   30662           6 :                   parser_->current_state().token,
   30663             :                   "ERR220 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'",
   30664             :                   exprtk_error_location));
   30665             : 
   30666           3 :                return error_node();
   30667             :             }
   30668     2953624 :             else if (is_invalid_break_continue_op(branch))
   30669             :             {
   30670           0 :                parser_->set_error(parser_error::make_error(
   30671             :                   parser_error::e_syntax,
   30672           0 :                   parser_->current_state().token,
   30673             :                   "ERR221 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'",
   30674             :                   exprtk_error_location));
   30675             : 
   30676           0 :                return error_node();
   30677             :             }
   30678     2953624 :             else if (details::e_assign == operation)
   30679             :             {
   30680       45671 :                return synthesize_assignment_expression(operation, branch);
   30681             :             }
   30682     2907953 :             else if (details::e_swap == operation)
   30683             :             {
   30684        2728 :                return synthesize_swap_expression(branch);
   30685             :             }
   30686     2905225 :             else if (is_assignment_operation(operation))
   30687             :             {
   30688       11596 :                return synthesize_assignment_operation_expression(operation, branch);
   30689             :             }
   30690     2893629 :             else if (is_vector_eqineq_logic_operation(operation, branch))
   30691             :             {
   30692        5322 :                return synthesize_veceqineqlogic_operation_expression(operation, branch);
   30693             :             }
   30694     2888307 :             else if (is_vector_arithmetic_operation(operation, branch))
   30695             :             {
   30696        8409 :                return synthesize_vecarithmetic_operation_expression(operation, branch);
   30697             :             }
   30698     2879898 :             else if (is_shortcircuit_expression(operation))
   30699             :             {
   30700         856 :                return synthesize_shortcircuit_expression(operation, branch);
   30701             :             }
   30702     2879042 :             else if (is_string_operation(operation, branch))
   30703             :             {
   30704       44568 :                return synthesize_string_expression(operation, branch);
   30705             :             }
   30706     2834474 :             else if (is_null_present(branch))
   30707             :             {
   30708         255 :                return synthesize_null_expression(operation, branch);
   30709             :             }
   30710             :             #ifndef exprtk_disable_cardinal_pow_optimisation
   30711     2834219 :             else if (is_constpow_operation(operation, branch))
   30712             :             {
   30713           1 :                return cardinal_pow_optimisation(branch);
   30714             :             }
   30715             :             #endif
   30716             : 
   30717     2834218 :             expression_node_ptr result = error_node();
   30718             : 
   30719             :             #ifndef exprtk_disable_enhanced_features
   30720     2834218 :             if (synthesize_expression(operation, branch, result))
   30721             :             {
   30722     1300273 :                return result;
   30723             :             }
   30724             :             else
   30725             :             #endif
   30726             : 
   30727             :             {
   30728             :                /*
   30729             :                   Possible reductions:
   30730             :                   1. c o cob -> cob
   30731             :                   2. cob o c -> cob
   30732             :                   3. c o boc -> boc
   30733             :                   4. boc o c -> boc
   30734             :                */
   30735     1533945 :                result = error_node();
   30736             : 
   30737     1533945 :                if (cocob_optimisable(operation, branch))
   30738             :                {
   30739        7918 :                   result = synthesize_cocob_expression::process((*this), operation, branch);
   30740             :                }
   30741     1526027 :                else if (coboc_optimisable(operation, branch) && (0 == result))
   30742             :                {
   30743       24432 :                   result = synthesize_coboc_expression::process((*this), operation, branch);
   30744             :                }
   30745             : 
   30746     1533945 :                if (result)
   30747       27297 :                   return result;
   30748             :             }
   30749             : 
   30750     1506648 :             if (uvouv_optimisable(operation, branch))
   30751             :             {
   30752         810 :                return synthesize_uvouv_expression(operation, branch);
   30753             :             }
   30754     1505838 :             else if (vob_optimisable(operation, branch))
   30755             :             {
   30756       52659 :                return synthesize_vob_expression::process((*this), operation, branch);
   30757             :             }
   30758     1453179 :             else if (bov_optimisable(operation, branch))
   30759             :             {
   30760      361461 :                return synthesize_bov_expression::process((*this), operation, branch);
   30761             :             }
   30762     1091718 :             else if (cob_optimisable(operation, branch))
   30763             :             {
   30764       98942 :                return synthesize_cob_expression::process((*this), operation, branch);
   30765             :             }
   30766      992776 :             else if (boc_optimisable(operation, branch))
   30767             :             {
   30768      146238 :                return synthesize_boc_expression::process((*this), operation, branch);
   30769             :             }
   30770             :             #ifndef exprtk_disable_enhanced_features
   30771      846538 :             else if (cov_optimisable(operation, branch))
   30772             :             {
   30773           0 :                return synthesize_cov_expression::process((*this), operation, branch);
   30774             :             }
   30775             :             #endif
   30776      846538 :             else if (binext_optimisable(operation, branch))
   30777             :             {
   30778      405857 :                return synthesize_binary_ext_expression::process((*this), operation, branch);
   30779             :             }
   30780             :             else
   30781      440681 :                return synthesize_expression<binary_node_t,2>(operation, branch);
   30782             :          }
   30783             : 
   30784         471 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
   30785             :          {
   30786         471 :             if (
   30787         471 :                  (0 == branch[0]) ||
   30788         471 :                  (0 == branch[1]) ||
   30789         471 :                  (0 == branch[2])
   30790             :                )
   30791             :             {
   30792           0 :                details::free_all_nodes(*node_allocator_,branch);
   30793             : 
   30794           0 :                parser_->set_error(parser_error::make_error(
   30795             :                   parser_error::e_syntax,
   30796           0 :                   parser_->current_state().token,
   30797             :                   "ERR222 - Invalid branches operator '" + details::to_str(operation) + "'",
   30798             :                   exprtk_error_location));
   30799             : 
   30800           0 :                return error_node();
   30801             :             }
   30802         471 :             else if (is_invalid_string_op(operation, branch))
   30803             :             {
   30804           0 :                parser_->set_error(parser_error::make_error(
   30805             :                   parser_error::e_syntax,
   30806           0 :                   parser_->current_state().token,
   30807             :                   "ERR223 - Invalid branches for string operator '" + details::to_str(operation) + "'",
   30808             :                   exprtk_error_location));
   30809             : 
   30810           0 :                return error_node();
   30811             :             }
   30812         471 :             else if (is_string_operation(operation, branch))
   30813             :             {
   30814         355 :                return synthesize_string_expression(operation, branch);
   30815             :             }
   30816             :             else
   30817         116 :                return synthesize_expression<trinary_node_t,3>(operation, branch);
   30818             :          }
   30819             : 
   30820           0 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
   30821             :          {
   30822           0 :             return synthesize_expression<quaternary_node_t,4>(operation,branch);
   30823             :          }
   30824             : 
   30825       99078 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
   30826             :          {
   30827       99078 :             expression_node_ptr branch[1] = { b0 };
   30828      198156 :             return (*this)(operation,branch);
   30829             :          }
   30830             : 
   30831     2657728 :          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
   30832             :          {
   30833     2657728 :             expression_node_ptr result = error_node();
   30834             : 
   30835     2657728 :             if ((0 != b0) && (0 != b1))
   30836             :             {
   30837     2657728 :                expression_node_ptr branch[2] = { b0, b1 };
   30838     2657728 :                result = expression_generator<Type>::operator()(operation, branch);
   30839     2657728 :                b0 = branch[0];
   30840     2657728 :                b1 = branch[1];
   30841             :             }
   30842             : 
   30843     2657728 :             return result;
   30844             :          }
   30845             : 
   30846        5614 :          inline expression_node_ptr conditional(expression_node_ptr condition,
   30847             :                                                 expression_node_ptr consequent,
   30848             :                                                 expression_node_ptr alternative) const
   30849             :          {
   30850        5614 :             if ((0 == condition) || (0 == consequent))
   30851             :             {
   30852           0 :                details::free_node(*node_allocator_, condition  );
   30853           0 :                details::free_node(*node_allocator_, consequent );
   30854           0 :                details::free_node(*node_allocator_, alternative);
   30855             : 
   30856           0 :                const std::string invalid_branches =
   30857           0 :                                  ((0 == condition ) ? std::string("condition ") : "") +
   30858           0 :                                  ((0 == consequent) ? std::string("consequent") : "") ;
   30859             : 
   30860           0 :                parser_->set_error(parser_error::make_error(
   30861             :                   parser_error::e_parser,
   30862           0 :                   parser_->current_state().token,
   30863             :                   "ERR224 - Invalid " + invalid_branches + " for conditional statement",
   30864             :                   exprtk_error_location));
   30865             : 
   30866           0 :                return error_node();
   30867           0 :             }
   30868             :             // Can the condition be immediately evaluated? if so optimise.
   30869        5614 :             else if (details::is_constant_node(condition))
   30870             :             {
   30871             :                // True branch
   30872        1756 :                if (details::is_true(condition))
   30873             :                {
   30874        1126 :                   details::free_node(*node_allocator_, condition  );
   30875        1126 :                   details::free_node(*node_allocator_, alternative);
   30876             : 
   30877        1126 :                   return consequent;
   30878             :                }
   30879             :                // False branch
   30880             :                else
   30881             :                {
   30882         630 :                   details::free_node(*node_allocator_, condition );
   30883         630 :                   details::free_node(*node_allocator_, consequent);
   30884             : 
   30885         630 :                   if (alternative)
   30886         570 :                      return alternative;
   30887             :                   else
   30888          60 :                      return node_allocator_->allocate<details::null_node<T> >();
   30889             :                }
   30890             :             }
   30891             : 
   30892        3858 :             expression_node_ptr result = error_node();
   30893        3858 :             std::string node_name      = "Unknown!";
   30894             : 
   30895        3858 :             if ((0 != consequent) && (0 != alternative))
   30896             :             {
   30897        2837 :                result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative);
   30898        2837 :                node_name = "conditional_node_t";
   30899             :             }
   30900             :             else
   30901             :             {
   30902        1021 :                result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent);
   30903        1021 :                node_name = "cons_conditional_node_t";
   30904             :             }
   30905             : 
   30906        3858 :             if (result && result->valid())
   30907             :             {
   30908        3858 :                return result;
   30909             :             }
   30910             : 
   30911           0 :             parser_->set_error(parser_error::make_error(
   30912             :                parser_error::e_parser,
   30913           0 :                token_t(),
   30914             :                "ERR225 - Failed to synthesize node: " + node_name,
   30915             :                exprtk_error_location));
   30916             : 
   30917           0 :             details::free_node(*node_allocator_, result);
   30918           0 :             return error_node();
   30919        3858 :          }
   30920             : 
   30921             :          #ifndef exprtk_disable_string_capabilities
   30922        1145 :          inline expression_node_ptr conditional_string(expression_node_ptr condition,
   30923             :                                                        expression_node_ptr consequent,
   30924             :                                                        expression_node_ptr alternative) const
   30925             :          {
   30926        1145 :             if ((0 == condition) || (0 == consequent))
   30927             :             {
   30928           0 :                details::free_node(*node_allocator_, condition  );
   30929           0 :                details::free_node(*node_allocator_, consequent );
   30930           0 :                details::free_node(*node_allocator_, alternative);
   30931             : 
   30932           0 :                const std::string invalid_branches =
   30933           0 :                                  ((0 == condition ) ? std::string("condition ") : "") +
   30934           0 :                                  ((0 == consequent) ? std::string("consequent") : "") ;
   30935             : 
   30936           0 :                parser_->set_error(parser_error::make_error(
   30937             :                   parser_error::e_parser,
   30938           0 :                   parser_->current_state().token,
   30939             :                   "ERR226 - Invalid " + invalid_branches + " for string conditional statement",
   30940             :                   exprtk_error_location));
   30941             : 
   30942           0 :                return error_node();
   30943           0 :             }
   30944             :             // Can the condition be immediately evaluated? if so optimise.
   30945        1145 :             else if (details::is_constant_node(condition))
   30946             :             {
   30947             :                // True branch
   30948           0 :                if (details::is_true(condition))
   30949             :                {
   30950           0 :                   details::free_node(*node_allocator_, condition  );
   30951           0 :                   details::free_node(*node_allocator_, alternative);
   30952             : 
   30953           0 :                   return consequent;
   30954             :                }
   30955             :                // False branch
   30956             :                else
   30957             :                {
   30958           0 :                   details::free_node(*node_allocator_, condition );
   30959           0 :                   details::free_node(*node_allocator_, consequent);
   30960             : 
   30961           0 :                   if (alternative)
   30962           0 :                      return alternative;
   30963             :                   else
   30964           0 :                      return node_allocator_->
   30965           0 :                               allocate_c<details::string_literal_node<Type> >("");
   30966             :                }
   30967             :             }
   30968        1145 :             else if ((0 != consequent) && (0 != alternative))
   30969             :             {
   30970        1145 :                expression_node_ptr result =
   30971        1145 :                   node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative);
   30972             : 
   30973        1145 :                if (result && result->valid())
   30974             :                {
   30975        1145 :                   return result;
   30976             :                }
   30977             : 
   30978           0 :                parser_->set_error(parser_error::make_error(
   30979             :                   parser_error::e_parser,
   30980           0 :                   token_t(),
   30981             :                   "ERR227 - Failed to synthesize node: conditional_string_node_t",
   30982             :                   exprtk_error_location));
   30983             : 
   30984           0 :                details::free_node(*node_allocator_, result);
   30985             :             }
   30986             : 
   30987           0 :             return error_node();
   30988             :          }
   30989             :          #else
   30990             :          inline expression_node_ptr conditional_string(expression_node_ptr,
   30991             :                                                        expression_node_ptr,
   30992             :                                                        expression_node_ptr) const
   30993             :          {
   30994             :             return error_node();
   30995             :          }
   30996             :          #endif
   30997             : 
   30998        1528 :          inline expression_node_ptr conditional_vector(expression_node_ptr condition,
   30999             :                                                        expression_node_ptr consequent,
   31000             :                                                        expression_node_ptr alternative) const
   31001             :          {
   31002        1528 :             if ((0 == condition) || (0 == consequent))
   31003             :             {
   31004           0 :                details::free_node(*node_allocator_, condition  );
   31005           0 :                details::free_node(*node_allocator_, consequent );
   31006           0 :                details::free_node(*node_allocator_, alternative);
   31007             : 
   31008           0 :                const std::string invalid_branches =
   31009           0 :                                  ((0 == condition ) ? std::string("condition ") : "") +
   31010           0 :                                  ((0 == consequent) ? std::string("consequent") : "") ;
   31011             : 
   31012           0 :                parser_->set_error(parser_error::make_error(
   31013             :                   parser_error::e_parser,
   31014           0 :                   parser_->current_state().token,
   31015             :                   "ERR228 - Invalid " + invalid_branches + " for vector conditional statement",
   31016             :                   exprtk_error_location));
   31017             : 
   31018           0 :                return error_node();
   31019           0 :             }
   31020             :             // Can the condition be immediately evaluated? if so optimise.
   31021        1528 :             else if (details::is_constant_node(condition))
   31022             :             {
   31023             :                // True branch
   31024         760 :                if (details::is_true(condition))
   31025             :                {
   31026         380 :                   details::free_node(*node_allocator_, condition  );
   31027         380 :                   details::free_node(*node_allocator_, alternative);
   31028             : 
   31029         380 :                   return consequent;
   31030             :                }
   31031             :                // False branch
   31032             :                else
   31033             :                {
   31034         380 :                   details::free_node(*node_allocator_, condition );
   31035         380 :                   details::free_node(*node_allocator_, consequent);
   31036             : 
   31037         380 :                   if (alternative)
   31038         380 :                      return alternative;
   31039             :                   else
   31040           0 :                      return node_allocator_->allocate<details::null_node<T> >();
   31041             : 
   31042             :                }
   31043             :             }
   31044         768 :             else if ((0 != consequent) && (0 != alternative))
   31045             :             {
   31046         768 :                return node_allocator_->
   31047         768 :                         allocate<conditional_vector_node_t>(condition, consequent, alternative);
   31048             :             }
   31049             :             else
   31050           0 :                return error_node();
   31051             :          }
   31052             : 
   31053        2687 :          inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
   31054             :          {
   31055        2687 :             if (
   31056        2687 :                  parser_->loop_runtime_check_ &&
   31057           0 :                  (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type))
   31058             :                )
   31059             :             {
   31060           0 :                return parser_->loop_runtime_check_;
   31061             :             }
   31062             : 
   31063        2687 :             return loop_runtime_check_ptr(0);
   31064             :          }
   31065             : 
   31066        6618 :          inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const
   31067             :          {
   31068        6618 :             return parser_->vector_access_runtime_check_;
   31069             :          }
   31070             : 
   31071          22 :          inline expression_node_ptr while_loop(expression_node_ptr& condition,
   31072             :                                                expression_node_ptr& branch,
   31073             :                                                const bool break_continue_present = false) const
   31074             :          {
   31075          22 :             if (!break_continue_present && details::is_constant_node(condition))
   31076             :             {
   31077           0 :                expression_node_ptr result = error_node();
   31078           0 :                if (details::is_true(condition))
   31079             :                {
   31080             :                   // Infinite loops are not allowed.
   31081             : 
   31082           0 :                   parser_->set_error(parser_error::make_error(
   31083             :                      parser_error::e_parser,
   31084           0 :                      parser_->current_state().token,
   31085             :                      "ERR229 - Infinite loop condition with 'break' not allowed in while-loops",
   31086             :                      exprtk_error_location));
   31087             : 
   31088           0 :                   result = error_node();
   31089             :                }
   31090             :                else
   31091           0 :                   result = node_allocator_->allocate<details::null_node<Type> >();
   31092             : 
   31093           0 :                details::free_node(*node_allocator_, condition);
   31094           0 :                details::free_node(*node_allocator_, branch   );
   31095             : 
   31096           0 :                return result;
   31097             :             }
   31098          22 :             else if (details::is_null_node(condition))
   31099             :             {
   31100           0 :                details::free_node(*node_allocator_,condition);
   31101             : 
   31102           0 :                return branch;
   31103             :             }
   31104             : 
   31105          22 :             loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop);
   31106             : 
   31107          22 :             if (!break_continue_present)
   31108             :             {
   31109          12 :                if (rtc)
   31110           0 :                   return node_allocator_->allocate<while_loop_rtc_node_t>
   31111           0 :                            (condition, branch,  rtc);
   31112             :                else
   31113          12 :                   return node_allocator_->allocate<while_loop_node_t>
   31114          12 :                            (condition, branch);
   31115             :             }
   31116             :             #ifndef exprtk_disable_break_continue
   31117             :             else
   31118             :             {
   31119          10 :                if (rtc)
   31120           0 :                   return node_allocator_->allocate<while_loop_bc_rtc_node_t>
   31121           0 :                            (condition, branch, rtc);
   31122             :                else
   31123          10 :                   return node_allocator_->allocate<while_loop_bc_node_t>
   31124          10 :                            (condition, branch);
   31125             :             }
   31126             :             #else
   31127             :                return error_node();
   31128             :             #endif
   31129             :          }
   31130             : 
   31131          82 :          inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
   31132             :                                                       expression_node_ptr& branch,
   31133             :                                                       const bool break_continue_present = false) const
   31134             :          {
   31135          82 :             if (!break_continue_present && details::is_constant_node(condition))
   31136             :             {
   31137          80 :                if (
   31138         160 :                     details::is_true(condition) &&
   31139          80 :                     details::is_constant_node(branch)
   31140             :                   )
   31141             :                {
   31142          80 :                   free_node(*node_allocator_,condition);
   31143             : 
   31144          80 :                   return branch;
   31145             :                }
   31146             : 
   31147           0 :                details::free_node(*node_allocator_, condition);
   31148           0 :                details::free_node(*node_allocator_, branch   );
   31149             : 
   31150           0 :                return error_node();
   31151             :             }
   31152           2 :             else if (details::is_null_node(condition))
   31153             :             {
   31154           0 :                details::free_node(*node_allocator_,condition);
   31155             : 
   31156           0 :                return branch;
   31157             :             }
   31158             : 
   31159           2 :             loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop);
   31160             : 
   31161           2 :             if (!break_continue_present)
   31162             :             {
   31163           1 :                if (rtc)
   31164           0 :                   return node_allocator_->allocate<repeat_until_loop_rtc_node_t>
   31165           0 :                            (condition, branch,  rtc);
   31166             :                else
   31167           1 :                   return node_allocator_->allocate<repeat_until_loop_node_t>
   31168           1 :                            (condition, branch);
   31169             :             }
   31170             :             #ifndef exprtk_disable_break_continue
   31171             :             else
   31172             :             {
   31173           1 :                if (rtc)
   31174           0 :                   return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t>
   31175           0 :                            (condition, branch, rtc);
   31176             :                else
   31177           1 :                   return node_allocator_->allocate<repeat_until_loop_bc_node_t>
   31178           1 :                            (condition, branch);
   31179             :             }
   31180             :             #else
   31181             :                return error_node();
   31182             :             #endif
   31183             :          }
   31184             : 
   31185        2663 :          inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
   31186             :                                              expression_node_ptr& condition,
   31187             :                                              expression_node_ptr& incrementor,
   31188             :                                              expression_node_ptr& loop_body,
   31189             :                                              bool break_continue_present = false) const
   31190             :          {
   31191        2663 :             if (!break_continue_present && details::is_constant_node(condition))
   31192             :             {
   31193           0 :                expression_node_ptr result = error_node();
   31194             : 
   31195           0 :                if (details::is_true(condition))
   31196             :                {
   31197             :                   // Infinite loops are not allowed.
   31198             : 
   31199           0 :                   parser_->set_error(parser_error::make_error(
   31200             :                      parser_error::e_parser,
   31201           0 :                      parser_->current_state().token,
   31202             :                      "ERR230 - Infinite loop condition without 'break' not allowed in for-loop",
   31203             :                      exprtk_error_location));
   31204             : 
   31205           0 :                   result = error_node();
   31206             :                }
   31207             :                else
   31208           0 :                   result = node_allocator_->allocate<details::null_node<Type> >();
   31209             : 
   31210           0 :                details::free_node(*node_allocator_, initialiser);
   31211           0 :                details::free_node(*node_allocator_, condition  );
   31212           0 :                details::free_node(*node_allocator_, incrementor);
   31213           0 :                details::free_node(*node_allocator_, loop_body  );
   31214             : 
   31215           0 :                return result;
   31216             :             }
   31217        2663 :             else if (details::is_null_node(condition) || (0 == condition))
   31218             :             {
   31219           0 :                details::free_node(*node_allocator_, initialiser);
   31220           0 :                details::free_node(*node_allocator_, condition  );
   31221           0 :                details::free_node(*node_allocator_, incrementor);
   31222             : 
   31223           0 :                return loop_body;
   31224             :             }
   31225             : 
   31226        2663 :             loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop);
   31227             : 
   31228        2663 :             if (!break_continue_present)
   31229             :             {
   31230        2051 :                if (rtc)
   31231           0 :                   return node_allocator_->allocate<for_loop_rtc_node_t>
   31232           0 :                                           (
   31233             :                                              initialiser,
   31234             :                                              condition,
   31235             :                                              incrementor,
   31236             :                                              loop_body,
   31237             :                                              rtc
   31238           0 :                                           );
   31239             :                else
   31240        2051 :                   return node_allocator_->allocate<for_loop_node_t>
   31241        2051 :                                           (
   31242             :                                              initialiser,
   31243             :                                              condition,
   31244             :                                              incrementor,
   31245             :                                              loop_body
   31246        2051 :                                           );
   31247             :             }
   31248             :             #ifndef exprtk_disable_break_continue
   31249             :             else
   31250             :             {
   31251         612 :                if (rtc)
   31252           0 :                   return node_allocator_->allocate<for_loop_bc_rtc_node_t>
   31253           0 :                                           (
   31254             :                                              initialiser,
   31255             :                                              condition,
   31256             :                                              incrementor,
   31257             :                                              loop_body,
   31258             :                                              rtc
   31259           0 :                                           );
   31260             :                else
   31261         612 :                   return node_allocator_->allocate<for_loop_bc_node_t>
   31262         612 :                                           (
   31263             :                                              initialiser,
   31264             :                                              condition,
   31265             :                                              incrementor,
   31266             :                                              loop_body
   31267         612 :                                           );
   31268             :             }
   31269             :             #else
   31270             :                return error_node();
   31271             :             #endif
   31272             :          }
   31273             : 
   31274             :          template <typename Allocator,
   31275             :                    template <typename, typename> class Sequence>
   31276         190 :          inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
   31277             :          {
   31278         190 :             expression_node_ptr result = error_node();
   31279             : 
   31280         190 :             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
   31281             :             {
   31282         180 :                expression_node_ptr condition  = arg_list[(2 * i)    ];
   31283         180 :                expression_node_ptr consequent = arg_list[(2 * i) + 1];
   31284             : 
   31285         180 :                if ((0 == result) && details::is_true(condition))
   31286             :                {
   31287         180 :                   result = consequent;
   31288         180 :                   break;
   31289             :                }
   31290             :             }
   31291             : 
   31292         190 :             if (0 == result)
   31293             :             {
   31294          10 :                result = arg_list.back();
   31295             :             }
   31296             : 
   31297         740 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   31298             :             {
   31299         550 :                expression_node_ptr current_expr = arg_list[i];
   31300             : 
   31301         550 :                if (current_expr && (current_expr != result))
   31302             :                {
   31303         360 :                   free_node(*node_allocator_,current_expr);
   31304             :                }
   31305             :             }
   31306             : 
   31307         190 :             return result;
   31308             :          }
   31309             : 
   31310             :          template <typename Allocator,
   31311             :                    template <typename, typename> class Sequence>
   31312          10 :          inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
   31313             :          {
   31314          10 :             expression_node_ptr result = error_node();
   31315             : 
   31316          50 :             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
   31317             :             {
   31318          40 :                expression_node_ptr condition  = arg_list[(2 * i)    ];
   31319          40 :                expression_node_ptr consequent = arg_list[(2 * i) + 1];
   31320             : 
   31321          40 :                if (details::is_true(condition))
   31322             :                {
   31323          40 :                   result = consequent;
   31324             :                }
   31325             :             }
   31326             : 
   31327          10 :             if (0 == result)
   31328             :             {
   31329           0 :                const T zero = T(0);
   31330           0 :                result       = node_allocator_->allocate<literal_node_t>(zero);
   31331             :             }
   31332             : 
   31333          90 :             for (std::size_t i = 0; i < arg_list.size(); ++i)
   31334             :             {
   31335          80 :                expression_node_ptr& current_expr = arg_list[i];
   31336             : 
   31337          80 :                if (current_expr && (current_expr != result))
   31338             :                {
   31339          70 :                   details::free_node(*node_allocator_,current_expr);
   31340             :                }
   31341             :             }
   31342             : 
   31343          10 :             return result;
   31344             :          }
   31345             : 
   31346             :          struct switch_nodes
   31347             :          {
   31348             :             typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t;
   31349             : 
   31350             :             #define case_stmt(N)                                                         \
   31351             :             if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
   31352             : 
   31353             :             struct switch_impl_1
   31354             :             {
   31355         740 :                static inline T process(const arg_list_t& arg)
   31356             :                {
   31357         740 :                   case_stmt(0)
   31358             : 
   31359          10 :                   assert(arg.size() == ((2 * 1) + 1));
   31360             : 
   31361          10 :                   return arg.back().first->value();
   31362             :                }
   31363             :             };
   31364             : 
   31365             :             struct switch_impl_2
   31366             :             {
   31367    11458441 :                static inline T process(const arg_list_t& arg)
   31368             :                {
   31369    11458441 :                   case_stmt(0) case_stmt(1)
   31370             : 
   31371     5755024 :                   assert(arg.size() == ((2 * 2) + 1));
   31372             : 
   31373     5755024 :                   return arg.back().first->value();
   31374             :                }
   31375             :             };
   31376             : 
   31377             :             struct switch_impl_3
   31378             :             {
   31379         100 :                static inline T process(const arg_list_t& arg)
   31380             :                {
   31381         100 :                   case_stmt(0) case_stmt(1)
   31382          99 :                   case_stmt(2)
   31383             : 
   31384          98 :                   assert(arg.size() == ((2 * 3) + 1));
   31385             : 
   31386          98 :                   return arg.back().first->value();
   31387             :                }
   31388             :             };
   31389             : 
   31390             :             struct switch_impl_4
   31391             :             {
   31392           0 :                static inline T process(const arg_list_t& arg)
   31393             :                {
   31394           0 :                   case_stmt(0) case_stmt(1)
   31395           0 :                   case_stmt(2) case_stmt(3)
   31396             : 
   31397           0 :                   assert(arg.size() == ((2 * 4) + 1));
   31398             : 
   31399           0 :                   return arg.back().first->value();
   31400             :                }
   31401             :             };
   31402             : 
   31403             :             struct switch_impl_5
   31404             :             {
   31405           0 :                static inline T process(const arg_list_t& arg)
   31406             :                {
   31407           0 :                   case_stmt(0) case_stmt(1)
   31408           0 :                   case_stmt(2) case_stmt(3)
   31409           0 :                   case_stmt(4)
   31410             : 
   31411           0 :                   assert(arg.size() == ((2 * 5) + 1));
   31412             : 
   31413           0 :                   return arg.back().first->value();
   31414             :                }
   31415             :             };
   31416             : 
   31417             :             struct switch_impl_6
   31418             :             {
   31419         136 :                static inline T process(const arg_list_t& arg)
   31420             :                {
   31421         136 :                   case_stmt(0) case_stmt(1)
   31422         135 :                   case_stmt(2) case_stmt(3)
   31423         133 :                   case_stmt(4) case_stmt(5)
   31424             : 
   31425         132 :                   assert(arg.size() == ((2 * 6) + 1));
   31426             : 
   31427         132 :                   return arg.back().first->value();
   31428             :                }
   31429             :             };
   31430             : 
   31431             :             struct switch_impl_7
   31432             :             {
   31433           0 :                static inline T process(const arg_list_t& arg)
   31434             :                {
   31435           0 :                   case_stmt(0) case_stmt(1)
   31436           0 :                   case_stmt(2) case_stmt(3)
   31437           0 :                   case_stmt(4) case_stmt(5)
   31438           0 :                   case_stmt(6)
   31439             : 
   31440           0 :                   assert(arg.size() == ((2 * 7) + 1));
   31441             : 
   31442           0 :                   return arg.back().first->value();
   31443             :                }
   31444             :             };
   31445             : 
   31446             :             #undef case_stmt
   31447             :          };
   31448             : 
   31449             :          template <typename Allocator,
   31450             :                    template <typename, typename> class Sequence>
   31451        1195 :          inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present)
   31452             :          {
   31453        1195 :             if (arg_list.empty())
   31454           0 :                return error_node();
   31455        1195 :             else if (
   31456        2390 :                       !all_nodes_valid(arg_list) ||
   31457        1195 :                       (!default_statement_present && (arg_list.size() < 2))
   31458             :                     )
   31459             :             {
   31460           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   31461             : 
   31462           0 :                return error_node();
   31463             :             }
   31464        1195 :             else if (is_constant_foldable(arg_list))
   31465         190 :                return const_optimise_switch(arg_list);
   31466             : 
   31467        1005 :             switch ((arg_list.size() - 1) / 2)
   31468             :             {
   31469             :                #define case_stmt(N)                                                       \
   31470             :                case N :                                                                   \
   31471             :                   return node_allocator_->                                                \
   31472             :                             allocate<details::switch_n_node                               \
   31473             :                               <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \
   31474             : 
   31475         740 :                case_stmt(1)
   31476         263 :                case_stmt(2)
   31477           1 :                case_stmt(3)
   31478           0 :                case_stmt(4)
   31479           0 :                case_stmt(5)
   31480           1 :                case_stmt(6)
   31481           0 :                case_stmt(7)
   31482             :                #undef case_stmt
   31483             : 
   31484           0 :                default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
   31485             :             }
   31486             :          }
   31487             : 
   31488             :          template <typename Allocator,
   31489             :                    template <typename, typename> class Sequence>
   31490         190 :          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
   31491             :          {
   31492         190 :             if (!all_nodes_valid(arg_list))
   31493             :             {
   31494           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   31495             : 
   31496           0 :                return error_node();
   31497             :             }
   31498         190 :             else if (is_constant_foldable(arg_list))
   31499          10 :                return const_optimise_mswitch(arg_list);
   31500             :             else
   31501         180 :                return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
   31502             :          }
   31503             : 
   31504             :          #define unary_opr_switch_statements             \
   31505             :          case_stmt(details::e_abs   , details::abs_op  ) \
   31506             :          case_stmt(details::e_acos  , details::acos_op ) \
   31507             :          case_stmt(details::e_acosh , details::acosh_op) \
   31508             :          case_stmt(details::e_asin  , details::asin_op ) \
   31509             :          case_stmt(details::e_asinh , details::asinh_op) \
   31510             :          case_stmt(details::e_atan  , details::atan_op ) \
   31511             :          case_stmt(details::e_atanh , details::atanh_op) \
   31512             :          case_stmt(details::e_ceil  , details::ceil_op ) \
   31513             :          case_stmt(details::e_cos   , details::cos_op  ) \
   31514             :          case_stmt(details::e_cosh  , details::cosh_op ) \
   31515             :          case_stmt(details::e_exp   , details::exp_op  ) \
   31516             :          case_stmt(details::e_expm1 , details::expm1_op) \
   31517             :          case_stmt(details::e_floor , details::floor_op) \
   31518             :          case_stmt(details::e_log   , details::log_op  ) \
   31519             :          case_stmt(details::e_log10 , details::log10_op) \
   31520             :          case_stmt(details::e_log2  , details::log2_op ) \
   31521             :          case_stmt(details::e_log1p , details::log1p_op) \
   31522             :          case_stmt(details::e_neg   , details::neg_op  ) \
   31523             :          case_stmt(details::e_pos   , details::pos_op  ) \
   31524             :          case_stmt(details::e_round , details::round_op) \
   31525             :          case_stmt(details::e_sin   , details::sin_op  ) \
   31526             :          case_stmt(details::e_sinc  , details::sinc_op ) \
   31527             :          case_stmt(details::e_sinh  , details::sinh_op ) \
   31528             :          case_stmt(details::e_sqrt  , details::sqrt_op ) \
   31529             :          case_stmt(details::e_tan   , details::tan_op  ) \
   31530             :          case_stmt(details::e_tanh  , details::tanh_op ) \
   31531             :          case_stmt(details::e_cot   , details::cot_op  ) \
   31532             :          case_stmt(details::e_sec   , details::sec_op  ) \
   31533             :          case_stmt(details::e_csc   , details::csc_op  ) \
   31534             :          case_stmt(details::e_r2d   , details::r2d_op  ) \
   31535             :          case_stmt(details::e_d2r   , details::d2r_op  ) \
   31536             :          case_stmt(details::e_d2g   , details::d2g_op  ) \
   31537             :          case_stmt(details::e_g2d   , details::g2d_op  ) \
   31538             :          case_stmt(details::e_notl  , details::notl_op ) \
   31539             :          case_stmt(details::e_sgn   , details::sgn_op  ) \
   31540             :          case_stmt(details::e_erf   , details::erf_op  ) \
   31541             :          case_stmt(details::e_erfc  , details::erfc_op ) \
   31542             :          case_stmt(details::e_ncdf  , details::ncdf_op ) \
   31543             :          case_stmt(details::e_frac  , details::frac_op ) \
   31544             :          case_stmt(details::e_trunc , details::trunc_op) \
   31545             : 
   31546        7697 :          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
   31547             :                                                              expression_node_ptr (&branch)[1])
   31548             :          {
   31549        7697 :             T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
   31550             : 
   31551        7697 :             switch (operation)
   31552             :             {
   31553             :                #define case_stmt(op0, op1)                                                         \
   31554             :                case op0 : return node_allocator_->                                                 \
   31555             :                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
   31556             : 
   31557        7697 :                unary_opr_switch_statements
   31558             :                #undef case_stmt
   31559           0 :                default : return error_node();
   31560             :             }
   31561             :          }
   31562             : 
   31563        1430 :          inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
   31564             :                                                                expression_node_ptr (&branch)[1])
   31565             :          {
   31566        1430 :             switch (operation)
   31567             :             {
   31568             :                #define case_stmt(op0, op1)                                                   \
   31569             :                case op0 : return node_allocator_->                                           \
   31570             :                              allocate<typename details::unary_vector_node<Type,op1<Type> > > \
   31571             :                                 (operation, branch[0]);                                      \
   31572             : 
   31573        1430 :                unary_opr_switch_statements
   31574             :                #undef case_stmt
   31575           0 :                default : return error_node();
   31576             :             }
   31577             :          }
   31578             : 
   31579       59908 :          inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
   31580             :                                                                 expression_node_ptr (&branch)[1])
   31581             :          {
   31582       59908 :             switch (operation)
   31583             :             {
   31584             :                #define case_stmt(op0, op1)                                                               \
   31585             :                case op0 : return node_allocator_->                                                       \
   31586             :                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
   31587             : 
   31588       59908 :                unary_opr_switch_statements
   31589             :                #undef case_stmt
   31590           0 :                default : return error_node();
   31591             :             }
   31592             :          }
   31593             : 
   31594         720 :          inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
   31595             :                                                        expression_node_ptr (&branch)[3])
   31596             :          {
   31597         720 :             expression_node_ptr temp_node = error_node();
   31598             : 
   31599         720 :             switch (operation)
   31600             :             {
   31601             :                #define case_stmt(op)                                                        \
   31602             :                case details::e_sf##op : temp_node = node_allocator_->                       \
   31603             :                              allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
   31604             :                                 (operation, branch);                                        \
   31605             :                              break;                                                         \
   31606             : 
   31607          60 :                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   31608          60 :                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   31609          60 :                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   31610          60 :                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   31611          60 :                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   31612          60 :                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   31613          60 :                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   31614          60 :                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
   31615          60 :                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
   31616          60 :                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
   31617          60 :                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
   31618          60 :                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
   31619             :                #undef case_stmt
   31620           0 :                default : return error_node();
   31621             :             }
   31622             : 
   31623         720 :             assert(temp_node);
   31624             : 
   31625         720 :             const T v = temp_node->value();
   31626             : 
   31627         720 :             details::free_node(*node_allocator_,temp_node);
   31628             : 
   31629         720 :             return node_allocator_->allocate<literal_node_t>(v);
   31630             :          }
   31631             : 
   31632        1200 :          inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
   31633             :          {
   31634             :             typedef details::variable_node<Type>* variable_ptr;
   31635             : 
   31636        1200 :             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
   31637        1200 :             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
   31638        1200 :             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
   31639             : 
   31640        1200 :             switch (operation)
   31641             :             {
   31642             :                #define case_stmt(op)                                                                \
   31643             :                case details::e_sf##op : return node_allocator_->                                    \
   31644             :                              allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
   31645             :                                 (v0, v1, v2);                                                       \
   31646             : 
   31647         100 :                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   31648         100 :                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   31649         100 :                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   31650         100 :                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   31651         100 :                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   31652         100 :                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   31653         100 :                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   31654         100 :                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
   31655         100 :                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
   31656         100 :                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
   31657         100 :                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
   31658         100 :                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
   31659             :                #undef case_stmt
   31660           0 :                default : return error_node();
   31661             :             }
   31662             :          }
   31663             : 
   31664        1920 :          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
   31665             :          {
   31666        1920 :             if (!all_nodes_valid(branch))
   31667           0 :                return error_node();
   31668        1920 :             else if (is_constant_foldable(branch))
   31669         720 :                return const_optimise_sf3(operation,branch);
   31670        1200 :             else if (all_nodes_variables(branch))
   31671        1200 :                return varnode_optimise_sf3(operation,branch);
   31672             :             else
   31673             :             {
   31674           0 :                switch (operation)
   31675             :                {
   31676             :                   #define case_stmt(op)                                                        \
   31677             :                   case details::e_sf##op : return node_allocator_->                            \
   31678             :                                 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
   31679             :                                    (operation, branch);                                        \
   31680             : 
   31681           0 :                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   31682           0 :                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   31683           0 :                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   31684           0 :                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   31685           0 :                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   31686           0 :                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   31687           0 :                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   31688           0 :                   case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
   31689           0 :                   case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
   31690           0 :                   case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
   31691           0 :                   case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
   31692           0 :                   case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
   31693             :                   #undef case_stmt
   31694           0 :                   default : return error_node();
   31695             :                }
   31696             :             }
   31697             :          }
   31698             : 
   31699         815 :          inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
   31700             :          {
   31701         815 :             expression_node_ptr temp_node = error_node();
   31702             : 
   31703         815 :             switch (operation)
   31704             :             {
   31705             :                #define case_stmt(op)                                                                    \
   31706             :                case details::e_sf##op : temp_node = node_allocator_->                                   \
   31707             :                                          allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
   31708             :                                             (operation, branch);                                        \
   31709             :                                         break;                                                          \
   31710             : 
   31711          60 :                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
   31712          60 :                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
   31713          60 :                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
   31714          60 :                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
   31715          60 :                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
   31716          60 :                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
   31717          60 :                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
   31718          60 :                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
   31719          60 :                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
   31720          60 :                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
   31721          60 :                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
   31722          80 :                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
   31723          75 :                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
   31724             :                #undef case_stmt
   31725           0 :                default : return error_node();
   31726             :             }
   31727             : 
   31728         815 :             assert(temp_node);
   31729             : 
   31730         815 :             const T v = temp_node->value();
   31731             : 
   31732         815 :             details::free_node(*node_allocator_,temp_node);
   31733             : 
   31734         815 :             return node_allocator_->allocate<literal_node_t>(v);
   31735             :          }
   31736             : 
   31737        1510 :          inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
   31738             :          {
   31739             :             typedef details::variable_node<Type>* variable_ptr;
   31740             : 
   31741        1510 :             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
   31742        1510 :             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
   31743        1510 :             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
   31744        1510 :             const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
   31745             : 
   31746        1510 :             switch (operation)
   31747             :             {
   31748             :                #define case_stmt(op)                                                                 \
   31749             :                case details::e_sf##op : return node_allocator_->                                     \
   31750             :                              allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
   31751             :                                 (v0, v1, v2, v3);                                                    \
   31752             : 
   31753         100 :                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
   31754         100 :                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
   31755         100 :                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
   31756         100 :                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
   31757         100 :                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
   31758         100 :                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
   31759         100 :                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
   31760         100 :                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
   31761         100 :                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
   31762         100 :                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
   31763         100 :                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
   31764         220 :                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
   31765         190 :                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
   31766             :                #undef case_stmt
   31767           0 :                default : return error_node();
   31768             :             }
   31769             :          }
   31770             : 
   31771        2325 :          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
   31772             :          {
   31773        2325 :             if (!all_nodes_valid(branch))
   31774           0 :                return error_node();
   31775        2325 :             else if (is_constant_foldable(branch))
   31776         815 :                return const_optimise_sf4(operation,branch);
   31777        1510 :             else if (all_nodes_variables(branch))
   31778        1510 :                return varnode_optimise_sf4(operation,branch);
   31779           0 :             switch (operation)
   31780             :             {
   31781             :                #define case_stmt(op)                                                        \
   31782             :                case details::e_sf##op : return node_allocator_->                            \
   31783             :                              allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
   31784             :                                 (operation, branch);                                        \
   31785             : 
   31786           0 :                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
   31787           0 :                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
   31788           0 :                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
   31789           0 :                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
   31790           0 :                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
   31791           0 :                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
   31792           0 :                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
   31793           0 :                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
   31794           0 :                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
   31795           0 :                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
   31796           0 :                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
   31797           0 :                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
   31798           0 :                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
   31799             :                #undef case_stmt
   31800           0 :                default : return error_node();
   31801             :             }
   31802             :          }
   31803             : 
   31804             :          template <typename Allocator,
   31805             :                    template <typename, typename> class Sequence>
   31806        1377 :          inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
   31807             :          {
   31808        1377 :             expression_node_ptr temp_node = error_node();
   31809             : 
   31810        1377 :             switch (operation)
   31811             :             {
   31812             :                #define case_stmt(op0, op1)                                                \
   31813             :                case op0 : temp_node = node_allocator_->                                   \
   31814             :                                          allocate<details::vararg_node<Type,op1<Type> > > \
   31815             :                                             (arg_list);                                   \
   31816             :                           break;                                                          \
   31817             : 
   31818         160 :                case_stmt(details::e_sum   , details::vararg_add_op  )
   31819         160 :                case_stmt(details::e_prod  , details::vararg_mul_op  )
   31820         145 :                case_stmt(details::e_avg   , details::vararg_avg_op  )
   31821         227 :                case_stmt(details::e_min   , details::vararg_min_op  )
   31822         205 :                case_stmt(details::e_max   , details::vararg_max_op  )
   31823         240 :                case_stmt(details::e_mand  , details::vararg_mand_op )
   31824         240 :                case_stmt(details::e_mor   , details::vararg_mor_op  )
   31825           0 :                case_stmt(details::e_multi , details::vararg_multi_op)
   31826             :                #undef case_stmt
   31827           0 :                default : return error_node();
   31828             :             }
   31829             : 
   31830        1377 :             const T v = temp_node->value();
   31831             : 
   31832        1377 :             details::free_node(*node_allocator_,temp_node);
   31833             : 
   31834        1377 :             return node_allocator_->allocate<literal_node_t>(v);
   31835             :          }
   31836             : 
   31837          24 :          inline bool special_one_parameter_vararg(const details::operator_type& operation) const
   31838             :          {
   31839             :             return (
   31840          24 :                      (details::e_sum  == operation) ||
   31841           0 :                      (details::e_prod == operation) ||
   31842           0 :                      (details::e_avg  == operation) ||
   31843          24 :                      (details::e_min  == operation) ||
   31844           0 :                      (details::e_max  == operation)
   31845          24 :                    );
   31846             :          }
   31847             : 
   31848             :          template <typename Allocator,
   31849             :                    template <typename, typename> class Sequence>
   31850        2308 :          inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
   31851             :          {
   31852        2308 :             switch (operation)
   31853             :             {
   31854             :                #define case_stmt(op0, op1)                                                  \
   31855             :                case op0 : return node_allocator_->                                          \
   31856             :                              allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
   31857             : 
   31858           1 :                case_stmt(details::e_sum   , details::vararg_add_op  )
   31859           1 :                case_stmt(details::e_prod  , details::vararg_mul_op  )
   31860         101 :                case_stmt(details::e_avg   , details::vararg_avg_op  )
   31861        2071 :                case_stmt(details::e_min   , details::vararg_min_op  )
   31862         101 :                case_stmt(details::e_max   , details::vararg_max_op  )
   31863          16 :                case_stmt(details::e_mand  , details::vararg_mand_op )
   31864          17 :                case_stmt(details::e_mor   , details::vararg_mor_op  )
   31865           0 :                case_stmt(details::e_multi , details::vararg_multi_op)
   31866             :                #undef case_stmt
   31867           0 :                default : return error_node();
   31868             :             }
   31869             :          }
   31870             : 
   31871             :          template <typename Allocator,
   31872             :                    template <typename, typename> class Sequence>
   31873        1741 :          inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
   31874             :          {
   31875        1741 :             if (1 == arg_list.size())
   31876             :             {
   31877        1741 :                switch (operation)
   31878             :                {
   31879             :                   #define case_stmt(op0, op1)                                                     \
   31880             :                   case op0 : return node_allocator_->                                             \
   31881             :                                 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
   31882             : 
   31883        1491 :                   case_stmt(details::e_sum  , details::vec_add_op)
   31884          30 :                   case_stmt(details::e_prod , details::vec_mul_op)
   31885          66 :                   case_stmt(details::e_avg  , details::vec_avg_op)
   31886         117 :                   case_stmt(details::e_min  , details::vec_min_op)
   31887          37 :                   case_stmt(details::e_max  , details::vec_max_op)
   31888             :                   #undef case_stmt
   31889           0 :                   default : return error_node();
   31890             :                }
   31891             :             }
   31892             :             else
   31893           0 :                return error_node();
   31894             :          }
   31895             : 
   31896             :          template <typename Allocator,
   31897             :                    template <typename, typename> class Sequence>
   31898       41517 :          inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
   31899             :          {
   31900       41517 :             if (!all_nodes_valid(arg_list))
   31901             :             {
   31902           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   31903             : 
   31904           0 :                return error_node();
   31905             :             }
   31906       41517 :             else if (is_constant_foldable(arg_list))
   31907        1377 :                return const_optimise_varargfunc(operation,arg_list);
   31908       40140 :             else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0]))
   31909        1741 :                return vectorize_func(operation,arg_list);
   31910       38399 :             else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation))
   31911          24 :                return arg_list[0];
   31912       38375 :             else if (all_nodes_variables(arg_list))
   31913        2308 :                return varnode_optimise_varargfunc(operation,arg_list);
   31914             : 
   31915             :             #ifndef exprtk_disable_string_capabilities
   31916       36067 :             if (details::e_smulti == operation)
   31917             :             {
   31918         170 :                expression_node_ptr result = node_allocator_->
   31919          85 :                  allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
   31920          85 :                if (result && result->valid())
   31921             :                {
   31922          85 :                   return result;
   31923             :                }
   31924             : 
   31925           0 :                parser_->set_error(parser_error::make_error(
   31926             :                   parser_error::e_synthesis,
   31927           0 :                   token_t(),
   31928             :                   "ERR231 - Failed to synthesize node: str_vararg_node<vararg_multi_op>",
   31929             :                   exprtk_error_location));
   31930             : 
   31931           0 :                details::free_node(*node_allocator_, result);
   31932             :             }
   31933             :             else
   31934             :             #endif
   31935             :             {
   31936       35982 :                expression_node_ptr result = error_node();
   31937             : 
   31938       35982 :                switch (operation)
   31939             :                {
   31940             :                   #define case_stmt(op0, op1)                                               \
   31941             :                   case op0 : result = node_allocator_->                                     \
   31942             :                                 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
   31943             :                              break;                                                         \
   31944             : 
   31945           3 :                   case_stmt(details::e_sum   , details::vararg_add_op  )
   31946           3 :                   case_stmt(details::e_prod  , details::vararg_mul_op  )
   31947           1 :                   case_stmt(details::e_avg   , details::vararg_avg_op  )
   31948        1950 :                   case_stmt(details::e_min   , details::vararg_min_op  )
   31949           1 :                   case_stmt(details::e_max   , details::vararg_max_op  )
   31950           0 :                   case_stmt(details::e_mand  , details::vararg_mand_op )
   31951           0 :                   case_stmt(details::e_mor   , details::vararg_mor_op  )
   31952       34024 :                   case_stmt(details::e_multi , details::vararg_multi_op)
   31953             :                   #undef case_stmt
   31954       35982 :                   default : return error_node();
   31955             :                }
   31956             : 
   31957       35982 :                if (result && result->valid())
   31958             :                {
   31959       35982 :                   return result;
   31960             :                }
   31961             : 
   31962           0 :                parser_->set_error(parser_error::make_error(
   31963             :                   parser_error::e_synthesis,
   31964           0 :                   token_t(),
   31965             :                   "ERR232 - Failed to synthesize node: vararg_node",
   31966             :                   exprtk_error_location));
   31967             : 
   31968           0 :                details::free_node(*node_allocator_, result);
   31969             :             }
   31970             : 
   31971           0 :             return error_node();
   31972             :          }
   31973             : 
   31974             :          template <std::size_t N>
   31975       60380 :          inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
   31976             :          {
   31977             :             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
   31978       60380 :             expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
   31979             : 
   31980       60380 :             if (0 == result)
   31981           0 :                return error_node();
   31982             :             else
   31983             :             {
   31984             :                // Can the function call be completely optimised?
   31985       60380 :                if (details::is_constant_node(result))
   31986         120 :                   return result;
   31987       60260 :                else if (!all_nodes_valid(b))
   31988             :                {
   31989           0 :                   details::free_node(*node_allocator_,result);
   31990           0 :                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
   31991             : 
   31992           0 :                   return error_node();
   31993             :                }
   31994       60260 :                else if (N != f->param_count)
   31995             :                {
   31996           0 :                   details::free_node(*node_allocator_,result);
   31997           0 :                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
   31998             : 
   31999           0 :                   return error_node();
   32000             :                }
   32001             : 
   32002       60260 :                function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result);
   32003             : 
   32004       60260 :                if (!func_node_ptr->init_branches(b))
   32005             :                {
   32006           0 :                   details::free_node(*node_allocator_,result);
   32007           0 :                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
   32008             : 
   32009           0 :                   return error_node();
   32010             :                }
   32011             : 
   32012       60260 :                if (result && result->valid())
   32013             :                {
   32014       60260 :                   return result;
   32015             :                }
   32016             : 
   32017           0 :                parser_->set_error(parser_error::make_error(
   32018             :                   parser_error::e_synthesis,
   32019           0 :                   token_t(),
   32020             :                   "ERR233 - Failed to synthesize node: function_N_node_t",
   32021             :                   exprtk_error_location));
   32022             : 
   32023           0 :                details::free_node(*node_allocator_, result);
   32024           0 :                return error_node();
   32025             :             }
   32026             :          }
   32027             : 
   32028         231 :          inline expression_node_ptr function(ifunction_t* f)
   32029             :          {
   32030             :             typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
   32031         231 :             return node_allocator_->allocate<function_N_node_t>(f);
   32032             :          }
   32033             : 
   32034          49 :          inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
   32035             :                                                          std::vector<expression_node_ptr>& arg_list)
   32036             :          {
   32037          49 :             if (!all_nodes_valid(arg_list))
   32038             :             {
   32039           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32040             : 
   32041           0 :                return error_node();
   32042             :             }
   32043             : 
   32044             :             typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
   32045             : 
   32046          49 :             expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
   32047             : 
   32048          49 :             if (
   32049          49 :                  !arg_list.empty()        &&
   32050          49 :                  !vaf->has_side_effects() &&
   32051           0 :                  is_constant_foldable(arg_list)
   32052             :                )
   32053             :             {
   32054           0 :                const Type v = result->value();
   32055           0 :                details::free_node(*node_allocator_,result);
   32056           0 :                result = node_allocator_->allocate<literal_node_t>(v);
   32057             :             }
   32058             : 
   32059          98 :             parser_->state_.activate_side_effect("vararg_function_call()");
   32060             : 
   32061          49 :             if (result && result->valid())
   32062             :             {
   32063          49 :                return result;
   32064             :             }
   32065             : 
   32066           0 :             parser_->set_error(parser_error::make_error(
   32067             :                parser_error::e_synthesis,
   32068           0 :                token_t(),
   32069             :                "ERR234 - Failed to synthesize node: vararg_function_node<ivararg_function_t>",
   32070             :                exprtk_error_location));
   32071             : 
   32072           0 :             details::free_node(*node_allocator_, result);
   32073           0 :             return error_node();
   32074             :          }
   32075             : 
   32076        1861 :          inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
   32077             :                                                           std::vector<expression_node_ptr>& arg_list,
   32078             :                                                           const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
   32079             :          {
   32080        1861 :             if (!all_nodes_valid(arg_list))
   32081             :             {
   32082           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32083           0 :                return error_node();
   32084             :             }
   32085             : 
   32086             :             typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
   32087             :             typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
   32088             : 
   32089        1861 :             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
   32090             : 
   32091        1861 :             expression_node_ptr result = error_node();
   32092        1861 :             std::string node_name = "Unknown";
   32093             : 
   32094        1861 :             if (no_psi == param_seq_index)
   32095             :             {
   32096          57 :                result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
   32097          57 :                node_name = "generic_function_node<igeneric_function_t>";
   32098             :             }
   32099             :             else
   32100             :             {
   32101        1804 :                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
   32102        1804 :                node_name = "multimode_genfunction_node<igeneric_function_t>";
   32103             :             }
   32104             : 
   32105        1861 :             alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
   32106             : 
   32107        1861 :             assert(genfunc_node_ptr);
   32108             : 
   32109        1861 :             if (
   32110        1861 :                  !arg_list.empty()                  &&
   32111        1846 :                  !gf->has_side_effects()            &&
   32112        3707 :                  parser_->state_.type_check_enabled &&
   32113           0 :                  is_constant_foldable(arg_list)
   32114             :                )
   32115             :             {
   32116           0 :                genfunc_node_ptr->init_branches();
   32117             : 
   32118           0 :                const Type v = result->value();
   32119             : 
   32120           0 :                details::free_node(*node_allocator_,result);
   32121             : 
   32122           0 :                return node_allocator_->allocate<literal_node_t>(v);
   32123             :             }
   32124        1861 :             else if (genfunc_node_ptr->init_branches())
   32125             :             {
   32126        1861 :                if (result && result->valid())
   32127             :                {
   32128        3722 :                   parser_->state_.activate_side_effect("generic_function_call()");
   32129        1861 :                   return result;
   32130             :                }
   32131             : 
   32132           0 :                parser_->set_error(parser_error::make_error(
   32133             :                   parser_error::e_synthesis,
   32134           0 :                   token_t(),
   32135             :                   "ERR235 - Failed to synthesize node: " + node_name,
   32136             :                   exprtk_error_location));
   32137             : 
   32138           0 :                details::free_node(*node_allocator_, result);
   32139           0 :                return error_node();
   32140             :             }
   32141             :             else
   32142             :             {
   32143           0 :                details::free_node(*node_allocator_, result);
   32144           0 :                details::free_all_nodes(*node_allocator_, arg_list);
   32145             : 
   32146           0 :                return error_node();
   32147             :             }
   32148        1861 :          }
   32149             : 
   32150             :          #ifndef exprtk_disable_string_capabilities
   32151          72 :          inline expression_node_ptr string_function_call(igeneric_function_t* gf,
   32152             :                                                          std::vector<expression_node_ptr>& arg_list,
   32153             :                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
   32154             :          {
   32155          72 :             if (!all_nodes_valid(arg_list))
   32156             :             {
   32157           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32158           0 :                return error_node();
   32159             :             }
   32160             : 
   32161             :             typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
   32162             :             typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
   32163             : 
   32164          72 :             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
   32165             : 
   32166          72 :             expression_node_ptr result = error_node();
   32167          72 :             std::string node_name = "Unknown";
   32168             : 
   32169          72 :             if (no_psi == param_seq_index)
   32170             :             {
   32171           0 :                result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
   32172           0 :                node_name = "string_function_node<igeneric_function_t>";
   32173             :             }
   32174             :             else
   32175             :             {
   32176          72 :                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
   32177          72 :                node_name = "multimode_strfunction_node<igeneric_function_t>";
   32178             :             }
   32179             : 
   32180          72 :             alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
   32181             : 
   32182          72 :             assert(strfunc_node_ptr);
   32183             : 
   32184          72 :             if (
   32185          72 :                  !arg_list.empty()       &&
   32186          72 :                  !gf->has_side_effects() &&
   32187           0 :                  is_constant_foldable(arg_list)
   32188             :                )
   32189             :             {
   32190           0 :                strfunc_node_ptr->init_branches();
   32191             : 
   32192           0 :                const Type v = result->value();
   32193             : 
   32194           0 :                details::free_node(*node_allocator_,result);
   32195             : 
   32196           0 :                return node_allocator_->allocate<literal_node_t>(v);
   32197             :             }
   32198          72 :             else if (strfunc_node_ptr->init_branches())
   32199             :             {
   32200          72 :                if (result && result->valid())
   32201             :                {
   32202         144 :                   parser_->state_.activate_side_effect("string_function_call()");
   32203          72 :                   return result;
   32204             :                }
   32205             : 
   32206           0 :                parser_->set_error(parser_error::make_error(
   32207             :                   parser_error::e_synthesis,
   32208           0 :                   token_t(),
   32209             :                   "ERR236 - Failed to synthesize node: " + node_name,
   32210             :                   exprtk_error_location));
   32211             : 
   32212           0 :                details::free_node(*node_allocator_, result);
   32213           0 :                return error_node();
   32214             :             }
   32215             :             else
   32216             :             {
   32217           0 :                details::free_node     (*node_allocator_,result  );
   32218           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32219             : 
   32220           0 :                return error_node();
   32221             :             }
   32222          72 :          }
   32223             :          #endif
   32224             : 
   32225             :          #ifndef exprtk_disable_return_statement
   32226         116 :          inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
   32227             :          {
   32228         116 :             if (!all_nodes_valid(arg_list))
   32229             :             {
   32230           0 :                details::free_all_nodes(*node_allocator_,arg_list);
   32231           0 :                return error_node();
   32232             :             }
   32233             : 
   32234             :             typedef details::return_node<Type> alloc_type;
   32235             : 
   32236         232 :             expression_node_ptr result = node_allocator_->
   32237         116 :                                             allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
   32238             : 
   32239         116 :             alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
   32240             : 
   32241         116 :             assert(return_node_ptr);
   32242             : 
   32243         116 :             if (return_node_ptr->init_branches())
   32244             :             {
   32245         116 :                if (result && result->valid())
   32246             :                {
   32247         232 :                   parser_->state_.activate_side_effect("return_call()");
   32248         116 :                   return result;
   32249             :                }
   32250             : 
   32251           0 :                parser_->set_error(parser_error::make_error(
   32252             :                   parser_error::e_synthesis,
   32253           0 :                   token_t(),
   32254             :                   "ERR237 - Failed to synthesize node: return_node",
   32255             :                   exprtk_error_location));
   32256             : 
   32257           0 :                details::free_node(*node_allocator_, result);
   32258           0 :                return error_node();
   32259             :             }
   32260             :             else
   32261             :             {
   32262           0 :                details::free_node     (*node_allocator_, result  );
   32263           0 :                details::free_all_nodes(*node_allocator_, arg_list);
   32264             : 
   32265           0 :                return error_node();
   32266             :             }
   32267             :          }
   32268             : 
   32269         111 :          inline expression_node_ptr return_envelope(expression_node_ptr body,
   32270             :                                                     results_context_t* rc,
   32271             :                                                     bool*& return_invoked)
   32272             :          {
   32273             :             typedef details::return_envelope_node<Type> alloc_type;
   32274             : 
   32275         111 :             expression_node_ptr result = node_allocator_->
   32276         111 :                                             allocate_cr<alloc_type>(body,(*rc));
   32277             : 
   32278         111 :             return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
   32279             : 
   32280         111 :             return result;
   32281             :          }
   32282             :          #else
   32283             :          inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
   32284             :          {
   32285             :             return error_node();
   32286             :          }
   32287             : 
   32288             :          inline expression_node_ptr return_envelope(expression_node_ptr,
   32289             :                                                     results_context_t*,
   32290             :                                                     bool*&)
   32291             :          {
   32292             :             return error_node();
   32293             :          }
   32294             :          #endif
   32295             : 
   32296       17612 :          inline expression_node_ptr vector_element(const std::string&  symbol,
   32297             :                                                    vector_holder_ptr   vector_base,
   32298             :                                                    expression_node_ptr vec_node,
   32299             :                                                    expression_node_ptr index)
   32300             :          {
   32301       17612 :             expression_node_ptr result = error_node();
   32302       17612 :             std::string node_name = "Unknown";
   32303             : 
   32304       17612 :             if (details::is_constant_node(index))
   32305             :             {
   32306       12983 :                const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
   32307             : 
   32308       12983 :                details::free_node(*node_allocator_,index);
   32309             : 
   32310       12983 :                if (vec_index >= vector_base->size())
   32311             :                {
   32312           0 :                   parser_->set_error(parser_error::make_error(
   32313             :                      parser_error::e_parser,
   32314           0 :                      token_t(),
   32315             :                      "ERR238 - Index of " + details::to_str(vec_index) + " out of range for "
   32316             :                      "vector '" + symbol + "' of size " + details::to_str(vector_base->size()),
   32317             :                      exprtk_error_location));
   32318             : 
   32319           0 :                   details::free_node(*node_allocator_,vec_node);
   32320             : 
   32321        1989 :                   return error_node();
   32322             :                }
   32323             : 
   32324       12983 :                if (vector_base->rebaseable())
   32325             :                {
   32326        1894 :                   vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
   32327             : 
   32328        1894 :                   result = (rtc) ?
   32329           0 :                      node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
   32330        1894 :                      node_allocator_->allocate<rebasevector_celem_node_t    >(vec_node, vec_index, vector_base     ) ;
   32331             : 
   32332        1894 :                   node_name = (rtc) ?
   32333             :                      "rebasevector_elem_rtc_node_t" :
   32334             :                      "rebasevector_elem_node_t"     ;
   32335             : 
   32336        1894 :                   if (result && result->valid())
   32337             :                   {
   32338        1894 :                      return result;
   32339             :                   }
   32340             : 
   32341           0 :                   parser_->set_error(parser_error::make_error(
   32342             :                      parser_error::e_synthesis,
   32343           0 :                      token_t(),
   32344             :                      "ERR239 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
   32345             :                      exprtk_error_location));
   32346             : 
   32347           0 :                   details::free_node(*node_allocator_, result);
   32348           0 :                   return error_node();
   32349             :                }
   32350       11089 :                else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node))
   32351             :                {
   32352          95 :                   vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
   32353             : 
   32354          95 :                   result = (rtc) ?
   32355           0 :                      node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
   32356          95 :                      node_allocator_->allocate<vector_celem_node_t    >(vec_node, vec_index, vector_base     ) ;
   32357             : 
   32358          95 :                   node_name = (rtc) ?
   32359             :                      "vector_elem_rtc_node_t" :
   32360             :                      "vector_elem_node_t"     ;
   32361             : 
   32362          95 :                   if (result && result->valid())
   32363             :                   {
   32364          95 :                      return result;
   32365             :                   }
   32366             : 
   32367           0 :                   parser_->set_error(parser_error::make_error(
   32368             :                      parser_error::e_synthesis,
   32369           0 :                      token_t(),
   32370             :                      "ERR240 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
   32371             :                      exprtk_error_location));
   32372             : 
   32373           0 :                   details::free_node(*node_allocator_, result);
   32374           0 :                   return error_node();
   32375             :                }
   32376             : 
   32377       10994 :                const scope_element& se = parser_->sem_.get_element(symbol,vec_index);
   32378             : 
   32379       10994 :                if (se.index == vec_index)
   32380             :                {
   32381        1580 :                   result = se.var_node;
   32382        1580 :                   details::free_node(*node_allocator_,vec_node);
   32383             :                }
   32384             :                else
   32385             :                {
   32386        9414 :                   scope_element nse;
   32387        9414 :                   nse.name      = symbol;
   32388        9414 :                   nse.active    = true;
   32389        9414 :                   nse.ref_count = 1;
   32390        9414 :                   nse.type      = scope_element::e_vecelem;
   32391        9414 :                   nse.index     = vec_index;
   32392        9414 :                   nse.depth     = parser_->state_.scope_depth;
   32393        9414 :                   nse.data      = 0;
   32394        9414 :                   nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index]));
   32395             : 
   32396        9414 :                   if (!parser_->sem_.add_element(nse))
   32397             :                   {
   32398           0 :                      parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
   32399             : 
   32400           0 :                      parser_->sem_.free_element(nse);
   32401             : 
   32402           0 :                      result = error_node();
   32403             :                   }
   32404             : 
   32405        9414 :                   details::free_node(*node_allocator_,vec_node);
   32406             : 
   32407             :                   exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str()));
   32408             : 
   32409       18828 :                   parser_->state_.activate_side_effect("vector_element()");
   32410             : 
   32411        9414 :                   result = nse.var_node;
   32412        9414 :                   node_name = "variable_node_t";
   32413        9414 :                }
   32414             :             }
   32415             :             else
   32416             :             {
   32417        4629 :                vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
   32418             : 
   32419        4629 :                if (vector_base->rebaseable())
   32420             :                {
   32421        1016 :                   result = (rtc) ?
   32422           2 :                      node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
   32423        1014 :                      node_allocator_->allocate<rebasevector_elem_node_t    >(vec_node, index, vector_base     ) ;
   32424             : 
   32425        1016 :                   node_name = (rtc) ?
   32426             :                      "rebasevector_elem_rtc_node_t" :
   32427             :                      "rebasevector_elem_node_t"     ;
   32428             :                }
   32429             :                else
   32430             :                {
   32431        3613 :                   result = rtc ?
   32432          92 :                      node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
   32433        3521 :                      node_allocator_->allocate<vector_elem_node_t    >(vec_node, index, vector_base     ) ;
   32434             : 
   32435        3613 :                   node_name = (rtc) ?
   32436             :                      "vector_elem_rtc_node_t" :
   32437             :                      "vector_elem_node_t"     ;
   32438             :                }
   32439             :             }
   32440             : 
   32441       15623 :             if (result && result->valid())
   32442             :             {
   32443       15623 :                return result;
   32444             :             }
   32445             : 
   32446           0 :             parser_->set_error(parser_error::make_error(
   32447             :                parser_error::e_synthesis,
   32448           0 :                token_t(),
   32449             :                "ERR241 - Failed to synthesize node: " + node_name,
   32450             :                exprtk_error_location));
   32451             : 
   32452           0 :             details::free_node(*node_allocator_, result);
   32453           0 :             return error_node();
   32454       17612 :          }
   32455             : 
   32456             :       private:
   32457             : 
   32458             :          template <std::size_t N, typename NodePtr>
   32459      656470 :          inline bool is_constant_foldable(NodePtr (&b)[N]) const
   32460             :          {
   32461     1372082 :             for (std::size_t i = 0; i < N; ++i)
   32462             :             {
   32463     1076558 :                if (0 == b[i])
   32464           0 :                   return false;
   32465     1076558 :                else if (!details::is_constant_node(b[i]))
   32466      360946 :                   return false;
   32467             :             }
   32468             : 
   32469      295524 :             return true;
   32470             :          }
   32471             : 
   32472             :          template <typename NodePtr,
   32473             :                    typename Allocator,
   32474             :                    template <typename, typename> class Sequence>
   32475       42902 :          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
   32476             :          {
   32477       48078 :             for (std::size_t i = 0; i < b.size(); ++i)
   32478             :             {
   32479       46501 :                if (0 == b[i])
   32480           0 :                   return false;
   32481       46501 :                else if (!details::is_constant_node(b[i]))
   32482       41325 :                   return false;
   32483             :             }
   32484             : 
   32485        1577 :             return true;
   32486             :          }
   32487             : 
   32488       57239 :          void lodge_assignment(symbol_type cst, expression_node_ptr node)
   32489             :          {
   32490      114478 :             parser_->state_.activate_side_effect("lodge_assignment()");
   32491             : 
   32492       57239 :             if (!parser_->dec_.collect_assignments())
   32493       57235 :                return;
   32494             : 
   32495           4 :             std::string symbol_name;
   32496             : 
   32497           4 :             switch (cst)
   32498             :             {
   32499           3 :                case e_st_variable : symbol_name = parser_->symtab_store_
   32500             :                                                      .get_variable_name(node);
   32501           3 :                                     break;
   32502             : 
   32503             :                #ifndef exprtk_disable_string_capabilities
   32504           1 :                case e_st_string   : symbol_name = parser_->symtab_store_
   32505             :                                                      .get_stringvar_name(node);
   32506           1 :                                     break;
   32507             :                #endif
   32508             : 
   32509           0 :                case e_st_vector   : {
   32510             :                                        typedef details::vector_holder<T> vector_holder_t;
   32511             : 
   32512           0 :                                        vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
   32513             : 
   32514           0 :                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
   32515             :                                     }
   32516           0 :                                     break;
   32517             : 
   32518           0 :                case e_st_vecelem  : {
   32519             :                                        typedef details::vector_holder<T> vector_holder_t;
   32520             : 
   32521           0 :                                        vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
   32522             : 
   32523           0 :                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
   32524             : 
   32525           0 :                                        cst = e_st_vector;
   32526             :                                     }
   32527           0 :                                     break;
   32528             : 
   32529           0 :                default            : return;
   32530             :             }
   32531             : 
   32532           4 :             if (!symbol_name.empty())
   32533             :             {
   32534           4 :                parser_->dec_.add_assignment(symbol_name,cst);
   32535             :             }
   32536           4 :          }
   32537             : 
   32538       57267 :          const void* base_ptr(expression_node_ptr node)
   32539             :          {
   32540       57267 :             if (node)
   32541             :             {
   32542       57267 :                switch(node->type())
   32543             :                {
   32544       32394 :                   case details::expression_node<T>::e_variable:
   32545       32394 :                      return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref());
   32546             : 
   32547         585 :                   case details::expression_node<T>::e_vecelem:
   32548         585 :                      return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref());
   32549             : 
   32550           0 :                   case details::expression_node<T>::e_veccelem:
   32551           0 :                      return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref());
   32552             : 
   32553          32 :                   case details::expression_node<T>::e_vecelemrtc:
   32554          32 :                      return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref());
   32555             : 
   32556           0 :                   case details::expression_node<T>::e_veccelemrtc:
   32557           0 :                      return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref());
   32558             : 
   32559         300 :                   case details::expression_node<T>::e_rbvecelem:
   32560         300 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref());
   32561             : 
   32562           0 :                   case details::expression_node<T>::e_rbvecelemrtc:
   32563           0 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref());
   32564             : 
   32565         300 :                   case details::expression_node<T>::e_rbveccelem:
   32566         300 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref());
   32567             : 
   32568           0 :                   case details::expression_node<T>::e_rbveccelemrtc:
   32569           0 :                      return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref());
   32570             : 
   32571        4457 :                   case details::expression_node<T>::e_vector:
   32572        4457 :                      return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data());
   32573             : 
   32574             :                   #ifndef exprtk_disable_string_capabilities
   32575       14337 :                   case details::expression_node<T>::e_stringvar:
   32576       14337 :                      return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base()));
   32577             : 
   32578        4862 :                   case details::expression_node<T>::e_stringvarrng:
   32579        4862 :                      return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base()));
   32580             :                   #endif
   32581           0 :                   default : return reinterpret_cast<const void*>(0);
   32582             :                }
   32583             :             }
   32584             : 
   32585           0 :             return reinterpret_cast<const void*>(0);
   32586             :          }
   32587             : 
   32588       57267 :          bool assign_immutable_symbol(expression_node_ptr node)
   32589             :          {
   32590       57267 :             interval_t interval;
   32591       57267 :             const void* baseptr_addr = base_ptr(node);
   32592             : 
   32593             :             exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr));
   32594             : 
   32595       57267 :             if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval))
   32596             :             {
   32597          28 :                typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval);
   32598             : 
   32599          28 :                if (parser_->immutable_symtok_map_.end() != itr)
   32600             :                {
   32601          28 :                   token_t& token = itr->second;
   32602          56 :                   parser_->set_error(parser_error::make_error(
   32603             :                      parser_error::e_parser,
   32604             :                      token,
   32605          28 :                      "ERR242 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.",
   32606             :                      exprtk_error_location));
   32607             :                }
   32608             :                else
   32609           0 :                   parser_->set_synthesis_error("Unable to assign symbol is immutable.");
   32610             : 
   32611          28 :                return true;
   32612             :             }
   32613             : 
   32614       57239 :             return false;
   32615             :          }
   32616             : 
   32617       45671 :          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   32618             :          {
   32619       45671 :             if (assign_immutable_symbol(branch[0]))
   32620             :             {
   32621          17 :                return error_node();
   32622             :             }
   32623       45654 :             else if (details::is_variable_node(branch[0]))
   32624             :             {
   32625       27695 :                lodge_assignment(e_st_variable,branch[0]);
   32626       27695 :                return synthesize_expression<assignment_node_t,2>(operation,branch);
   32627             :             }
   32628       17959 :             else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0]))
   32629             :             {
   32630          83 :                lodge_assignment(e_st_vecelem,branch[0]);
   32631          83 :                return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
   32632             :             }
   32633       17876 :             else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0]))
   32634             :             {
   32635          20 :                lodge_assignment(e_st_vecelem,branch[0]);
   32636          20 :                return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch);
   32637             :             }
   32638       17856 :             else if (details::is_rebasevector_elem_node(branch[0]))
   32639             :             {
   32640           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   32641           0 :                return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
   32642             :             }
   32643       17856 :             else if (details::is_rebasevector_elem_rtc_node(branch[0]))
   32644             :             {
   32645           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   32646           0 :                return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch);
   32647             :             }
   32648       17856 :             else if (details::is_rebasevector_celem_node(branch[0]))
   32649             :             {
   32650           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   32651           0 :                return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
   32652             :             }
   32653             :             #ifndef exprtk_disable_string_capabilities
   32654       17856 :             else if (details::is_string_node(branch[0]))
   32655             :             {
   32656       11736 :                lodge_assignment(e_st_string,branch[0]);
   32657       11736 :                return synthesize_expression<assignment_string_node_t,2>(operation, branch);
   32658             :             }
   32659        6120 :             else if (details::is_string_range_node(branch[0]))
   32660             :             {
   32661        4850 :                lodge_assignment(e_st_string,branch[0]);
   32662        4850 :                return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
   32663             :             }
   32664             :             #endif
   32665        1270 :             else if (details::is_vector_node(branch[0]))
   32666             :             {
   32667        1270 :                lodge_assignment(e_st_vector,branch[0]);
   32668             : 
   32669        1270 :                if (details::is_ivector_node(branch[1]))
   32670        1156 :                   return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
   32671             :                else
   32672         114 :                   return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
   32673             :             }
   32674             :             else
   32675             :             {
   32676           0 :                parser_->set_error(parser_error::make_error(
   32677             :                   parser_error::e_syntax,
   32678           0 :                   parser_->current_state().token,
   32679             :                   "ERR243 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
   32680             :                   exprtk_error_location));
   32681             : 
   32682           0 :                return error_node();
   32683             :             }
   32684             :          }
   32685             : 
   32686       11596 :          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
   32687             :                                                                                expression_node_ptr (&branch)[2])
   32688             :          {
   32689       11596 :             if (assign_immutable_symbol(branch[0]))
   32690             :             {
   32691          11 :                return error_node();
   32692             :             }
   32693             : 
   32694       11585 :             expression_node_ptr result = error_node();
   32695       11585 :             std::string node_name = "Unknown";
   32696             : 
   32697       11585 :             if (details::is_variable_node(branch[0]))
   32698             :             {
   32699        4690 :                lodge_assignment(e_st_variable,branch[0]);
   32700             : 
   32701        4690 :                switch (operation)
   32702             :                {
   32703             :                   #define case_stmt(op0, op1)                                                                 \
   32704             :                   case op0 : result = node_allocator_->                                                       \
   32705             :                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
   32706             :                                    (operation, branch[0], branch[1]);                                         \
   32707             :                              node_name = "assignment_op_node";                                                \
   32708             :                              break;                                                                           \
   32709             : 
   32710        4205 :                   case_stmt(details::e_addass , details::add_op)
   32711         245 :                   case_stmt(details::e_subass , details::sub_op)
   32712         120 :                   case_stmt(details::e_mulass , details::mul_op)
   32713         120 :                   case_stmt(details::e_divass , details::div_op)
   32714           0 :                   case_stmt(details::e_modass , details::mod_op)
   32715             :                   #undef case_stmt
   32716           0 :                   default : return error_node();
   32717             :                }
   32718             :             }
   32719        6895 :             else if (details::is_vector_elem_node(branch[0]))
   32720             :             {
   32721         500 :                lodge_assignment(e_st_vecelem,branch[0]);
   32722             : 
   32723         500 :                switch (operation)
   32724             :                {
   32725             :                   #define case_stmt(op0, op1)                                                                           \
   32726             :                   case op0 : result = node_allocator_->                                                                 \
   32727             :                                  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
   32728             :                                     (operation, branch[0], branch[1]);                                                  \
   32729             :                              node_name = "assignment_vec_elem_op_node";                                                 \
   32730             :                              break;                                                                                     \
   32731             : 
   32732         230 :                   case_stmt(details::e_addass , details::add_op)
   32733         170 :                   case_stmt(details::e_subass , details::sub_op)
   32734          50 :                   case_stmt(details::e_mulass , details::mul_op)
   32735          50 :                   case_stmt(details::e_divass , details::div_op)
   32736           0 :                   case_stmt(details::e_modass , details::mod_op)
   32737             :                   #undef case_stmt
   32738           0 :                   default : return error_node();
   32739             :                }
   32740             :             }
   32741        6395 :             else if (details::is_vector_elem_rtc_node(branch[0]))
   32742             :             {
   32743          12 :                lodge_assignment(e_st_vecelem,branch[0]);
   32744             : 
   32745          12 :                switch (operation)
   32746             :                {
   32747             :                   #define case_stmt(op0, op1)                                                                               \
   32748             :                   case op0 : result = node_allocator_->                                                                     \
   32749             :                                  template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \
   32750             :                                     (operation, branch[0], branch[1]);                                                      \
   32751             :                              node_name = "assignment_vec_elem_op_rtc_node";                                                 \
   32752             :                              break;                                                                                         \
   32753             : 
   32754           8 :                   case_stmt(details::e_addass , details::add_op)
   32755           4 :                   case_stmt(details::e_subass , details::sub_op)
   32756           0 :                   case_stmt(details::e_mulass , details::mul_op)
   32757           0 :                   case_stmt(details::e_divass , details::div_op)
   32758           0 :                   case_stmt(details::e_modass , details::mod_op)
   32759             :                   #undef case_stmt
   32760           0 :                   default : return error_node();
   32761             :                }
   32762             :             }
   32763        6383 :             else if (details::is_vector_celem_rtc_node(branch[0]))
   32764             :             {
   32765           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   32766             : 
   32767           0 :                switch (operation)
   32768             :                {
   32769             :                   #define case_stmt(op0, op1)                                                                                \
   32770             :                   case op0 : result = node_allocator_->                                                                      \
   32771             :                                  template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \
   32772             :                                     (operation, branch[0], branch[1]);                                                       \
   32773             :                              node_name = "assignment_vec_celem_op_rtc_node";                                                 \
   32774             :                              break;                                                                                          \
   32775             : 
   32776           0 :                   case_stmt(details::e_addass , details::add_op)
   32777           0 :                   case_stmt(details::e_subass , details::sub_op)
   32778           0 :                   case_stmt(details::e_mulass , details::mul_op)
   32779           0 :                   case_stmt(details::e_divass , details::div_op)
   32780           0 :                   case_stmt(details::e_modass , details::mod_op)
   32781             :                   #undef case_stmt
   32782           0 :                   default : return error_node();
   32783             :                }
   32784             :             }
   32785        6383 :             else if (details::is_rebasevector_elem_node(branch[0]))
   32786             :             {
   32787         300 :                lodge_assignment(e_st_vecelem,branch[0]);
   32788             : 
   32789         300 :                switch (operation)
   32790             :                {
   32791             :                   #define case_stmt(op0, op1)                                                                                 \
   32792             :                   case op0 : result = node_allocator_->                                                                       \
   32793             :                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
   32794             :                                     (operation, branch[0], branch[1]);                                                        \
   32795             :                              node_name = "assignment_rebasevec_elem_op_node";                                                 \
   32796             :                              break;                                                                                           \
   32797             : 
   32798         180 :                   case_stmt(details::e_addass , details::add_op)
   32799         120 :                   case_stmt(details::e_subass , details::sub_op)
   32800           0 :                   case_stmt(details::e_mulass , details::mul_op)
   32801           0 :                   case_stmt(details::e_divass , details::div_op)
   32802           0 :                   case_stmt(details::e_modass , details::mod_op)
   32803             :                   #undef case_stmt
   32804           0 :                   default : return error_node();
   32805             :                }
   32806             :             }
   32807        6083 :             else if (details::is_rebasevector_celem_node(branch[0]))
   32808             :             {
   32809         300 :                lodge_assignment(e_st_vecelem,branch[0]);
   32810             : 
   32811         300 :                switch (operation)
   32812             :                {
   32813             :                   #define case_stmt(op0, op1)                                                                                  \
   32814             :                   case op0 : result = node_allocator_->                                                                        \
   32815             :                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
   32816             :                                     (operation, branch[0], branch[1]);                                                         \
   32817             :                              node_name = "assignment_rebasevec_celem_op_node";                                                 \
   32818             :                              break;                                                                                            \
   32819             : 
   32820         180 :                   case_stmt(details::e_addass , details::add_op)
   32821         120 :                   case_stmt(details::e_subass , details::sub_op)
   32822           0 :                   case_stmt(details::e_mulass , details::mul_op)
   32823           0 :                   case_stmt(details::e_divass , details::div_op)
   32824           0 :                   case_stmt(details::e_modass , details::mod_op)
   32825             :                   #undef case_stmt
   32826           0 :                   default : return error_node();
   32827             :                }
   32828             :             }
   32829        5783 :             else if (details::is_rebasevector_elem_rtc_node(branch[0]))
   32830             :             {
   32831           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   32832             : 
   32833           0 :                switch (operation)
   32834             :                {
   32835             :                   #define case_stmt(op0, op1)                                                                                     \
   32836             :                   case op0 : result = node_allocator_->                                                                           \
   32837             :                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \
   32838             :                                     (operation, branch[0], branch[1]);                                                            \
   32839             :                              node_name = "assignment_rebasevec_elem_op_rtc_node";                                                 \
   32840             :                              break;                                                                                               \
   32841             : 
   32842           0 :                   case_stmt(details::e_addass , details::add_op)
   32843           0 :                   case_stmt(details::e_subass , details::sub_op)
   32844           0 :                   case_stmt(details::e_mulass , details::mul_op)
   32845           0 :                   case_stmt(details::e_divass , details::div_op)
   32846           0 :                   case_stmt(details::e_modass , details::mod_op)
   32847             :                   #undef case_stmt
   32848           0 :                   default : return error_node();
   32849             :                }
   32850             :             }
   32851        5783 :             else if (details::is_rebasevector_celem_rtc_node(branch[0]))
   32852             :             {
   32853           0 :                lodge_assignment(e_st_vecelem,branch[0]);
   32854             : 
   32855           0 :                switch (operation)
   32856             :                {
   32857             :                   #define case_stmt(op0, op1)                                                                                      \
   32858             :                   case op0 : result = node_allocator_->                                                                            \
   32859             :                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \
   32860             :                                     (operation, branch[0], branch[1]);                                                             \
   32861             :                              node_name = "assignment_rebasevec_celem_op_rtc_node";                                                 \
   32862             :                              break;                                                                                                \
   32863             : 
   32864           0 :                   case_stmt(details::e_addass , details::add_op)
   32865           0 :                   case_stmt(details::e_subass , details::sub_op)
   32866           0 :                   case_stmt(details::e_mulass , details::mul_op)
   32867           0 :                   case_stmt(details::e_divass , details::div_op)
   32868           0 :                   case_stmt(details::e_modass , details::mod_op)
   32869             :                   #undef case_stmt
   32870           0 :                   default : return error_node();
   32871             :                }
   32872             :             }
   32873        5783 :             else if (details::is_vector_node(branch[0]))
   32874             :             {
   32875        3183 :                lodge_assignment(e_st_vector,branch[0]);
   32876             : 
   32877        3183 :                if (details::is_ivector_node(branch[1]))
   32878             :                {
   32879         721 :                   switch (operation)
   32880             :                   {
   32881             :                      #define case_stmt(op0, op1)                                                                        \
   32882             :                      case op0 : result = node_allocator_->                                                              \
   32883             :                                    template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
   32884             :                                       (operation, branch[0], branch[1]);                                                \
   32885             :                                 node_name = "assignment_rebasevec_celem_op_node";                                       \
   32886             :                                 break;                                                                                  \
   32887             : 
   32888         481 :                      case_stmt(details::e_addass , details::add_op)
   32889          80 :                      case_stmt(details::e_subass , details::sub_op)
   32890          80 :                      case_stmt(details::e_mulass , details::mul_op)
   32891          80 :                      case_stmt(details::e_divass , details::div_op)
   32892           0 :                      case_stmt(details::e_modass , details::mod_op)
   32893             :                      #undef case_stmt
   32894           0 :                      default : return error_node();
   32895             :                   }
   32896             :                }
   32897             :                else
   32898             :                {
   32899        2462 :                   switch (operation)
   32900             :                   {
   32901             :                      #define case_stmt(op0, op1)                                                                     \
   32902             :                      case op0 : result = node_allocator_->                                                           \
   32903             :                                    template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
   32904             :                                       (operation, branch[0], branch[1]);                                             \
   32905             :                                 node_name = "assignment_vec_op_node";                                                \
   32906             :                                 break;                                                                               \
   32907             : 
   32908        2007 :                      case_stmt(details::e_addass , details::add_op)
   32909         295 :                      case_stmt(details::e_subass , details::sub_op)
   32910          80 :                      case_stmt(details::e_mulass , details::mul_op)
   32911          80 :                      case_stmt(details::e_divass , details::div_op)
   32912           0 :                      case_stmt(details::e_modass , details::mod_op)
   32913             :                      #undef case_stmt
   32914           0 :                      default : return error_node();
   32915             :                   }
   32916             :                }
   32917             :             }
   32918             :             #ifndef exprtk_disable_string_capabilities
   32919        2600 :             else if (
   32920        5200 :                       (details::e_addass == operation) &&
   32921        2600 :                       details::is_string_node(branch[0])
   32922             :                     )
   32923             :             {
   32924             :                typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
   32925             : 
   32926        2600 :                lodge_assignment(e_st_string,branch[0]);
   32927             : 
   32928        2600 :                result = synthesize_expression<addass_t,2>(operation,branch);
   32929        2600 :                node_name = "assignment_string_node<T,details::asn_addassignment>";
   32930             :             }
   32931             :             #endif
   32932             :             else
   32933             :             {
   32934           0 :                parser_->set_error(parser_error::make_error(
   32935             :                   parser_error::e_syntax,
   32936           0 :                   parser_->current_state().token,
   32937             :                   "ERR244 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
   32938             :                   exprtk_error_location));
   32939             : 
   32940           0 :                return error_node();
   32941             :             }
   32942             : 
   32943       11585 :             if (result && result->valid())
   32944             :             {
   32945       11585 :                return result;
   32946             :             }
   32947             : 
   32948           0 :             parser_->set_error(parser_error::make_error(
   32949             :                parser_error::e_synthesis,
   32950           0 :                token_t(),
   32951             :                "ERR245 - Failed to synthesize node: " + node_name,
   32952             :                exprtk_error_location));
   32953             : 
   32954           0 :             details::free_node(*node_allocator_, result);
   32955           0 :             return error_node();
   32956       11585 :          }
   32957             : 
   32958        5322 :          inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
   32959             :                                                                                    expression_node_ptr (&branch)[2])
   32960             :          {
   32961        5322 :             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
   32962        5322 :             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
   32963             : 
   32964             :             #define batch_eqineq_logic_case                 \
   32965             :             case_stmt(details::e_lt    , details::lt_op   ) \
   32966             :             case_stmt(details::e_lte   , details::lte_op  ) \
   32967             :             case_stmt(details::e_gt    , details::gt_op   ) \
   32968             :             case_stmt(details::e_gte   , details::gte_op  ) \
   32969             :             case_stmt(details::e_eq    , details::eq_op   ) \
   32970             :             case_stmt(details::e_ne    , details::ne_op   ) \
   32971             :             case_stmt(details::e_equal , details::equal_op) \
   32972             :             case_stmt(details::e_and   , details::and_op  ) \
   32973             :             case_stmt(details::e_nand  , details::nand_op ) \
   32974             :             case_stmt(details::e_or    , details::or_op   ) \
   32975             :             case_stmt(details::e_nor   , details::nor_op  ) \
   32976             :             case_stmt(details::e_xor   , details::xor_op  ) \
   32977             :             case_stmt(details::e_xnor  , details::xnor_op ) \
   32978             : 
   32979        5322 :             expression_node_ptr result = error_node();
   32980        5322 :             std::string node_name = "Unknown";
   32981             : 
   32982        5322 :             if (is_b0_ivec && is_b1_ivec)
   32983             :             {
   32984        4442 :                switch (operation)
   32985             :                {
   32986             :                   #define case_stmt(op0, op1)                                                                    \
   32987             :                   case op0 : result = node_allocator_->                                                          \
   32988             :                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
   32989             :                                    (operation, branch[0], branch[1]);                                            \
   32990             :                              node_name = "vec_binop_vecvec_node";                                                \
   32991             :                              break;                                                                              \
   32992             : 
   32993        4442 :                   batch_eqineq_logic_case
   32994             :                   #undef case_stmt
   32995           0 :                   default : return error_node();
   32996             :                }
   32997             :             }
   32998         880 :             else if (is_b0_ivec && !is_b1_ivec)
   32999             :             {
   33000         400 :                switch (operation)
   33001             :                {
   33002             :                   #define case_stmt(op0, op1)                                                                    \
   33003             :                   case op0 : result = node_allocator_->                                                          \
   33004             :                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
   33005             :                                    (operation, branch[0], branch[1]);                                            \
   33006             :                              node_name = "vec_binop_vecval_node";                                                \
   33007             :                              break;                                                                              \
   33008             : 
   33009         400 :                   batch_eqineq_logic_case
   33010             :                   #undef case_stmt
   33011           0 :                   default : return error_node();
   33012             :                }
   33013             :             }
   33014         480 :             else if (!is_b0_ivec && is_b1_ivec)
   33015             :             {
   33016         480 :                switch (operation)
   33017             :                {
   33018             :                   #define case_stmt(op0, op1)                                                                    \
   33019             :                   case op0 : result = node_allocator_->                                                          \
   33020             :                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
   33021             :                                    (operation, branch[0], branch[1]);                                            \
   33022             :                              node_name = "vec_binop_valvec_node";                                                \
   33023             :                              break;                                                                              \
   33024             : 
   33025         480 :                   batch_eqineq_logic_case
   33026             :                   #undef case_stmt
   33027           0 :                   default : return error_node();
   33028             :                }
   33029             :             }
   33030             :             else
   33031           0 :                return error_node();
   33032             : 
   33033        5322 :             if (result && result->valid())
   33034             :             {
   33035        5322 :                return result;
   33036             :             }
   33037             : 
   33038           0 :             parser_->set_error(parser_error::make_error(
   33039             :                parser_error::e_synthesis,
   33040           0 :                token_t(),
   33041             :                "ERR246 - Failed to synthesize node: " + node_name,
   33042             :                exprtk_error_location));
   33043             : 
   33044           0 :             details::free_node(*node_allocator_, result);
   33045           0 :             return error_node();
   33046             : 
   33047             :             #undef batch_eqineq_logic_case
   33048        5322 :          }
   33049             : 
   33050        8409 :          inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
   33051             :                                                                                   expression_node_ptr (&branch)[2])
   33052             :          {
   33053        8409 :             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
   33054        8409 :             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
   33055             : 
   33056             :             #define vector_ops                          \
   33057             :             case_stmt(details::e_add , details::add_op) \
   33058             :             case_stmt(details::e_sub , details::sub_op) \
   33059             :             case_stmt(details::e_mul , details::mul_op) \
   33060             :             case_stmt(details::e_div , details::div_op) \
   33061             :             case_stmt(details::e_mod , details::mod_op) \
   33062             : 
   33063        8409 :             expression_node_ptr result = error_node();
   33064        8409 :             std::string node_name = "Unknown";
   33065             : 
   33066        8409 :             if (is_b0_ivec && is_b1_ivec)
   33067             :             {
   33068        3998 :                switch (operation)
   33069             :                {
   33070             :                   #define case_stmt(op0, op1)                                                                    \
   33071             :                   case op0 : result = node_allocator_->                                                          \
   33072             :                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
   33073             :                                    (operation, branch[0], branch[1]);                                            \
   33074             :                              node_name = "vec_binop_vecvec_node";                                                \
   33075             :                              break;                                                                              \
   33076             : 
   33077        3998 :                   vector_ops
   33078           0 :                   case_stmt(details::e_pow,details:: pow_op)
   33079             :                   #undef case_stmt
   33080           0 :                   default : return error_node();
   33081             :                }
   33082             :             }
   33083        4411 :             else if (is_b0_ivec && !is_b1_ivec)
   33084             :             {
   33085        2204 :                switch (operation)
   33086             :                {
   33087             :                   #define case_stmt(op0, op1)                                                                    \
   33088             :                   case op0 : result = node_allocator_->                                                          \
   33089             :                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
   33090             :                                    (operation, branch[0], branch[1]);                                            \
   33091             :                              node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)";                                \
   33092             :                              break;                                                                              \
   33093             : 
   33094        2164 :                   vector_ops
   33095          40 :                   case_stmt(details::e_pow,details:: pow_op)
   33096             :                   #undef case_stmt
   33097           0 :                   default : return error_node();
   33098             :                }
   33099             :             }
   33100        2207 :             else if (!is_b0_ivec && is_b1_ivec)
   33101             :             {
   33102        2207 :                switch (operation)
   33103             :                {
   33104             :                   #define case_stmt(op0, op1)                                                                    \
   33105             :                   case op0 : result = node_allocator_->                                                          \
   33106             :                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
   33107             :                                    (operation, branch[0], branch[1]);                                            \
   33108             :                              node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)";                                \
   33109             :                              break;                                                                              \
   33110             : 
   33111        2207 :                   vector_ops
   33112             :                   #undef case_stmt
   33113           0 :                   default : return error_node();
   33114             :                }
   33115             :             }
   33116             :             else
   33117           0 :                return error_node();
   33118             : 
   33119        8409 :             if (result && result->valid())
   33120             :             {
   33121        8409 :                return result;
   33122             :             }
   33123             : 
   33124           0 :             parser_->set_error(parser_error::make_error(
   33125             :                parser_error::e_synthesis,
   33126           0 :                token_t(),
   33127             :                "ERR247 - Failed to synthesize node: " + node_name,
   33128             :                exprtk_error_location));
   33129             : 
   33130           0 :             details::free_node(*node_allocator_, result);
   33131           0 :             return error_node();
   33132             : 
   33133             :             #undef vector_ops
   33134        8409 :          }
   33135             : 
   33136        2728 :          inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
   33137             :          {
   33138        2728 :             const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
   33139        2728 :             const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
   33140             : 
   33141        2728 :             const bool v0_is_ivec = details::is_ivector_node  (branch[0]);
   33142        2728 :             const bool v1_is_ivec = details::is_ivector_node  (branch[1]);
   33143             : 
   33144             :             #ifndef exprtk_disable_string_capabilities
   33145        2728 :             const bool v0_is_str = details::is_generally_string_node(branch[0]);
   33146        2728 :             const bool v1_is_str = details::is_generally_string_node(branch[1]);
   33147             :             #endif
   33148             : 
   33149        2728 :             expression_node_ptr result = error_node();
   33150        2728 :             std::string node_name      = "Unknown";
   33151             : 
   33152        2728 :             if (v0_is_ivar && v1_is_ivar)
   33153             :             {
   33154             :                typedef details::variable_node<T>* variable_node_ptr;
   33155             : 
   33156         566 :                variable_node_ptr v0 = variable_node_ptr(0);
   33157         566 :                variable_node_ptr v1 = variable_node_ptr(0);
   33158             : 
   33159         566 :                if (
   33160         886 :                     (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
   33161         320 :                     (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
   33162             :                   )
   33163             :                {
   33164         240 :                   result    = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
   33165         240 :                   node_name = "swap_node";
   33166             :                }
   33167             :                else
   33168             :                {
   33169         326 :                   result    = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
   33170         326 :                   node_name = "swap_generic_node";
   33171             :                }
   33172         566 :             }
   33173        2162 :             else if (v0_is_ivec && v1_is_ivec)
   33174             :             {
   33175         662 :                result    = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
   33176         662 :                node_name = "swap_vecvec_node";
   33177             :             }
   33178             :             #ifndef exprtk_disable_string_capabilities
   33179        1500 :             else if (v0_is_str && v1_is_str)
   33180             :             {
   33181        3000 :                if (is_string_node(branch[0]) && is_string_node(branch[1]))
   33182             :                {
   33183           0 :                   result = node_allocator_->allocate<details::swap_string_node<T> >
   33184           0 :                                                (branch[0], branch[1]);
   33185           0 :                   node_name = "swap_string_node";
   33186             :                }
   33187             :                else
   33188             :                {
   33189        3000 :                   result = node_allocator_->allocate<details::swap_genstrings_node<T> >
   33190        1500 :                                                (branch[0], branch[1]);
   33191        1500 :                   node_name = "swap_genstrings_node";
   33192             :                }
   33193             :             }
   33194             :             #endif
   33195             :             else
   33196             :             {
   33197           0 :                parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
   33198           0 :                return error_node();
   33199             :             }
   33200             : 
   33201        2728 :             if (result && result->valid())
   33202             :             {
   33203        5456 :                parser_->state_.activate_side_effect("synthesize_swap_expression()");
   33204        2728 :                return result;
   33205             :             }
   33206             : 
   33207           0 :             parser_->set_error(parser_error::make_error(
   33208             :                parser_error::e_synthesis,
   33209           0 :                token_t(),
   33210             :                "ERR248 - Failed to synthesize node: " + node_name,
   33211             :                exprtk_error_location));
   33212             : 
   33213           0 :             details::free_node(*node_allocator_, result);
   33214           0 :             return error_node();
   33215        2728 :          }
   33216             : 
   33217             :          #ifndef exprtk_disable_sc_andor
   33218         856 :          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   33219             :          {
   33220         856 :             expression_node_ptr result = error_node();
   33221             : 
   33222         856 :             if (details::is_constant_node(branch[0]))
   33223             :             {
   33224         843 :                if (
   33225        1266 :                     (details::e_scand == operation) &&
   33226        1266 :                     std::equal_to<T>()(T(0),branch[0]->value())
   33227             :                   )
   33228         210 :                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
   33229         633 :                else if (
   33230        1053 :                          (details::e_scor == operation) &&
   33231        1053 :                          std::not_equal_to<T>()(T(0),branch[0]->value())
   33232             :                        )
   33233         210 :                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
   33234             :             }
   33235             : 
   33236         856 :             if (details::is_constant_node(branch[1]) && (0 == result))
   33237             :             {
   33238         430 :                if (
   33239         650 :                     (details::e_scand == operation) &&
   33240         650 :                     std::equal_to<T>()(T(0),branch[1]->value())
   33241             :                   )
   33242         106 :                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
   33243         324 :                else if (
   33244         534 :                          (details::e_scor == operation) &&
   33245         534 :                          std::not_equal_to<T>()(T(0),branch[1]->value())
   33246             :                        )
   33247         105 :                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
   33248             :             }
   33249             : 
   33250         856 :             if (result)
   33251             :             {
   33252         631 :                details::free_node(*node_allocator_, branch[0]);
   33253         631 :                details::free_node(*node_allocator_, branch[1]);
   33254             : 
   33255         631 :                return result;
   33256             :             }
   33257         225 :             else if (details::e_scand == operation)
   33258             :             {
   33259         120 :                return synthesize_expression<scand_node_t,2>(operation, branch);
   33260             :             }
   33261         105 :             else if (details::e_scor == operation)
   33262             :             {
   33263         105 :                return synthesize_expression<scor_node_t,2>(operation, branch);
   33264             :             }
   33265             :             else
   33266           0 :                return error_node();
   33267             :          }
   33268             :          #else
   33269             :          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
   33270             :          {
   33271             :             return error_node();
   33272             :          }
   33273             :          #endif
   33274             : 
   33275             :          #define basic_opr_switch_statements         \
   33276             :          case_stmt(details::e_add , details::add_op) \
   33277             :          case_stmt(details::e_sub , details::sub_op) \
   33278             :          case_stmt(details::e_mul , details::mul_op) \
   33279             :          case_stmt(details::e_div , details::div_op) \
   33280             :          case_stmt(details::e_mod , details::mod_op) \
   33281             :          case_stmt(details::e_pow , details::pow_op) \
   33282             : 
   33283             :          #define extended_opr_switch_statements        \
   33284             :          case_stmt(details::e_lt   , details::lt_op  ) \
   33285             :          case_stmt(details::e_lte  , details::lte_op ) \
   33286             :          case_stmt(details::e_gt   , details::gt_op  ) \
   33287             :          case_stmt(details::e_gte  , details::gte_op ) \
   33288             :          case_stmt(details::e_eq   , details::eq_op  ) \
   33289             :          case_stmt(details::e_ne   , details::ne_op  ) \
   33290             :          case_stmt(details::e_and  , details::and_op ) \
   33291             :          case_stmt(details::e_nand , details::nand_op) \
   33292             :          case_stmt(details::e_or   , details::or_op  ) \
   33293             :          case_stmt(details::e_nor  , details::nor_op ) \
   33294             :          case_stmt(details::e_xor  , details::xor_op ) \
   33295             :          case_stmt(details::e_xnor , details::xnor_op) \
   33296             : 
   33297             :          #ifndef exprtk_disable_cardinal_pow_optimisation
   33298             :          template <typename TType, template <typename, typename> class IPowNode>
   33299       62113 :          inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
   33300             :          {
   33301       62113 :             switch (p)
   33302             :             {
   33303             :                #define case_stmt(cp)                                                     \
   33304             :                case cp : return node_allocator_->                                        \
   33305             :                             allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
   33306             : 
   33307       20138 :                case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
   33308       27770 :                case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
   33309       11085 :                case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
   33310         960 :                case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
   33311         960 :                case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
   33312         960 :                case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
   33313         240 :                case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
   33314           0 :                case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
   33315           0 :                case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
   33316           0 :                case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
   33317           0 :                case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
   33318           0 :                case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
   33319           0 :                case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
   33320           0 :                case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
   33321           0 :                case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
   33322             :                #undef case_stmt
   33323           0 :                default : return error_node();
   33324             :             }
   33325             :          }
   33326             : 
   33327       73697 :          inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
   33328             :          {
   33329       73697 :             const bool not_recipricol = (c >= T(0));
   33330       73697 :             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
   33331             : 
   33332       73697 :             if (0 == p)
   33333         240 :                return node_allocator_->allocate_c<literal_node_t>(T(1));
   33334       73457 :             else if (std::equal_to<T>()(T(2),c))
   33335             :             {
   33336       11345 :                return node_allocator_->
   33337       11345 :                   template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
   33338             :             }
   33339             :             else
   33340             :             {
   33341       62112 :                if (not_recipricol)
   33342       59062 :                   return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
   33343             :                else
   33344        3050 :                   return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
   33345             :             }
   33346             :          }
   33347             : 
   33348      644791 :          inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
   33349             :          {
   33350      644791 :             return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
   33351             :          }
   33352             : 
   33353           1 :          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
   33354             :          {
   33355           1 :             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   33356           1 :             const bool not_recipricol = (c >= T(0));
   33357           1 :             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
   33358             : 
   33359           1 :             node_allocator_->free(branch[1]);
   33360             : 
   33361           1 :             if (0 == p)
   33362             :             {
   33363           0 :                details::free_all_nodes(*node_allocator_, branch);
   33364             : 
   33365           0 :                return node_allocator_->allocate_c<literal_node_t>(T(1));
   33366             :             }
   33367           1 :             else if (not_recipricol)
   33368           1 :                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
   33369             :             else
   33370           0 :                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p);
   33371             :          }
   33372             :          #else
   33373             :          inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
   33374             :          {
   33375             :             return error_node();
   33376             :          }
   33377             : 
   33378             :          inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
   33379             :          {
   33380             :             return false;
   33381             :          }
   33382             : 
   33383             :          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
   33384             :          {
   33385             :             return error_node();
   33386             :          }
   33387             :          #endif
   33388             : 
   33389             :          struct synthesize_binary_ext_expression
   33390             :          {
   33391      405857 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   33392             :                                                       const details::operator_type& operation,
   33393             :                                                       expression_node_ptr (&branch)[2])
   33394             :             {
   33395      405857 :                const bool left_neg  = is_neg_unary_node(branch[0]);
   33396      405857 :                const bool right_neg = is_neg_unary_node(branch[1]);
   33397             : 
   33398      405857 :                if (left_neg && right_neg)
   33399             :                {
   33400         200 :                   if (
   33401         200 :                        (details::e_add == operation) ||
   33402         200 :                        (details::e_sub == operation) ||
   33403         200 :                        (details::e_mul == operation) ||
   33404          80 :                        (details::e_div == operation)
   33405             :                      )
   33406             :                   {
   33407         200 :                      if (
   33408         400 :                           !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
   33409         200 :                           !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
   33410             :                         )
   33411             :                      {
   33412           0 :                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
   33413             : 
   33414           0 :                         return error_node();
   33415             :                      }
   33416             :                   }
   33417             : 
   33418         200 :                   switch (operation)
   33419             :                   {
   33420             :                                            // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
   33421           0 :                      case details::e_add : return expr_gen(details::e_neg,
   33422           0 :                                               expr_gen.node_allocator_->
   33423             :                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
   33424           0 :                                                     (branch[0],branch[1]));
   33425             : 
   33426             :                                            // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
   33427           0 :                      case details::e_sub : return expr_gen.node_allocator_->
   33428             :                                               template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
   33429           0 :                                                  (branch[1],branch[0]);
   33430             : 
   33431         200 :                      default             : break;
   33432             :                   }
   33433             :                }
   33434      405657 :                else if (left_neg && !right_neg)
   33435             :                {
   33436         540 :                   if (
   33437         540 :                        (details::e_add == operation) ||
   33438         360 :                        (details::e_sub == operation) ||
   33439         200 :                        (details::e_mul == operation) ||
   33440          80 :                        (details::e_div == operation)
   33441             :                      )
   33442             :                   {
   33443         540 :                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
   33444             :                      {
   33445           0 :                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
   33446             : 
   33447           0 :                         return error_node();
   33448             :                      }
   33449             : 
   33450         540 :                      switch (operation)
   33451             :                      {
   33452             :                                               // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
   33453         180 :                         case details::e_add : return expr_gen.node_allocator_->
   33454             :                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
   33455         180 :                                                    (branch[1], branch[0]);
   33456             : 
   33457             :                                               // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
   33458         320 :                         case details::e_sub : return expr_gen(details::e_neg,
   33459         160 :                                                  expr_gen.node_allocator_->
   33460             :                                                     template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
   33461         320 :                                                        (branch[0], branch[1]));
   33462             : 
   33463             :                                               // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
   33464         240 :                         case details::e_mul : return expr_gen(details::e_neg,
   33465         120 :                                                  expr_gen.node_allocator_->
   33466             :                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
   33467         240 :                                                        (branch[0], branch[1]));
   33468             : 
   33469             :                                               // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
   33470         160 :                         case details::e_div : return expr_gen(details::e_neg,
   33471          80 :                                                  expr_gen.node_allocator_->
   33472             :                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
   33473         160 :                                                        (branch[0], branch[1]));
   33474             : 
   33475           0 :                         default             : return error_node();
   33476             :                      }
   33477             :                   }
   33478             :                }
   33479      405117 :                else if (!left_neg && right_neg)
   33480             :                {
   33481         688 :                   if (
   33482         688 :                        (details::e_add == operation) ||
   33483         688 :                        (details::e_sub == operation) ||
   33484         688 :                        (details::e_mul == operation) ||
   33485         568 :                        (details::e_div == operation)
   33486             :                      )
   33487             :                   {
   33488         200 :                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
   33489             :                      {
   33490           0 :                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
   33491             : 
   33492           0 :                         return error_node();
   33493             :                      }
   33494             : 
   33495         200 :                      switch (operation)
   33496             :                      {
   33497             :                                               // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
   33498           0 :                         case details::e_add : return expr_gen.node_allocator_->
   33499             :                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
   33500           0 :                                                    (branch[0], branch[1]);
   33501             : 
   33502             :                                               // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
   33503           0 :                         case details::e_sub : return expr_gen.node_allocator_->
   33504             :                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
   33505           0 :                                                    (branch[0], branch[1]);
   33506             : 
   33507             :                                               // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
   33508         240 :                         case details::e_mul : return expr_gen(details::e_neg,
   33509         120 :                                                  expr_gen.node_allocator_->
   33510             :                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
   33511         240 :                                                        (branch[0], branch[1]));
   33512             : 
   33513             :                                               // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
   33514         160 :                         case details::e_div : return expr_gen(details::e_neg,
   33515          80 :                                                  expr_gen.node_allocator_->
   33516             :                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
   33517         160 :                                                        (branch[0], branch[1]));
   33518             : 
   33519           0 :                         default             : return error_node();
   33520             :                      }
   33521             :                   }
   33522             :                }
   33523             : 
   33524      405117 :                switch (operation)
   33525             :                {
   33526             :                   #define case_stmt(op0, op1)                                                          \
   33527             :                   case op0 : return expr_gen.node_allocator_->                                         \
   33528             :                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
   33529             :                                    (branch[0], branch[1]);                                             \
   33530             : 
   33531      397115 :                   basic_opr_switch_statements
   33532        8002 :                   extended_opr_switch_statements
   33533             :                   #undef case_stmt
   33534           0 :                   default : return error_node();
   33535             :                }
   33536             :             }
   33537             :          };
   33538             : 
   33539             :          struct synthesize_vob_expression
   33540             :          {
   33541       52659 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   33542             :                                                       const details::operator_type& operation,
   33543             :                                                       expression_node_ptr (&branch)[2])
   33544             :             {
   33545       52659 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   33546             : 
   33547             :                #ifndef exprtk_disable_enhanced_features
   33548       52659 :                if (details::is_sf3ext_node(branch[1]))
   33549             :                {
   33550       37060 :                   expression_node_ptr result = error_node();
   33551             : 
   33552             :                   const bool synthesis_result =
   33553             :                      synthesize_sf4ext_expression::template compile_right<vtype>
   33554       37060 :                         (expr_gen, v, operation, branch[1], result);
   33555             : 
   33556       37060 :                   if (synthesis_result)
   33557             :                   {
   33558       18860 :                      details::free_node(*expr_gen.node_allocator_,branch[1]);
   33559       18860 :                      return result;
   33560             :                   }
   33561             :                }
   33562             :                #endif
   33563             : 
   33564       33799 :                if (
   33565       33799 :                     (details::e_mul == operation) ||
   33566       26875 :                     (details::e_div == operation)
   33567             :                   )
   33568             :                {
   33569       21217 :                   if (details::is_uv_node(branch[1]))
   33570             :                   {
   33571             :                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
   33572             : 
   33573         290 :                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
   33574             : 
   33575         290 :                      if (details::e_neg == o)
   33576             :                      {
   33577          40 :                         const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
   33578             : 
   33579          40 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   33580             : 
   33581          40 :                         switch (operation)
   33582             :                         {
   33583          80 :                            case details::e_mul : return expr_gen(details::e_neg,
   33584          40 :                                                     expr_gen.node_allocator_->
   33585             :                                                        template allocate_rr<typename details::
   33586          40 :                                                           vov_node<Type,details::mul_op<Type> > >(v,v1));
   33587             : 
   33588           0 :                            case details::e_div : return expr_gen(details::e_neg,
   33589           0 :                                                     expr_gen.node_allocator_->
   33590             :                                                        template allocate_rr<typename details::
   33591           0 :                                                           vov_node<Type,details::div_op<Type> > >(v,v1));
   33592             : 
   33593           0 :                            default             : break;
   33594             :                         }
   33595             :                      }
   33596             :                   }
   33597             :                }
   33598             : 
   33599       33759 :                switch (operation)
   33600             :                {
   33601             :                   #define case_stmt(op0, op1)                                                      \
   33602             :                   case op0 : return expr_gen.node_allocator_->                                     \
   33603             :                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
   33604             :                                    (v, branch[1]);                                                 \
   33605             : 
   33606       33722 :                   basic_opr_switch_statements
   33607          37 :                   extended_opr_switch_statements
   33608             :                   #undef case_stmt
   33609           0 :                   default : return error_node();
   33610             :                }
   33611             :             }
   33612             :          };
   33613             : 
   33614             :          struct synthesize_bov_expression
   33615             :          {
   33616      361461 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   33617             :                                                       const details::operator_type& operation,
   33618             :                                                       expression_node_ptr (&branch)[2])
   33619             :             {
   33620      361461 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   33621             : 
   33622             :                #ifndef exprtk_disable_enhanced_features
   33623      361461 :                if (details::is_sf3ext_node(branch[0]))
   33624             :                {
   33625       67662 :                   expression_node_ptr result = error_node();
   33626             : 
   33627             :                   const bool synthesis_result =
   33628             :                      synthesize_sf4ext_expression::template compile_left<vtype>
   33629       67662 :                         (expr_gen, v, operation, branch[0], result);
   33630             : 
   33631       67662 :                   if (synthesis_result)
   33632             :                   {
   33633        8575 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   33634             : 
   33635        8575 :                      return result;
   33636             :                   }
   33637             :                }
   33638             :                #endif
   33639             : 
   33640      352886 :                if (
   33641      352886 :                     (details::e_add == operation) ||
   33642      175360 :                     (details::e_sub == operation) ||
   33643      107499 :                     (details::e_mul == operation) ||
   33644       23044 :                     (details::e_div == operation)
   33645             :                   )
   33646             :                {
   33647      352023 :                   if (details::is_uv_node(branch[0]))
   33648             :                   {
   33649             :                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
   33650             : 
   33651         171 :                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
   33652             : 
   33653         171 :                      if (details::e_neg == o)
   33654             :                      {
   33655         120 :                         const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
   33656             : 
   33657         120 :                         details::free_node(*expr_gen.node_allocator_,branch[0]);
   33658             : 
   33659         120 :                         switch (operation)
   33660             :                         {
   33661          40 :                            case details::e_add : return expr_gen.node_allocator_->
   33662             :                                                     template allocate_rr<typename details::
   33663          40 :                                                        vov_node<Type,details::sub_op<Type> > >(v,v0);
   33664             : 
   33665          80 :                            case details::e_sub : return expr_gen(details::e_neg,
   33666          40 :                                                     expr_gen.node_allocator_->
   33667             :                                                        template allocate_rr<typename details::
   33668          40 :                                                           vov_node<Type,details::add_op<Type> > >(v0,v));
   33669             : 
   33670          80 :                            case details::e_mul : return expr_gen(details::e_neg,
   33671          40 :                                                     expr_gen.node_allocator_->
   33672             :                                                        template allocate_rr<typename details::
   33673          40 :                                                           vov_node<Type,details::mul_op<Type> > >(v0,v));
   33674             : 
   33675           0 :                            case details::e_div : return expr_gen(details::e_neg,
   33676           0 :                                                     expr_gen.node_allocator_->
   33677             :                                                        template allocate_rr<typename details::
   33678           0 :                                                           vov_node<Type,details::div_op<Type> > >(v0,v));
   33679           0 :                            default : break;
   33680             :                         }
   33681             :                      }
   33682             :                   }
   33683             :                }
   33684             : 
   33685      352766 :                switch (operation)
   33686             :                {
   33687             :                   #define case_stmt(op0, op1)                                                      \
   33688             :                   case op0 : return expr_gen.node_allocator_->                                     \
   33689             :                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
   33690             :                                    (branch[0], v);                                                 \
   33691             : 
   33692      351909 :                   basic_opr_switch_statements
   33693         857 :                   extended_opr_switch_statements
   33694             :                   #undef case_stmt
   33695           0 :                   default : return error_node();
   33696             :                }
   33697             :             }
   33698             :          };
   33699             : 
   33700             :          struct synthesize_cob_expression
   33701             :          {
   33702       98942 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   33703             :                                                       const details::operator_type& operation,
   33704             :                                                       expression_node_ptr (&branch)[2])
   33705             :             {
   33706       98942 :                const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   33707             : 
   33708       98942 :                details::free_node(*expr_gen.node_allocator_,branch[0]);
   33709             : 
   33710       98942 :                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   33711             :                {
   33712         590 :                   details::free_node(*expr_gen.node_allocator_,branch[1]);
   33713             : 
   33714         590 :                   return expr_gen(T(0));
   33715             :                }
   33716       98352 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   33717             :                {
   33718          55 :                   details::free_node(*expr_gen.node_allocator_, branch[1]);
   33719             : 
   33720          55 :                   return expr_gen(T(0));
   33721             :                }
   33722       98297 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   33723           0 :                   return branch[1];
   33724       98297 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   33725           0 :                   return branch[1];
   33726             : 
   33727       98297 :                if (details::is_cob_node(branch[1]))
   33728             :                {
   33729             :                   // Simplify expressions of the form:
   33730             :                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
   33731             :                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
   33732        1461 :                   if (
   33733        1461 :                        (details::e_mul == operation) ||
   33734        1211 :                        (details::e_add == operation)
   33735             :                      )
   33736             :                   {
   33737         841 :                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   33738             : 
   33739         841 :                      if (operation == cobnode->operation())
   33740             :                      {
   33741           0 :                         switch (operation)
   33742             :                         {
   33743           0 :                            case details::e_add : cobnode->set_c(c + cobnode->c()); break;
   33744           0 :                            case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
   33745           0 :                            default             : return error_node();
   33746             :                         }
   33747             : 
   33748           0 :                         return cobnode;
   33749             :                      }
   33750             :                   }
   33751             : 
   33752        1461 :                   if (operation == details::e_mul)
   33753             :                   {
   33754         250 :                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   33755         250 :                      details::operator_type cob_opr = cobnode->operation();
   33756             : 
   33757         250 :                      if (
   33758         250 :                           (details::e_div == cob_opr) ||
   33759             :                           (details::e_mul == cob_opr)
   33760             :                         )
   33761             :                      {
   33762           0 :                         switch (cob_opr)
   33763             :                         {
   33764           0 :                            case details::e_div : cobnode->set_c(c * cobnode->c()); break;
   33765           0 :                            case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
   33766           0 :                            default             : return error_node();
   33767             :                         }
   33768             : 
   33769           0 :                         return cobnode;
   33770             :                      }
   33771             :                   }
   33772        1211 :                   else if (operation == details::e_div)
   33773             :                   {
   33774         250 :                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   33775         250 :                      details::operator_type cob_opr = cobnode->operation();
   33776             : 
   33777         250 :                      if (
   33778         250 :                           (details::e_div == cob_opr) ||
   33779             :                           (details::e_mul == cob_opr)
   33780             :                         )
   33781             :                      {
   33782           0 :                         details::expression_node<Type>* new_cobnode = error_node();
   33783             : 
   33784           0 :                         switch (cob_opr)
   33785             :                         {
   33786           0 :                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
   33787             :                                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
   33788           0 :                                                        (c / cobnode->c(), cobnode->move_branch(0));
   33789           0 :                                                  break;
   33790             : 
   33791           0 :                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
   33792             :                                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   33793           0 :                                                        (c / cobnode->c(), cobnode->move_branch(0));
   33794           0 :                                                  break;
   33795             : 
   33796           0 :                            default             : return error_node();
   33797             :                         }
   33798             : 
   33799           0 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   33800             : 
   33801           0 :                         return new_cobnode;
   33802             :                      }
   33803             :                   }
   33804             :                }
   33805             :                #ifndef exprtk_disable_enhanced_features
   33806       96836 :                else if (details::is_sf3ext_node(branch[1]))
   33807             :                {
   33808       28475 :                   expression_node_ptr result = error_node();
   33809             : 
   33810             :                   const bool synthesis_result =
   33811             :                      synthesize_sf4ext_expression::template compile_right<ctype>
   33812       28475 :                         (expr_gen, c, operation, branch[1], result);
   33813             : 
   33814       28475 :                   if (synthesis_result)
   33815             :                   {
   33816       10324 :                      details::free_node(*expr_gen.node_allocator_,branch[1]);
   33817             : 
   33818       10324 :                      return result;
   33819             :                   }
   33820             :                }
   33821             :                #endif
   33822             : 
   33823       87973 :                switch (operation)
   33824             :                {
   33825             :                   #define case_stmt(op0, op1)                                                      \
   33826             :                   case op0 : return expr_gen.node_allocator_->                                     \
   33827             :                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
   33828             :                                    (c,  branch[1]);                                                \
   33829             : 
   33830       87341 :                   basic_opr_switch_statements
   33831         632 :                   extended_opr_switch_statements
   33832             :                   #undef case_stmt
   33833           0 :                   default : return error_node();
   33834             :                }
   33835             :             }
   33836             :          };
   33837             : 
   33838             :          struct synthesize_boc_expression
   33839             :          {
   33840      146238 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   33841             :                                                       const details::operator_type& operation,
   33842             :                                                       expression_node_ptr (&branch)[2])
   33843             :             {
   33844      146238 :                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   33845             : 
   33846      146238 :                details::free_node(*(expr_gen.node_allocator_), branch[1]);
   33847             : 
   33848      146238 :                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   33849             :                {
   33850         104 :                   details::free_node(*expr_gen.node_allocator_, branch[0]);
   33851             : 
   33852         104 :                   return expr_gen(T(0));
   33853             :                }
   33854      146134 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   33855             :                {
   33856           1 :                   details::free_node(*expr_gen.node_allocator_, branch[0]);
   33857             : 
   33858           1 :                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
   33859             :                }
   33860      146133 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   33861           1 :                   return branch[0];
   33862      146132 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   33863         104 :                   return branch[0];
   33864             : 
   33865      146028 :                if (details::is_boc_node(branch[0]))
   33866             :                {
   33867             :                   // Simplify expressions of the form:
   33868             :                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
   33869             :                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
   33870        2175 :                   if (
   33871        2175 :                        (details::e_mul == operation) ||
   33872        1857 :                        (details::e_add == operation)
   33873             :                      )
   33874             :                   {
   33875         983 :                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   33876             : 
   33877         983 :                      if (operation == bocnode->operation())
   33878             :                      {
   33879           0 :                         switch (operation)
   33880             :                         {
   33881           0 :                            case details::e_add : bocnode->set_c(c + bocnode->c()); break;
   33882           0 :                            case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
   33883           0 :                            default             : return error_node();
   33884             :                         }
   33885             : 
   33886           0 :                         return bocnode;
   33887             :                      }
   33888         983 :                   }
   33889        1192 :                   else if (operation == details::e_div)
   33890             :                   {
   33891         250 :                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   33892         250 :                      details::operator_type        boc_opr = bocnode->operation();
   33893             : 
   33894         250 :                      if (
   33895         250 :                           (details::e_div == boc_opr) ||
   33896             :                           (details::e_mul == boc_opr)
   33897             :                         )
   33898             :                      {
   33899           0 :                         switch (boc_opr)
   33900             :                         {
   33901           0 :                            case details::e_div : bocnode->set_c(c * bocnode->c()); break;
   33902           0 :                            case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
   33903           0 :                            default             : return error_node();
   33904             :                         }
   33905             : 
   33906           0 :                         return bocnode;
   33907             :                      }
   33908             :                   }
   33909         942 :                   else if (operation == details::e_pow)
   33910             :                   {
   33911             :                      // (v ^ c0) ^ c1 --> v ^(c0 * c1)
   33912           0 :                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   33913           0 :                      details::operator_type        boc_opr = bocnode->operation();
   33914             : 
   33915           0 :                      if (details::e_pow == boc_opr)
   33916             :                      {
   33917           0 :                         bocnode->set_c(bocnode->c() * c);
   33918             : 
   33919           0 :                         return bocnode;
   33920             :                      }
   33921             :                   }
   33922             :                }
   33923             : 
   33924             :                #ifndef exprtk_disable_enhanced_features
   33925      146028 :                if (details::is_sf3ext_node(branch[0]))
   33926             :                {
   33927       48002 :                   expression_node_ptr result = error_node();
   33928             : 
   33929             :                   const bool synthesis_result =
   33930             :                      synthesize_sf4ext_expression::template compile_left<ctype>
   33931       48002 :                         (expr_gen, c, operation, branch[0], result);
   33932             : 
   33933       48002 :                   if (synthesis_result)
   33934             :                   {
   33935        4521 :                      free_node(*expr_gen.node_allocator_, branch[0]);
   33936             : 
   33937        4521 :                      return result;
   33938             :                   }
   33939             :                }
   33940             :                #endif
   33941             : 
   33942      141507 :                switch (operation)
   33943             :                {
   33944             :                   #define case_stmt(op0, op1)                                                      \
   33945             :                   case op0 : return expr_gen.node_allocator_->                                     \
   33946             :                                 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
   33947             :                                    (branch[0], c);                                                 \
   33948             : 
   33949      132284 :                   basic_opr_switch_statements
   33950        9223 :                   extended_opr_switch_statements
   33951             :                   #undef case_stmt
   33952           0 :                   default : return error_node();
   33953             :                }
   33954             :             }
   33955             :          };
   33956             : 
   33957             :          struct synthesize_cocob_expression
   33958             :          {
   33959        7918 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   33960             :                                                       const details::operator_type& operation,
   33961             :                                                       expression_node_ptr (&branch)[2])
   33962             :             {
   33963        7918 :                expression_node_ptr result = error_node();
   33964             : 
   33965             :                // (cob) o c --> cob
   33966        7918 :                if (details::is_cob_node(branch[0]))
   33967             :                {
   33968        4717 :                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
   33969             : 
   33970        4717 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   33971             : 
   33972        4717 :                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   33973             :                   {
   33974           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   33975           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   33976             : 
   33977           0 :                      return expr_gen(T(0));
   33978             :                   }
   33979        4717 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   33980             :                   {
   33981           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   33982           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   33983             : 
   33984           0 :                      return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
   33985             :                   }
   33986        4717 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   33987             :                   {
   33988           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   33989             : 
   33990           0 :                      return branch[0];
   33991             :                   }
   33992        4717 :                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   33993             :                   {
   33994           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   33995             : 
   33996           0 :                      return branch[0];
   33997             :                   }
   33998        4717 :                   else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
   33999             :                   {
   34000           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   34001             : 
   34002           0 :                      return branch[0];
   34003             :                   }
   34004             : 
   34005        7579 :                   const bool op_addsub = (details::e_add == cobnode->operation()) ||
   34006        2862 :                                          (details::e_sub == cobnode->operation()) ;
   34007             : 
   34008        4717 :                   if (op_addsub)
   34009             :                   {
   34010        2285 :                      switch (operation)
   34011             :                      {
   34012         495 :                         case details::e_add : cobnode->set_c(cobnode->c() + c); break;
   34013        1770 :                         case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
   34014          20 :                         default             : return error_node();
   34015             :                      }
   34016             : 
   34017        2265 :                      result = cobnode;
   34018             :                   }
   34019        2432 :                   else if (details::e_mul == cobnode->operation())
   34020             :                   {
   34021        1782 :                      switch (operation)
   34022             :                      {
   34023         215 :                         case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
   34024        1285 :                         case details::e_div : cobnode->set_c(cobnode->c() / c); break;
   34025         282 :                         default             : return error_node();
   34026             :                      }
   34027             : 
   34028        1500 :                      result = cobnode;
   34029             :                   }
   34030         650 :                   else if (details::e_div == cobnode->operation())
   34031             :                   {
   34032         650 :                      if (details::e_mul == operation)
   34033             :                      {
   34034         215 :                         cobnode->set_c(cobnode->c() * c);
   34035         215 :                         result = cobnode;
   34036             :                      }
   34037         435 :                      else if (details::e_div == operation)
   34038             :                      {
   34039         195 :                         result = expr_gen.node_allocator_->
   34040             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   34041         195 :                                        (cobnode->c() / c, cobnode->move_branch(0));
   34042             : 
   34043         195 :                         details::free_node(*expr_gen.node_allocator_, branch[0]);
   34044             :                      }
   34045             :                   }
   34046             : 
   34047        4415 :                   if (result)
   34048             :                   {
   34049        4175 :                      details::free_node(*expr_gen.node_allocator_,branch[1]);
   34050             :                   }
   34051             :                }
   34052             : 
   34053             :                // c o (cob) --> cob
   34054        3201 :                else if (details::is_cob_node(branch[1]))
   34055             :                {
   34056        3201 :                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
   34057             : 
   34058        3201 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   34059             : 
   34060        3201 :                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   34061             :                   {
   34062           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   34063           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   34064             : 
   34065           0 :                      return expr_gen(T(0));
   34066             :                   }
   34067        3201 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   34068             :                   {
   34069           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   34070           0 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   34071             : 
   34072           0 :                      return expr_gen(T(0));
   34073             :                   }
   34074        3201 :                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   34075             :                   {
   34076           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   34077             : 
   34078           0 :                      return branch[1];
   34079             :                   }
   34080        3201 :                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   34081             :                   {
   34082           0 :                      details::free_node(*expr_gen.node_allocator_, branch[0]);
   34083             : 
   34084           0 :                      return branch[1];
   34085             :                   }
   34086             : 
   34087        3201 :                   if (details::e_add == cobnode->operation())
   34088             :                   {
   34089         580 :                      if (details::e_add == operation)
   34090             :                      {
   34091         165 :                         cobnode->set_c(c + cobnode->c());
   34092         165 :                         result = cobnode;
   34093             :                      }
   34094         415 :                      else if (details::e_sub == operation)
   34095             :                      {
   34096         165 :                         result = expr_gen.node_allocator_->
   34097             :                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
   34098         165 :                                        (c - cobnode->c(), cobnode->move_branch(0));
   34099             : 
   34100         165 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34101             :                      }
   34102             :                   }
   34103        2621 :                   else if (details::e_sub == cobnode->operation())
   34104             :                   {
   34105         540 :                      if (details::e_add == operation)
   34106             :                      {
   34107         165 :                         cobnode->set_c(c + cobnode->c());
   34108         165 :                         result = cobnode;
   34109             :                      }
   34110         375 :                      else if (details::e_sub == operation)
   34111             :                      {
   34112         125 :                         result = expr_gen.node_allocator_->
   34113             :                                     template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
   34114         125 :                                        (c - cobnode->c(), cobnode->move_branch(0));
   34115             : 
   34116         125 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34117             :                      }
   34118             :                   }
   34119        2081 :                   else if (details::e_mul == cobnode->operation())
   34120             :                   {
   34121        1041 :                      if (details::e_mul == operation)
   34122             :                      {
   34123         335 :                         cobnode->set_c(c * cobnode->c());
   34124         335 :                         result = cobnode;
   34125             :                      }
   34126         706 :                      else if (details::e_div == operation)
   34127             :                      {
   34128         225 :                         result = expr_gen.node_allocator_->
   34129             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   34130         225 :                                        (c / cobnode->c(), cobnode->move_branch(0));
   34131             : 
   34132         225 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34133             :                      }
   34134             :                   }
   34135        1040 :                   else if (details::e_div == cobnode->operation())
   34136             :                   {
   34137        1040 :                      if (details::e_mul == operation)
   34138             :                      {
   34139         335 :                         cobnode->set_c(c * cobnode->c());
   34140         335 :                         result = cobnode;
   34141             :                      }
   34142         705 :                      else if (details::e_div == operation)
   34143             :                      {
   34144         225 :                         result = expr_gen.node_allocator_->
   34145             :                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
   34146         225 :                                        (c / cobnode->c(), cobnode->move_branch(0));
   34147             : 
   34148         225 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34149             :                      }
   34150             :                   }
   34151             : 
   34152        3201 :                   if (result)
   34153             :                   {
   34154        1740 :                      details::free_node(*expr_gen.node_allocator_,branch[0]);
   34155             :                   }
   34156             :                }
   34157             : 
   34158        7616 :                return result;
   34159             :             }
   34160             :          };
   34161             : 
   34162             :          struct synthesize_coboc_expression
   34163             :          {
   34164       24432 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34165             :                                                       const details::operator_type& operation,
   34166             :                                                       expression_node_ptr (&branch)[2])
   34167             :             {
   34168       24432 :                expression_node_ptr result = error_node();
   34169             : 
   34170             :                // (boc) o c --> boc
   34171       24432 :                if (details::is_boc_node(branch[0]))
   34172             :                {
   34173       22177 :                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
   34174             : 
   34175       22177 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   34176             : 
   34177       22177 :                   if (details::e_add == bocnode->operation())
   34178             :                   {
   34179        8689 :                      switch (operation)
   34180             :                      {
   34181        4925 :                         case details::e_add : bocnode->set_c(bocnode->c() + c); break;
   34182        3514 :                         case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
   34183         250 :                         default             : return error_node();
   34184             :                      }
   34185             : 
   34186        8439 :                      result = bocnode;
   34187             :                   }
   34188       13488 :                   else if (details::e_mul == bocnode->operation())
   34189             :                   {
   34190        3635 :                      switch (operation)
   34191             :                      {
   34192        1720 :                         case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
   34193        1395 :                         case details::e_div : bocnode->set_c(bocnode->c() / c); break;
   34194         520 :                         default             : return error_node();
   34195             :                      }
   34196             : 
   34197        3115 :                      result = bocnode;
   34198             :                   }
   34199        9853 :                   else if (details::e_sub == bocnode->operation())
   34200             :                   {
   34201        5963 :                      if (details::e_add == operation)
   34202             :                      {
   34203        2339 :                         result = expr_gen.node_allocator_->
   34204             :                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
   34205        2339 :                                        (bocnode->move_branch(0), c - bocnode->c());
   34206             : 
   34207        2339 :                         details::free_node(*expr_gen.node_allocator_,branch[0]);
   34208             :                      }
   34209        3624 :                      else if (details::e_sub == operation)
   34210             :                      {
   34211        3304 :                         bocnode->set_c(bocnode->c() + c);
   34212        3304 :                         result = bocnode;
   34213             :                      }
   34214             :                   }
   34215        3890 :                   else if (details::e_div == bocnode->operation())
   34216             :                   {
   34217        3890 :                      switch (operation)
   34218             :                      {
   34219        2175 :                         case details::e_div : bocnode->set_c(bocnode->c() * c); break;
   34220        1240 :                         case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
   34221         475 :                         default             : return error_node();
   34222             :                      }
   34223             : 
   34224        3415 :                      result = bocnode;
   34225             :                   }
   34226             : 
   34227       20932 :                   if (result)
   34228             :                   {
   34229       20612 :                      details::free_node(*expr_gen.node_allocator_, branch[1]);
   34230             :                   }
   34231             :                }
   34232             : 
   34233             :                // c o (boc) --> boc
   34234        2255 :                else if (details::is_boc_node(branch[1]))
   34235             :                {
   34236        2255 :                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
   34237             : 
   34238        2255 :                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   34239             : 
   34240        2255 :                   if (details::e_add == bocnode->operation())
   34241             :                   {
   34242         260 :                      if (details::e_add == operation)
   34243             :                      {
   34244         205 :                         bocnode->set_c(c + bocnode->c());
   34245         205 :                         result = bocnode;
   34246             :                      }
   34247          55 :                      else if (details::e_sub == operation)
   34248             :                      {
   34249          45 :                         result = expr_gen.node_allocator_->
   34250             :                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
   34251          45 :                                        (c - bocnode->c(), bocnode->move_branch(0));
   34252             : 
   34253          45 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34254             :                      }
   34255             :                   }
   34256        1995 :                   else if (details::e_sub == bocnode->operation())
   34257             :                   {
   34258         190 :                      if (details::e_add == operation)
   34259             :                      {
   34260          45 :                         result = expr_gen.node_allocator_->
   34261             :                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
   34262          45 :                                        (bocnode->move_branch(0), c - bocnode->c());
   34263             : 
   34264          45 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34265             :                      }
   34266         145 :                      else if (details::e_sub == operation)
   34267             :                      {
   34268          65 :                         result = expr_gen.node_allocator_->
   34269             :                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
   34270          65 :                                        (c + bocnode->c(), bocnode->move_branch(0));
   34271             : 
   34272          65 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34273             :                      }
   34274             :                   }
   34275        1805 :                   else if (details::e_mul == bocnode->operation())
   34276             :                   {
   34277         895 :                      if (details::e_mul == operation)
   34278             :                      {
   34279         125 :                         bocnode->set_c(c * bocnode->c());
   34280         125 :                         result = bocnode;
   34281             :                      }
   34282         770 :                      else if (details::e_div == operation)
   34283             :                      {
   34284          45 :                         result = expr_gen.node_allocator_->
   34285             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   34286          45 :                                        (c / bocnode->c(), bocnode->move_branch(0));
   34287             : 
   34288          45 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34289             :                      }
   34290             :                   }
   34291         910 :                   else if (details::e_div == bocnode->operation())
   34292             :                   {
   34293         910 :                      if (details::e_mul == operation)
   34294             :                      {
   34295         120 :                         bocnode->set_c(bocnode->c() / c);
   34296         120 :                         result = bocnode;
   34297             :                      }
   34298         790 :                      else if (details::e_div == operation)
   34299             :                      {
   34300         120 :                         result = expr_gen.node_allocator_->
   34301             :                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
   34302         120 :                                        (c * bocnode->c(), bocnode->move_branch(0));
   34303             : 
   34304         120 :                         details::free_node(*expr_gen.node_allocator_,branch[1]);
   34305             :                      }
   34306             :                   }
   34307             : 
   34308        2255 :                   if (result)
   34309             :                   {
   34310         770 :                      details::free_node(*expr_gen.node_allocator_,branch[0]);
   34311             :                   }
   34312             :                }
   34313             : 
   34314       23187 :                return result;
   34315             :             }
   34316             :          };
   34317             : 
   34318             :          #ifndef exprtk_disable_enhanced_features
   34319     2834218 :          inline bool synthesize_expression(const details::operator_type& operation,
   34320             :                                            expression_node_ptr (&branch)[2],
   34321             :                                            expression_node_ptr& result)
   34322             :          {
   34323     2834218 :             result = error_node();
   34324             : 
   34325     2834218 :             if (!operation_optimisable(operation))
   34326      261298 :                return false;
   34327             : 
   34328     2572920 :             const std::string node_id = branch_to_id(branch);
   34329             : 
   34330     2572920 :             const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
   34331             : 
   34332     2572920 :             if (synthesize_map_.end() != itr)
   34333             :             {
   34334     1300273 :                result = itr->second((*this), operation, branch);
   34335             : 
   34336     1300273 :                return true;
   34337             :             }
   34338             :             else
   34339     1272647 :                return false;
   34340     2572920 :          }
   34341             : 
   34342             :          struct synthesize_vov_expression
   34343             :          {
   34344      252616 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34345             :                                                       const details::operator_type& operation,
   34346             :                                                       expression_node_ptr (&branch)[2])
   34347             :             {
   34348      252616 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   34349      252616 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   34350             : 
   34351      252616 :                switch (operation)
   34352             :                {
   34353             :                   #define case_stmt(op0, op1)                                                      \
   34354             :                   case op0 : return expr_gen.node_allocator_->                                     \
   34355             :                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
   34356             :                                    (v1, v2);                                                       \
   34357             : 
   34358      245551 :                   basic_opr_switch_statements
   34359        7065 :                   extended_opr_switch_statements
   34360             :                   #undef case_stmt
   34361           0 :                   default : return error_node();
   34362             :                }
   34363             :             }
   34364             :          };
   34365             : 
   34366             :          struct synthesize_cov_expression
   34367             :          {
   34368      205044 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34369             :                                                       const details::operator_type& operation,
   34370             :                                                       expression_node_ptr (&branch)[2])
   34371             :             {
   34372      205044 :                const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
   34373      205044 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref  ();
   34374             : 
   34375      205044 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   34376             : 
   34377      205044 :                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   34378         191 :                   return expr_gen(T(0));
   34379      204853 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   34380          60 :                   return expr_gen(T(0));
   34381      204793 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   34382          61 :                   return static_cast<details::variable_node<Type>*>(branch[1]);
   34383      204732 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   34384         202 :                   return static_cast<details::variable_node<Type>*>(branch[1]);
   34385             : 
   34386      204530 :                switch (operation)
   34387             :                {
   34388             :                   #define case_stmt(op0, op1)                                                      \
   34389             :                   case op0 : return expr_gen.node_allocator_->                                     \
   34390             :                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
   34391             :                                    (c, v);                                                         \
   34392             : 
   34393      204422 :                   basic_opr_switch_statements
   34394         108 :                   extended_opr_switch_statements
   34395             :                   #undef case_stmt
   34396           0 :                   default : return error_node();
   34397             :                }
   34398             :             }
   34399             :          };
   34400             : 
   34401             :          struct synthesize_voc_expression
   34402             :          {
   34403      351671 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34404             :                                                       const details::operator_type& operation,
   34405             :                                                       expression_node_ptr (&branch)[2])
   34406             :             {
   34407      351671 :                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref  ();
   34408      351671 :                const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
   34409             : 
   34410      351671 :                details::free_node(*(expr_gen.node_allocator_), branch[1]);
   34411             : 
   34412      351671 :                if (expr_gen.cardinal_pow_optimisable(operation,c))
   34413             :                {
   34414       85877 :                   if (std::equal_to<T>()(T(1),c))
   34415       12180 :                      return branch[0];
   34416             :                   else
   34417       73697 :                      return expr_gen.cardinal_pow_optimisation(v,c);
   34418             :                }
   34419      265794 :                else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
   34420         180 :                   return expr_gen(T(0));
   34421      265614 :                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
   34422           0 :                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
   34423      265614 :                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
   34424         541 :                   return static_cast<details::variable_node<Type>*>(branch[0]);
   34425      265073 :                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
   34426         193 :                   return static_cast<details::variable_node<Type>*>(branch[0]);
   34427      264880 :                else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
   34428          60 :                   return static_cast<details::variable_node<Type>*>(branch[0]);
   34429             : 
   34430      264820 :                switch (operation)
   34431             :                {
   34432             :                   #define case_stmt(op0, op1)                                                      \
   34433             :                   case op0 : return expr_gen.node_allocator_->                                     \
   34434             :                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
   34435             :                                    (v, c);                                                         \
   34436             : 
   34437      254309 :                   basic_opr_switch_statements
   34438       10511 :                   extended_opr_switch_statements
   34439             :                   #undef case_stmt
   34440           0 :                   default : return error_node();
   34441             :                }
   34442             :             }
   34443             :          };
   34444             : 
   34445             :          struct synthesize_sf3ext_expression
   34446             :          {
   34447             :             template <typename T0, typename T1, typename T2>
   34448      369024 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34449             :                                                       const details::operator_type& sf3opr,
   34450             :                                                       T0 t0, T1 t1, T2 t2)
   34451             :             {
   34452      369024 :                switch (sf3opr)
   34453             :                {
   34454             :                   #define case_stmt(op)                                                                              \
   34455             :                   case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
   34456             :                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2);                                   \
   34457             : 
   34458       37140 :                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
   34459       36603 :                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
   34460       97749 :                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
   34461       44413 :                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
   34462       51710 :                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
   34463       42612 :                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
   34464       38520 :                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
   34465       20277 :                   case_stmt(28) case_stmt(29) case_stmt(30)
   34466             :                   #undef case_stmt
   34467           0 :                   default : return error_node();
   34468             :                }
   34469             :             }
   34470             : 
   34471             :             template <typename T0, typename T1, typename T2>
   34472      374939 :             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
   34473             :                                        T0 t0, T1 t1, T2 t2,
   34474             :                                        expression_node_ptr& result)
   34475             :             {
   34476             :                details::operator_type sf3opr;
   34477             : 
   34478      374939 :                if (!expr_gen.sf3_optimisable(id,sf3opr))
   34479        5915 :                   return false;
   34480             :                else
   34481      369024 :                   result = synthesize_sf3ext_expression::template process<T0, T1, T2>
   34482      369024 :                               (expr_gen, sf3opr, t0, t1, t2);
   34483             : 
   34484      369024 :                return true;
   34485             :             }
   34486             :          };
   34487             : 
   34488             :          struct synthesize_sf4ext_expression
   34489             :          {
   34490             :             template <typename T0, typename T1, typename T2, typename T3>
   34491       97284 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34492             :                                                       const details::operator_type& sf4opr,
   34493             :                                                       T0 t0, T1 t1, T2 t2, T3 t3)
   34494             :             {
   34495       97284 :                switch (sf4opr)
   34496             :                {
   34497             :                   #define case_stmt0(op)                                                                                      \
   34498             :                   case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
   34499             :                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                        \
   34500             : 
   34501             :                   #define case_stmt1(op)                                                                                             \
   34502             :                   case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
   34503             :                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                               \
   34504             : 
   34505        3540 :                   case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
   34506        5065 :                   case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
   34507        4399 :                   case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
   34508        4475 :                   case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
   34509        4711 :                   case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
   34510        4810 :                   case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
   34511        4733 :                   case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
   34512        5911 :                   case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
   34513        3470 :                   case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
   34514             : 
   34515        6670 :                   case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
   34516        6550 :                   case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
   34517        2725 :                   case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
   34518        3770 :                   case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
   34519        3385 :                   case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
   34520        3340 :                   case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
   34521        3460 :                   case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
   34522        3115 :                   case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
   34523        3480 :                   case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
   34524        2590 :                   case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
   34525        1590 :                   case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
   34526        6400 :                   case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
   34527         640 :                   case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
   34528        1590 :                   case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
   34529        1720 :                   case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
   34530        5145 :                   case_stmt1(60) case_stmt1(61)
   34531             : 
   34532             :                   #undef case_stmt0
   34533             :                   #undef case_stmt1
   34534           0 :                   default : return error_node();
   34535             :                }
   34536             :             }
   34537             : 
   34538             :             template <typename T0, typename T1, typename T2, typename T3>
   34539      242740 :             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
   34540             :                                        T0 t0, T1 t1, T2 t2, T3 t3,
   34541             :                                        expression_node_ptr& result)
   34542             :             {
   34543             :                details::operator_type sf4opr;
   34544             : 
   34545      242740 :                if (!expr_gen.sf4_optimisable(id,sf4opr))
   34546      145456 :                   return false;
   34547             :                else
   34548       97284 :                   result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
   34549       97284 :                               (expr_gen, sf4opr, t0, t1, t2, t3);
   34550             : 
   34551       97284 :                return true;
   34552             :             }
   34553             : 
   34554             :             // T o (sf3ext)
   34555             :             template <typename ExternalType>
   34556       65535 :             static inline bool compile_right(expression_generator<Type>& expr_gen,
   34557             :                                              ExternalType t,
   34558             :                                              const details::operator_type& operation,
   34559             :                                              expression_node_ptr& sf3node,
   34560             :                                              expression_node_ptr& result)
   34561             :             {
   34562       65535 :                if (!details::is_sf3ext_node(sf3node))
   34563           0 :                   return false;
   34564             : 
   34565             :                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
   34566             : 
   34567       65535 :                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
   34568       65535 :                const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
   34569             : 
   34570       65535 :                switch (n->type())
   34571             :                {
   34572        2785 :                   case details::expression_node<Type>::e_covoc : return compile_right_impl
   34573             :                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
   34574        2785 :                                                                        (expr_gen, id, t, sf3node, result);
   34575             : 
   34576       14845 :                   case details::expression_node<Type>::e_covov : return compile_right_impl
   34577             :                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
   34578       14845 :                                                                        (expr_gen, id, t, sf3node, result);
   34579             : 
   34580       15450 :                   case details::expression_node<Type>::e_vocov : return compile_right_impl
   34581             :                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
   34582       15450 :                                                                        (expr_gen, id, t, sf3node, result);
   34583             : 
   34584       15375 :                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
   34585             :                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
   34586       15375 :                                                                        (expr_gen, id, t, sf3node, result);
   34587             : 
   34588       17080 :                   case details::expression_node<Type>::e_vovov : return compile_right_impl
   34589             :                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
   34590       17080 :                                                                        (expr_gen, id, t, sf3node, result);
   34591             : 
   34592           0 :                   default                                      : return false;
   34593             :                }
   34594       65535 :             }
   34595             : 
   34596             :             // (sf3ext) o T
   34597             :             template <typename ExternalType>
   34598      115664 :             static inline bool compile_left(expression_generator<Type>& expr_gen,
   34599             :                                             ExternalType t,
   34600             :                                             const details::operator_type& operation,
   34601             :                                             expression_node_ptr& sf3node,
   34602             :                                             expression_node_ptr& result)
   34603             :             {
   34604      115664 :                if (!details::is_sf3ext_node(sf3node))
   34605           0 :                   return false;
   34606             : 
   34607             :                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
   34608             : 
   34609      115664 :                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
   34610             : 
   34611      115664 :                const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
   34612             : 
   34613      115664 :                switch (n->type())
   34614             :                {
   34615        4480 :                   case details::expression_node<Type>::e_covoc : return compile_left_impl
   34616             :                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
   34617        4480 :                                                                        (expr_gen, id, t, sf3node, result);
   34618             : 
   34619       27465 :                   case details::expression_node<Type>::e_covov : return compile_left_impl
   34620             :                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
   34621       27465 :                                                                        (expr_gen, id, t, sf3node, result);
   34622             : 
   34623       24883 :                   case details::expression_node<Type>::e_vocov : return compile_left_impl
   34624             :                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
   34625       24883 :                                                                        (expr_gen, id, t, sf3node, result);
   34626             : 
   34627       25960 :                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
   34628             :                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
   34629       25960 :                                                                        (expr_gen, id, t, sf3node, result);
   34630             : 
   34631       32876 :                   case details::expression_node<Type>::e_vovov : return compile_left_impl
   34632             :                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
   34633       32876 :                                                                        (expr_gen, id, t, sf3node, result);
   34634             : 
   34635           0 :                   default                                      : return false;
   34636             :                }
   34637      115664 :             }
   34638             : 
   34639             :             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
   34640       65535 :             static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
   34641             :                                                   const std::string& id,
   34642             :                                                   ExternalType t,
   34643             :                                                   expression_node_ptr& node,
   34644             :                                                   expression_node_ptr& result)
   34645             :             {
   34646       65535 :                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
   34647             : 
   34648       65535 :                if (n)
   34649             :                {
   34650       65535 :                   T0 t0 = n->t0();
   34651       65535 :                   T1 t1 = n->t1();
   34652       65535 :                   T2 t2 = n->t2();
   34653             : 
   34654             :                   return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
   34655       65535 :                             (expr_gen, id, t, t0, t1, t2, result);
   34656             :                }
   34657             :                else
   34658           0 :                   return false;
   34659             :             }
   34660             : 
   34661             :             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
   34662      115664 :             static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
   34663             :                                                  const std::string& id,
   34664             :                                                  ExternalType t,
   34665             :                                                  expression_node_ptr& node,
   34666             :                                                  expression_node_ptr& result)
   34667             :             {
   34668      115664 :                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
   34669             : 
   34670      115664 :                if (n)
   34671             :                {
   34672      115664 :                   T0 t0 = n->t0();
   34673      115664 :                   T1 t1 = n->t1();
   34674      115664 :                   T2 t2 = n->t2();
   34675             : 
   34676             :                   return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
   34677      115664 :                             (expr_gen, id, t0, t1, t2, t, result);
   34678             :                }
   34679             :                else
   34680           0 :                   return false;
   34681             :             }
   34682             :          };
   34683             : 
   34684             :          struct synthesize_vovov_expression0
   34685             :          {
   34686             :             typedef typename vovov_t::type0 node_type;
   34687             :             typedef typename vovov_t::sf3_type sf3_type;
   34688             : 
   34689       58597 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34690             :                                                       const details::operator_type& operation,
   34691             :                                                       expression_node_ptr (&branch)[2])
   34692             :             {
   34693             :                // (v0 o0 v1) o1 (v2)
   34694       58597 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   34695       58597 :                const Type& v0 = vov->v0();
   34696       58597 :                const Type& v1 = vov->v1();
   34697       58597 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   34698       58597 :                const details::operator_type o0 = vov->operation();
   34699       58597 :                const details::operator_type o1 = operation;
   34700             : 
   34701       58597 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   34702             : 
   34703       58597 :                expression_node_ptr result = error_node();
   34704             : 
   34705       58597 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   34706             :                {
   34707             :                   // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
   34708       58597 :                   if ((details::e_div == o0) && (details::e_div == o1))
   34709             :                   {
   34710             :                      const bool synthesis_result =
   34711             :                         synthesize_sf3ext_expression::
   34712        8225 :                            template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
   34713             : 
   34714             :                      exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
   34715             : 
   34716        8225 :                      return (synthesis_result) ? result : error_node();
   34717             :                   }
   34718             :                }
   34719             : 
   34720             :                const bool synthesis_result =
   34721             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
   34722       50372 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
   34723             : 
   34724       50372 :                if (synthesis_result)
   34725       49577 :                   return result;
   34726             : 
   34727         795 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   34728         795 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   34729             : 
   34730         795 :                if (!expr_gen.valid_operator(o0,f0))
   34731           0 :                   return error_node();
   34732         795 :                else if (!expr_gen.valid_operator(o1,f1))
   34733           0 :                   return error_node();
   34734             :                else
   34735         795 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
   34736             :             }
   34737             : 
   34738       50372 :             static inline std::string id(expression_generator<Type>& expr_gen,
   34739             :                                          const details::operator_type o0,
   34740             :                                          const details::operator_type o1)
   34741             :             {
   34742      100744 :                return details::build_string()
   34743      100744 :                   << "(t" << expr_gen.to_str(o0)
   34744      100744 :                   << "t)" << expr_gen.to_str(o1)
   34745      100744 :                   << "t";
   34746             :             }
   34747             :          };
   34748             : 
   34749             :          struct synthesize_vovov_expression1
   34750             :          {
   34751             :             typedef typename vovov_t::type1 node_type;
   34752             :             typedef typename vovov_t::sf3_type sf3_type;
   34753             : 
   34754       21729 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34755             :                                                       const details::operator_type& operation,
   34756             :                                                       expression_node_ptr (&branch)[2])
   34757             :             {
   34758             :                // (v0) o0 (v1 o1 v2)
   34759       21729 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   34760       21729 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   34761       21729 :                const Type& v1 = vov->v0();
   34762       21729 :                const Type& v2 = vov->v1();
   34763       21729 :                const details::operator_type o0 = operation;
   34764       21729 :                const details::operator_type o1 = vov->operation();
   34765             : 
   34766       21729 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   34767             : 
   34768       21729 :                expression_node_ptr result = error_node();
   34769             : 
   34770       21729 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   34771             :                {
   34772             :                   // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
   34773       21729 :                   if ((details::e_div == o0) && (details::e_div == o1))
   34774             :                   {
   34775             :                      const bool synthesis_result =
   34776             :                         synthesize_sf3ext_expression::
   34777        1190 :                            template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
   34778             : 
   34779             :                      exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
   34780             : 
   34781        1190 :                      return (synthesis_result) ? result : error_node();
   34782             :                   }
   34783             :                }
   34784             : 
   34785             :                const bool synthesis_result =
   34786             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
   34787       20539 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
   34788             : 
   34789       20539 :                if (synthesis_result)
   34790       20409 :                   return result;
   34791             : 
   34792         130 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   34793         130 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   34794             : 
   34795         130 :                if (!expr_gen.valid_operator(o0,f0))
   34796           0 :                   return error_node();
   34797         130 :                else if (!expr_gen.valid_operator(o1,f1))
   34798           0 :                   return error_node();
   34799             :                else
   34800         130 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
   34801             :             }
   34802             : 
   34803       20539 :             static inline std::string id(expression_generator<Type>& expr_gen,
   34804             :                                          const details::operator_type o0,
   34805             :                                          const details::operator_type o1)
   34806             :             {
   34807       41078 :                return details::build_string()
   34808       41078 :                   << "t"  << expr_gen.to_str(o0)
   34809       41078 :                   << "(t" << expr_gen.to_str(o1)
   34810       41078 :                   << "t)";
   34811             :             }
   34812             :          };
   34813             : 
   34814             :          struct synthesize_vovoc_expression0
   34815             :          {
   34816             :             typedef typename vovoc_t::type0 node_type;
   34817             :             typedef typename vovoc_t::sf3_type sf3_type;
   34818             : 
   34819       47456 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34820             :                                                       const details::operator_type& operation,
   34821             :                                                       expression_node_ptr (&branch)[2])
   34822             :             {
   34823             :                // (v0 o0 v1) o1 (c)
   34824       47456 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   34825       47456 :                const Type& v0 = vov->v0();
   34826       47456 :                const Type& v1 = vov->v1();
   34827       47456 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   34828       47456 :                const details::operator_type o0 = vov->operation();
   34829       47456 :                const details::operator_type o1 = operation;
   34830             : 
   34831       47456 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   34832       47456 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   34833             : 
   34834       47456 :                expression_node_ptr result = error_node();
   34835             : 
   34836       47456 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   34837             :                {
   34838             :                   // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
   34839       47456 :                   if ((details::e_div == o0) && (details::e_div == o1))
   34840             :                   {
   34841             :                      const bool synthesis_result =
   34842             :                         synthesize_sf3ext_expression::
   34843        6665 :                            template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
   34844             : 
   34845             :                      exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
   34846             : 
   34847        6665 :                      return (synthesis_result) ? result : error_node();
   34848             :                   }
   34849             :                }
   34850             : 
   34851             :                const bool synthesis_result =
   34852             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
   34853       40791 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
   34854             : 
   34855       40791 :                if (synthesis_result)
   34856       40027 :                   return result;
   34857             : 
   34858         764 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   34859         764 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   34860             : 
   34861         764 :                if (!expr_gen.valid_operator(o0,f0))
   34862           0 :                   return error_node();
   34863         764 :                else if (!expr_gen.valid_operator(o1,f1))
   34864           0 :                   return error_node();
   34865             :                else
   34866         764 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
   34867             :             }
   34868             : 
   34869       40791 :             static inline std::string id(expression_generator<Type>& expr_gen,
   34870             :                                          const details::operator_type o0,
   34871             :                                          const details::operator_type o1)
   34872             :             {
   34873       81582 :                return details::build_string()
   34874       81582 :                   << "(t" << expr_gen.to_str(o0)
   34875       81582 :                   << "t)" << expr_gen.to_str(o1)
   34876       81582 :                   << "t";
   34877             :             }
   34878             :          };
   34879             : 
   34880             :          struct synthesize_vovoc_expression1
   34881             :          {
   34882             :             typedef typename vovoc_t::type1 node_type;
   34883             :             typedef typename vovoc_t::sf3_type sf3_type;
   34884             : 
   34885       24765 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34886             :                                                       const details::operator_type& operation,
   34887             :                                                       expression_node_ptr (&branch)[2])
   34888             :             {
   34889             :                // (v0) o0 (v1 o1 c)
   34890       24765 :                const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
   34891       24765 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   34892       24765 :                const Type& v1 = voc->v();
   34893       24765 :                const Type   c = voc->c();
   34894       24765 :                const details::operator_type o0 = operation;
   34895       24765 :                const details::operator_type o1 = voc->operation();
   34896             : 
   34897       24765 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   34898             : 
   34899       24765 :                expression_node_ptr result = error_node();
   34900             : 
   34901       24765 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   34902             :                {
   34903             :                   // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
   34904       24765 :                   if ((details::e_div == o0) && (details::e_div == o1))
   34905             :                   {
   34906             :                      const bool synthesis_result =
   34907             :                         synthesize_sf3ext_expression::
   34908        1365 :                            template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
   34909             : 
   34910             :                      exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
   34911             : 
   34912        1365 :                      return (synthesis_result) ? result : error_node();
   34913             :                   }
   34914             :                }
   34915             : 
   34916             :                const bool synthesis_result =
   34917             :                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
   34918       23400 :                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
   34919             : 
   34920       23400 :                if (synthesis_result)
   34921       23190 :                   return result;
   34922             : 
   34923         210 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   34924         210 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   34925             : 
   34926         210 :                if (!expr_gen.valid_operator(o0,f0))
   34927           0 :                   return error_node();
   34928         210 :                else if (!expr_gen.valid_operator(o1,f1))
   34929           0 :                   return error_node();
   34930             :                else
   34931         210 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
   34932             :             }
   34933             : 
   34934       23400 :             static inline std::string id(expression_generator<Type>& expr_gen,
   34935             :                                          const details::operator_type o0,
   34936             :                                          const details::operator_type o1)
   34937             :             {
   34938       46800 :                return details::build_string()
   34939       46800 :                   << "t"  << expr_gen.to_str(o0)
   34940       46800 :                   << "(t" << expr_gen.to_str(o1)
   34941       46800 :                   << "t)";
   34942             :             }
   34943             :          };
   34944             : 
   34945             :          struct synthesize_vocov_expression0
   34946             :          {
   34947             :             typedef typename vocov_t::type0 node_type;
   34948             :             typedef typename vocov_t::sf3_type sf3_type;
   34949             : 
   34950       52929 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   34951             :                                                       const details::operator_type& operation,
   34952             :                                                       expression_node_ptr (&branch)[2])
   34953             :             {
   34954             :                // (v0 o0 c) o1 (v1)
   34955       52929 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   34956       52929 :                const Type& v0 = voc->v();
   34957       52929 :                const Type   c = voc->c();
   34958       52929 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   34959       52929 :                const details::operator_type o0 = voc->operation();
   34960       52929 :                const details::operator_type o1 = operation;
   34961             : 
   34962       52929 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   34963             : 
   34964       52929 :                expression_node_ptr result = error_node();
   34965             : 
   34966       52929 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   34967             :                {
   34968             :                   // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
   34969       52929 :                   if ((details::e_div == o0) && (details::e_div == o1))
   34970             :                   {
   34971             :                      const bool synthesis_result =
   34972             :                         synthesize_sf3ext_expression::
   34973        7360 :                            template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
   34974             : 
   34975             :                      exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
   34976             : 
   34977        7360 :                      return (synthesis_result) ? result : error_node();
   34978             :                   }
   34979             :                }
   34980             : 
   34981             :                const bool synthesis_result =
   34982             :                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
   34983       45569 :                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
   34984             : 
   34985       45569 :                if (synthesis_result)
   34986       45539 :                   return result;
   34987             : 
   34988          30 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   34989          30 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   34990             : 
   34991          30 :                if (!expr_gen.valid_operator(o0,f0))
   34992           0 :                   return error_node();
   34993          30 :                else if (!expr_gen.valid_operator(o1,f1))
   34994           0 :                   return error_node();
   34995             :                else
   34996          30 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
   34997             :             }
   34998             : 
   34999       45569 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35000             :                                          const details::operator_type o0,
   35001             :                                          const details::operator_type o1)
   35002             :             {
   35003       91138 :                return details::build_string()
   35004       91138 :                   << "(t" << expr_gen.to_str(o0)
   35005       91138 :                   << "t)" << expr_gen.to_str(o1)
   35006       91138 :                   << "t";
   35007             :             }
   35008             :          };
   35009             : 
   35010             :          struct synthesize_vocov_expression1
   35011             :          {
   35012             :             typedef typename vocov_t::type1 node_type;
   35013             :             typedef typename vocov_t::sf3_type sf3_type;
   35014             : 
   35015       28391 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35016             :                                                       const details::operator_type& operation,
   35017             :                                                       expression_node_ptr (&branch)[2])
   35018             :             {
   35019             :                // (v0) o0 (c o1 v1)
   35020       28391 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   35021       28391 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   35022       28391 :                const Type   c = cov->c();
   35023       28391 :                const Type& v1 = cov->v();
   35024       28391 :                const details::operator_type o0 = operation;
   35025       28391 :                const details::operator_type o1 = cov->operation();
   35026             : 
   35027       28391 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35028             : 
   35029       28391 :                expression_node_ptr result = error_node();
   35030             : 
   35031       28391 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35032             :                {
   35033             :                   // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
   35034       28391 :                   if ((details::e_div == o0) && (details::e_div == o1))
   35035             :                   {
   35036             :                      const bool synthesis_result =
   35037             :                         synthesize_sf3ext_expression::
   35038        1565 :                            template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
   35039             : 
   35040             :                      exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
   35041             : 
   35042        1565 :                      return (synthesis_result) ? result : error_node();
   35043             :                   }
   35044             :                }
   35045             : 
   35046             :                const bool synthesis_result =
   35047             :                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
   35048       26826 :                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
   35049             : 
   35050       26826 :                if (synthesis_result)
   35051       26765 :                   return result;
   35052             : 
   35053          61 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35054          61 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35055             : 
   35056          61 :                if (!expr_gen.valid_operator(o0,f0))
   35057           0 :                   return error_node();
   35058          61 :                else if (!expr_gen.valid_operator(o1,f1))
   35059           0 :                   return error_node();
   35060             :                else
   35061          61 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
   35062             :             }
   35063             : 
   35064       26826 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35065             :                                          const details::operator_type o0,
   35066             :                                          const details::operator_type o1)
   35067             :             {
   35068       53652 :                return details::build_string()
   35069       53652 :                   << "t"  << expr_gen.to_str(o0)
   35070       53652 :                   << "(t" << expr_gen.to_str(o1)
   35071       53652 :                   << "t)";
   35072             :             }
   35073             :          };
   35074             : 
   35075             :          struct synthesize_covov_expression0
   35076             :          {
   35077             :             typedef typename covov_t::type0 node_type;
   35078             :             typedef typename covov_t::sf3_type sf3_type;
   35079             : 
   35080       57436 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35081             :                                                       const details::operator_type& operation,
   35082             :                                                       expression_node_ptr (&branch)[2])
   35083             :             {
   35084             :                // (c o0 v0) o1 (v1)
   35085       57436 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   35086       57436 :                const Type   c = cov->c();
   35087       57436 :                const Type& v0 = cov->v();
   35088       57436 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   35089       57436 :                const details::operator_type o0 = cov->operation();
   35090       57436 :                const details::operator_type o1 = operation;
   35091             : 
   35092       57436 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35093             : 
   35094       57436 :                expression_node_ptr result = error_node();
   35095             : 
   35096       57436 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35097             :                {
   35098             :                   // (c / v0) / v1 --> (covov) c / (v0 * v1)
   35099       57436 :                   if ((details::e_div == o0) && (details::e_div == o1))
   35100             :                   {
   35101             :                      const bool synthesis_result =
   35102             :                         synthesize_sf3ext_expression::
   35103        8375 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
   35104             : 
   35105             :                      exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
   35106             : 
   35107        8375 :                      return (synthesis_result) ? result : error_node();
   35108             :                   }
   35109             :                }
   35110             : 
   35111             :                const bool synthesis_result =
   35112             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
   35113       49061 :                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
   35114             : 
   35115       49061 :                if (synthesis_result)
   35116       49061 :                   return result;
   35117             : 
   35118           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35119           0 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35120             : 
   35121           0 :                if (!expr_gen.valid_operator(o0,f0))
   35122           0 :                   return error_node();
   35123           0 :                else if (!expr_gen.valid_operator(o1,f1))
   35124           0 :                   return error_node();
   35125             :                else
   35126           0 :                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
   35127             :             }
   35128             : 
   35129       49061 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35130             :                                          const details::operator_type o0,
   35131             :                                          const details::operator_type o1)
   35132             :             {
   35133       98122 :                return details::build_string()
   35134       98122 :                   << "(t" << expr_gen.to_str(o0)
   35135       98122 :                   << "t)" << expr_gen.to_str(o1)
   35136       98122 :                   << "t";
   35137             :             }
   35138             :          };
   35139             : 
   35140             :          struct synthesize_covov_expression1
   35141             :          {
   35142             :             typedef typename covov_t::type1 node_type;
   35143             :             typedef typename covov_t::sf3_type sf3_type;
   35144             : 
   35145       35209 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35146             :                                                       const details::operator_type& operation,
   35147             :                                                       expression_node_ptr (&branch)[2])
   35148             :             {
   35149             :                // (c) o0 (v0 o1 v1)
   35150       35209 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   35151       35209 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   35152       35209 :                const Type& v0 = vov->v0();
   35153       35209 :                const Type& v1 = vov->v1();
   35154       35209 :                const details::operator_type o0 = operation;
   35155       35209 :                const details::operator_type o1 = vov->operation();
   35156             : 
   35157       35209 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35158       35209 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35159             : 
   35160       35209 :                expression_node_ptr result = error_node();
   35161             : 
   35162       35209 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35163             :                {
   35164             :                   // c / (v0 / v1) --> (covov) (c * v1) / v0
   35165       35209 :                   if ((details::e_div == o0) && (details::e_div == o1))
   35166             :                   {
   35167             :                      const bool synthesis_result =
   35168             :                         synthesize_sf3ext_expression::
   35169        1325 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
   35170             : 
   35171             :                      exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
   35172             : 
   35173        1325 :                      return (synthesis_result) ? result : error_node();
   35174             :                   }
   35175             :                }
   35176             : 
   35177             :                const bool synthesis_result =
   35178             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
   35179       33884 :                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
   35180             : 
   35181       33884 :                if (synthesis_result)
   35182       33823 :                   return result;
   35183             : 
   35184          61 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35185          61 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35186             : 
   35187          61 :                if (!expr_gen.valid_operator(o0,f0))
   35188           0 :                   return error_node();
   35189          61 :                else if (!expr_gen.valid_operator(o1,f1))
   35190           0 :                   return error_node();
   35191             :                else
   35192          61 :                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
   35193             :             }
   35194             : 
   35195       33884 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35196             :                                          const details::operator_type o0,
   35197             :                                          const details::operator_type o1)
   35198             :             {
   35199       67768 :                return details::build_string()
   35200       67768 :                   << "t"  << expr_gen.to_str(o0)
   35201       67768 :                   << "(t" << expr_gen.to_str(o1)
   35202       67768 :                   << "t)";
   35203             :             }
   35204             :          };
   35205             : 
   35206             :          struct synthesize_covoc_expression0
   35207             :          {
   35208             :             typedef typename covoc_t::type0 node_type;
   35209             :             typedef typename covoc_t::sf3_type sf3_type;
   35210             : 
   35211       40414 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35212             :                                                       const details::operator_type& operation,
   35213             :                                                       expression_node_ptr (&branch)[2])
   35214             :             {
   35215             :                // (c0 o0 v) o1 (c1)
   35216       40414 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   35217       40414 :                const Type  c0 = cov->c();
   35218       40414 :                const Type&  v = cov->v();
   35219       40414 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   35220       40414 :                const details::operator_type o0 = cov->operation();
   35221       40414 :                const details::operator_type o1 = operation;
   35222             : 
   35223       40414 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35224       40414 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35225             : 
   35226       40414 :                expression_node_ptr result = error_node();
   35227             : 
   35228       40414 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35229             :                {
   35230             :                   // (c0 + v) + c1 --> (cov) (c0 + c1) + v
   35231       40414 :                   if ((details::e_add == o0) && (details::e_add == o1))
   35232             :                   {
   35233             :                      exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
   35234             : 
   35235        2687 :                      return expr_gen.node_allocator_->
   35236        2687 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
   35237             :                   }
   35238             :                   // (c0 + v) - c1 --> (cov) (c0 - c1) + v
   35239       37727 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   35240             :                   {
   35241             :                      exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
   35242             : 
   35243        2166 :                      return expr_gen.node_allocator_->
   35244        2166 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
   35245             :                   }
   35246             :                   // (c0 - v) + c1 --> (cov) (c0 + c1) - v
   35247       35561 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   35248             :                   {
   35249             :                      exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
   35250             : 
   35251        1720 :                      return expr_gen.node_allocator_->
   35252        1720 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
   35253             :                   }
   35254             :                   // (c0 - v) - c1 --> (cov) (c0 - c1) - v
   35255       33841 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   35256             :                   {
   35257             :                      exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
   35258             : 
   35259        1951 :                      return expr_gen.node_allocator_->
   35260        1951 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
   35261             :                   }
   35262             :                   // (c0 * v) * c1 --> (cov) (c0 * c1) * v
   35263       31890 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   35264             :                   {
   35265             :                      exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
   35266             : 
   35267        3335 :                      return expr_gen.node_allocator_->
   35268        3335 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
   35269             :                   }
   35270             :                   // (c0 * v) / c1 --> (cov) (c0 / c1) * v
   35271       28555 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   35272             :                   {
   35273             :                      exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
   35274             : 
   35275        3057 :                      return expr_gen.node_allocator_->
   35276        3057 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
   35277             :                   }
   35278             :                   // (c0 / v) * c1 --> (cov) (c0 * c1) / v
   35279       25498 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   35280             :                   {
   35281             :                      exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
   35282             : 
   35283        3250 :                      return expr_gen.node_allocator_->
   35284        3250 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
   35285             :                   }
   35286             :                   // (c0 / v) / c1 --> (cov) (c0 / c1) / v
   35287       22248 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   35288             :                   {
   35289             :                      exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
   35290             : 
   35291        3805 :                      return expr_gen.node_allocator_->
   35292        3805 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
   35293             :                   }
   35294             :                }
   35295             : 
   35296             :                const bool synthesis_result =
   35297             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
   35298       18443 :                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
   35299             : 
   35300       18443 :                if (synthesis_result)
   35301       16833 :                   return result;
   35302             : 
   35303        1610 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35304        1610 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35305             : 
   35306        1610 :                if (!expr_gen.valid_operator(o0,f0))
   35307           0 :                   return error_node();
   35308        1610 :                else if (!expr_gen.valid_operator(o1,f1))
   35309           0 :                   return error_node();
   35310             :                else
   35311        1610 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
   35312             :             }
   35313             : 
   35314       18443 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35315             :                                          const details::operator_type o0,
   35316             :                                          const details::operator_type o1)
   35317             :             {
   35318       36886 :                return details::build_string()
   35319       36886 :                   << "(t" << expr_gen.to_str(o0)
   35320       36886 :                   << "t)" << expr_gen.to_str(o1)
   35321       36886 :                   << "t";
   35322             :             }
   35323             :          };
   35324             : 
   35325             :          struct synthesize_covoc_expression1
   35326             :          {
   35327             :             typedef typename covoc_t::type1 node_type;
   35328             :             typedef typename covoc_t::sf3_type sf3_type;
   35329             : 
   35330       14236 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35331             :                                                       const details::operator_type& operation,
   35332             :                                                       expression_node_ptr (&branch)[2])
   35333             :             {
   35334             :                // (c0) o0 (v o1 c1)
   35335       14236 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
   35336       14236 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   35337       14236 :                const Type&  v = voc->v();
   35338       14236 :                const Type  c1 = voc->c();
   35339       14236 :                const details::operator_type o0 = operation;
   35340       14236 :                const details::operator_type o1 = voc->operation();
   35341             : 
   35342       14236 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35343       14236 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35344             : 
   35345       14236 :                expression_node_ptr result = error_node();
   35346             : 
   35347       14236 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35348             :                {
   35349             :                   // (c0) + (v + c1) --> (cov) (c0 + c1) + v
   35350       14236 :                   if ((details::e_add == o0) && (details::e_add == o1))
   35351             :                   {
   35352             :                      exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
   35353             : 
   35354         845 :                      return expr_gen.node_allocator_->
   35355         845 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
   35356             :                   }
   35357             :                   // (c0) + (v - c1) --> (cov) (c0 - c1) + v
   35358       13391 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   35359             :                   {
   35360             :                      exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
   35361             : 
   35362         825 :                      return expr_gen.node_allocator_->
   35363         825 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
   35364             :                   }
   35365             :                   // (c0) - (v + c1) --> (cov) (c0 - c1) - v
   35366       12566 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   35367             :                   {
   35368             :                      exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
   35369             : 
   35370         815 :                      return expr_gen.node_allocator_->
   35371         815 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
   35372             :                   }
   35373             :                   // (c0) - (v - c1) --> (cov) (c0 + c1) - v
   35374       11751 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   35375             :                   {
   35376             :                      exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
   35377             : 
   35378         795 :                      return expr_gen.node_allocator_->
   35379         795 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
   35380             :                   }
   35381             :                   // (c0) * (v * c1) --> (voc) v * (c0 * c1)
   35382       10956 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   35383             :                   {
   35384             :                      exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
   35385             : 
   35386         835 :                      return expr_gen.node_allocator_->
   35387         835 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
   35388             :                   }
   35389             :                   // (c0) * (v / c1) --> (cov) (c0 / c1) * v
   35390       10121 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   35391             :                   {
   35392             :                      exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
   35393             : 
   35394         825 :                      return expr_gen.node_allocator_->
   35395         825 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
   35396             :                   }
   35397             :                   // (c0) / (v * c1) --> (cov) (c0 / c1) / v
   35398        9296 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   35399             :                   {
   35400             :                      exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
   35401             : 
   35402         805 :                      return expr_gen.node_allocator_->
   35403         805 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
   35404             :                   }
   35405             :                   // (c0) / (v / c1) --> (cov) (c0 * c1) / v
   35406        8491 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   35407             :                   {
   35408             :                      exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
   35409             : 
   35410         795 :                      return expr_gen.node_allocator_->
   35411         795 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
   35412             :                   }
   35413             :                }
   35414             : 
   35415             :                const bool synthesis_result =
   35416             :                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
   35417        7696 :                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
   35418             : 
   35419        7696 :                if (synthesis_result)
   35420        7615 :                   return result;
   35421             : 
   35422          81 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35423          81 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35424             : 
   35425          81 :                if (!expr_gen.valid_operator(o0,f0))
   35426           0 :                   return error_node();
   35427          81 :                else if (!expr_gen.valid_operator(o1,f1))
   35428           0 :                   return error_node();
   35429             :                else
   35430          81 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
   35431             :             }
   35432             : 
   35433        7696 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35434             :                                          const details::operator_type o0,
   35435             :                                          const details::operator_type o1)
   35436             :             {
   35437       15392 :                return details::build_string()
   35438       15392 :                   << "t"  << expr_gen.to_str(o0)
   35439       15392 :                   << "(t" << expr_gen.to_str(o1)
   35440       15392 :                   << "t)";
   35441             :             }
   35442             :          };
   35443             : 
   35444             :          struct synthesize_cocov_expression0
   35445             :          {
   35446             :             typedef typename cocov_t::type0 node_type;
   35447             :             static inline expression_node_ptr process(expression_generator<Type>&,
   35448             :                                                       const details::operator_type&,
   35449             :                                                       expression_node_ptr (&)[2])
   35450             :             {
   35451             :                // (c0 o0 c1) o1 (v) - Not possible.
   35452             :                return error_node();
   35453             :             }
   35454             :          };
   35455             : 
   35456             :          struct synthesize_cocov_expression1
   35457             :          {
   35458             :             typedef typename cocov_t::type1 node_type;
   35459             :             typedef typename cocov_t::sf3_type sf3_type;
   35460             : 
   35461       15880 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35462             :                                                       const details::operator_type& operation,
   35463             :                                                       expression_node_ptr (&branch)[2])
   35464             :             {
   35465             :                // (c0) o0 (c1 o1 v)
   35466       15880 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   35467       15880 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   35468       15880 :                const Type  c1 = cov->c();
   35469       15880 :                const Type&  v = cov->v();
   35470       15880 :                const details::operator_type o0 = operation;
   35471       15880 :                const details::operator_type o1 = cov->operation();
   35472             : 
   35473       15880 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35474       15880 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35475             : 
   35476       15880 :                expression_node_ptr result = error_node();
   35477             : 
   35478       15880 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35479             :                {
   35480             :                   // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
   35481       15880 :                   if ((details::e_add == o0) && (details::e_add == o1))
   35482             :                   {
   35483             :                      exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
   35484             : 
   35485        1005 :                      return expr_gen.node_allocator_->
   35486        1005 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
   35487             :                   }
   35488             :                   // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
   35489       14875 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   35490             :                   {
   35491             :                      exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
   35492             : 
   35493         985 :                      return expr_gen.node_allocator_->
   35494         985 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
   35495             :                   }
   35496             :                   // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
   35497       13890 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   35498             :                   {
   35499             :                      exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
   35500             : 
   35501         970 :                      return expr_gen.node_allocator_->
   35502         970 :                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
   35503             :                   }
   35504             :                   // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
   35505       12920 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   35506             :                   {
   35507             :                      exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
   35508             : 
   35509         970 :                      return expr_gen.node_allocator_->
   35510         970 :                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
   35511             :                   }
   35512             :                   // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
   35513       11950 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   35514             :                   {
   35515             :                      exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
   35516             : 
   35517         835 :                      return expr_gen.node_allocator_->
   35518         835 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
   35519             :                   }
   35520             :                   // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
   35521       11115 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   35522             :                   {
   35523             :                      exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
   35524             : 
   35525         835 :                      return expr_gen.node_allocator_->
   35526         835 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
   35527             :                   }
   35528             :                   // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
   35529       10280 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   35530             :                   {
   35531             :                      exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
   35532             : 
   35533         800 :                      return expr_gen.node_allocator_->
   35534         800 :                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
   35535             :                   }
   35536             :                   // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
   35537        9480 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   35538             :                   {
   35539             :                      exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
   35540             : 
   35541         810 :                      return expr_gen.node_allocator_->
   35542         810 :                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
   35543             :                   }
   35544             :                }
   35545             : 
   35546             :                const bool synthesis_result =
   35547             :                   synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
   35548        8670 :                      (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
   35549             : 
   35550        8670 :                if (synthesis_result)
   35551        8607 :                   return result;
   35552             : 
   35553          63 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35554          63 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35555             : 
   35556          63 :                if (!expr_gen.valid_operator(o0,f0))
   35557           0 :                   return error_node();
   35558          63 :                else if (!expr_gen.valid_operator(o1,f1))
   35559           0 :                   return error_node();
   35560             :                else
   35561          63 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
   35562             :             }
   35563             : 
   35564        8670 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35565             :                                          const details::operator_type o0,
   35566             :                                          const details::operator_type o1)
   35567             :             {
   35568       17340 :                return details::build_string()
   35569       17340 :                   << "t"  << expr_gen.to_str(o0)
   35570       17340 :                   << "(t" << expr_gen.to_str(o1)
   35571       17340 :                   << "t)";
   35572             :             }
   35573             :          };
   35574             : 
   35575             :          struct synthesize_vococ_expression0
   35576             :          {
   35577             :             typedef typename vococ_t::type0 node_type;
   35578             :             typedef typename vococ_t::sf3_type sf3_type;
   35579             : 
   35580       28394 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35581             :                                                       const details::operator_type& operation,
   35582             :                                                       expression_node_ptr (&branch)[2])
   35583             :             {
   35584             :                // (v o0 c0) o1 (c1)
   35585       28394 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   35586       28394 :                const Type&  v = voc->v();
   35587       28394 :                const Type& c0 = voc->c();
   35588       28394 :                const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   35589       28394 :                const details::operator_type o0 = voc->operation();
   35590       28394 :                const details::operator_type o1 = operation;
   35591             : 
   35592       28394 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35593       28394 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35594             : 
   35595       28394 :                expression_node_ptr result = error_node();
   35596             : 
   35597       28394 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35598             :                {
   35599             :                   // (v + c0) + c1 --> (voc) v + (c0 + c1)
   35600       28394 :                   if ((details::e_add == o0) && (details::e_add == o1))
   35601             :                   {
   35602             :                      exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
   35603             : 
   35604        2390 :                      return expr_gen.node_allocator_->
   35605        2390 :                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
   35606             :                   }
   35607             :                   // (v + c0) - c1 --> (voc) v + (c0 - c1)
   35608       26004 :                   else if ((details::e_add == o0) && (details::e_sub == o1))
   35609             :                   {
   35610             :                      exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
   35611             : 
   35612        2025 :                      return expr_gen.node_allocator_->
   35613        2025 :                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
   35614             :                   }
   35615             :                   // (v - c0) + c1 --> (voc) v - (c0 + c1)
   35616       23979 :                   else if ((details::e_sub == o0) && (details::e_add == o1))
   35617             :                   {
   35618             :                      exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
   35619             : 
   35620        1770 :                      return expr_gen.node_allocator_->
   35621        1770 :                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
   35622             :                   }
   35623             :                   // (v - c0) - c1 --> (voc) v - (c0 + c1)
   35624       22209 :                   else if ((details::e_sub == o0) && (details::e_sub == o1))
   35625             :                   {
   35626             :                      exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
   35627             : 
   35628        1705 :                      return expr_gen.node_allocator_->
   35629        1705 :                                template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
   35630             :                   }
   35631             :                   // (v * c0) * c1 --> (voc) v * (c0 * c1)
   35632       20504 :                   else if ((details::e_mul == o0) && (details::e_mul == o1))
   35633             :                   {
   35634             :                      exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
   35635             : 
   35636        2875 :                      return expr_gen.node_allocator_->
   35637        2875 :                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
   35638             :                   }
   35639             :                   // (v * c0) / c1 --> (voc) v * (c0 / c1)
   35640       17629 :                   else if ((details::e_mul == o0) && (details::e_div == o1))
   35641             :                   {
   35642             :                      exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
   35643             : 
   35644        2180 :                      return expr_gen.node_allocator_->
   35645        2180 :                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
   35646             :                   }
   35647             :                   // (v / c0) * c1 --> (voc) v * (c1 / c0)
   35648       15449 :                   else if ((details::e_div == o0) && (details::e_mul == o1))
   35649             :                   {
   35650             :                      exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
   35651             : 
   35652        2686 :                      return expr_gen.node_allocator_->
   35653        2686 :                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
   35654             :                   }
   35655             :                   // (v / c0) / c1 --> (voc) v / (c0 * c1)
   35656       12763 :                   else if ((details::e_div == o0) && (details::e_div == o1))
   35657             :                   {
   35658             :                      exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
   35659             : 
   35660        3110 :                      return expr_gen.node_allocator_->
   35661        3110 :                                template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
   35662             :                   }
   35663             :                   // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
   35664        9653 :                   else if ((details::e_pow == o0) && (details::e_pow == o1))
   35665             :                   {
   35666             :                      exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
   35667             : 
   35668           0 :                      return expr_gen.node_allocator_->
   35669           0 :                                template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
   35670             :                   }
   35671             :                }
   35672             : 
   35673             :                const bool synthesis_result =
   35674             :                   synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
   35675        9653 :                      (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
   35676             : 
   35677        9653 :                if (synthesis_result)
   35678        7543 :                   return result;
   35679             : 
   35680        2110 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35681        2110 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35682             : 
   35683        2110 :                if (!expr_gen.valid_operator(o0,f0))
   35684           0 :                   return error_node();
   35685        2110 :                else if (!expr_gen.valid_operator(o1,f1))
   35686           0 :                   return error_node();
   35687             :                else
   35688        2110 :                   return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
   35689             :             }
   35690             : 
   35691        9653 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35692             :                                          const details::operator_type o0,
   35693             :                                          const details::operator_type o1)
   35694             :             {
   35695       19306 :                return details::build_string()
   35696       19306 :                   << "(t" << expr_gen.to_str(o0)
   35697       19306 :                   << "t)" << expr_gen.to_str(o1)
   35698       19306 :                   << "t";
   35699             :             }
   35700             :          };
   35701             : 
   35702             :          struct synthesize_vococ_expression1
   35703             :          {
   35704             :             typedef typename vococ_t::type0 node_type;
   35705             : 
   35706             :             static inline expression_node_ptr process(expression_generator<Type>&,
   35707             :                                                       const details::operator_type&,
   35708             :                                                       expression_node_ptr (&)[2])
   35709             :             {
   35710             :                // (v) o0 (c0 o1 c1) - Not possible.
   35711             :                exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
   35712             :                return error_node();
   35713             :             }
   35714             :          };
   35715             : 
   35716             :          struct synthesize_vovovov_expression0
   35717             :          {
   35718             :             typedef typename vovovov_t::type0 node_type;
   35719             :             typedef typename vovovov_t::sf4_type sf4_type;
   35720             :             typedef typename node_type::T0 T0;
   35721             :             typedef typename node_type::T1 T1;
   35722             :             typedef typename node_type::T2 T2;
   35723             :             typedef typename node_type::T3 T3;
   35724             : 
   35725        9910 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35726             :                                                       const details::operator_type& operation,
   35727             :                                                       expression_node_ptr (&branch)[2])
   35728             :             {
   35729             :                // (v0 o0 v1) o1 (v2 o2 v3)
   35730        9910 :                const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
   35731        9910 :                const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
   35732        9910 :                const Type& v0 = vov0->v0();
   35733        9910 :                const Type& v1 = vov0->v1();
   35734        9910 :                const Type& v2 = vov1->v0();
   35735        9910 :                const Type& v3 = vov1->v1();
   35736        9910 :                const details::operator_type o0 = vov0->operation();
   35737        9910 :                const details::operator_type o1 = operation;
   35738        9910 :                const details::operator_type o2 = vov1->operation();
   35739             : 
   35740        9910 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35741        9910 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35742             : 
   35743        9910 :                expression_node_ptr result = error_node();
   35744             : 
   35745        9910 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35746             :                {
   35747             :                   // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
   35748        9910 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   35749             :                   {
   35750             :                      const bool synthesis_result =
   35751             :                         synthesize_sf4ext_expression::
   35752          40 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
   35753             : 
   35754             :                      exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
   35755             : 
   35756          40 :                      return (synthesis_result) ? result : error_node();
   35757             :                   }
   35758             :                   // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
   35759        9870 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   35760             :                   {
   35761             :                      const bool synthesis_result =
   35762             :                         synthesize_sf4ext_expression::
   35763          40 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
   35764             : 
   35765             :                      exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
   35766             : 
   35767          40 :                      return (synthesis_result) ? result : error_node();
   35768             :                   }
   35769             :                   // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
   35770        9830 :                   else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
   35771             :                   {
   35772             :                      const bool synthesis_result =
   35773             :                         synthesize_sf4ext_expression::
   35774         115 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
   35775             : 
   35776             :                      exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
   35777             : 
   35778         115 :                      return (synthesis_result) ? result : error_node();
   35779             :                   }
   35780             :                   // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
   35781        9715 :                   else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
   35782             :                   {
   35783             :                      const bool synthesis_result =
   35784             :                         synthesize_sf4ext_expression::
   35785         115 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
   35786             : 
   35787             :                      exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
   35788             : 
   35789         115 :                      return (synthesis_result) ? result : error_node();
   35790             :                   }
   35791             :                   // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
   35792        9600 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   35793             :                   {
   35794             :                      const bool synthesis_result =
   35795             :                         synthesize_sf4ext_expression::
   35796          40 :                            template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
   35797             : 
   35798             :                      exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
   35799             : 
   35800          40 :                      return (synthesis_result) ? result : error_node();
   35801             :                   }
   35802             :                }
   35803             : 
   35804             :                const bool synthesis_result =
   35805             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   35806        9560 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   35807             : 
   35808        9560 :                if (synthesis_result)
   35809        7806 :                   return result;
   35810             : 
   35811        1754 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35812        1754 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35813        1754 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   35814             : 
   35815        1754 :                if (!expr_gen.valid_operator(o0,f0))
   35816           0 :                   return error_node();
   35817        1754 :                else if (!expr_gen.valid_operator(o1,f1))
   35818           0 :                   return error_node();
   35819        1754 :                else if (!expr_gen.valid_operator(o2,f2))
   35820           0 :                   return error_node();
   35821             :                else
   35822        1754 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   35823             :             }
   35824             : 
   35825        9560 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35826             :                                          const details::operator_type o0,
   35827             :                                          const details::operator_type o1,
   35828             :                                          const details::operator_type o2)
   35829             :             {
   35830       19120 :                return details::build_string()
   35831       19120 :                   << "(t" << expr_gen.to_str(o0)
   35832       19120 :                   << "t)" << expr_gen.to_str(o1)
   35833       19120 :                   << "(t" << expr_gen.to_str(o2)
   35834       19120 :                   << "t)";
   35835             :             }
   35836             :          };
   35837             : 
   35838             :          struct synthesize_vovovoc_expression0
   35839             :          {
   35840             :             typedef typename vovovoc_t::type0 node_type;
   35841             :             typedef typename vovovoc_t::sf4_type sf4_type;
   35842             :             typedef typename node_type::T0 T0;
   35843             :             typedef typename node_type::T1 T1;
   35844             :             typedef typename node_type::T2 T2;
   35845             :             typedef typename node_type::T3 T3;
   35846             : 
   35847        7630 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35848             :                                                       const details::operator_type& operation,
   35849             :                                                       expression_node_ptr (&branch)[2])
   35850             :             {
   35851             :                // (v0 o0 v1) o1 (v2 o2 c)
   35852        7630 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   35853        7630 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
   35854        7630 :                const Type& v0 = vov->v0();
   35855        7630 :                const Type& v1 = vov->v1();
   35856        7630 :                const Type& v2 = voc->v ();
   35857        7630 :                const Type   c = voc->c ();
   35858        7630 :                const details::operator_type o0 = vov->operation();
   35859        7630 :                const details::operator_type o1 = operation;
   35860        7630 :                const details::operator_type o2 = voc->operation();
   35861             : 
   35862        7630 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35863        7630 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35864             : 
   35865        7630 :                expression_node_ptr result = error_node();
   35866             : 
   35867        7630 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35868             :                {
   35869             :                   // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
   35870        7630 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   35871             :                   {
   35872             :                      const bool synthesis_result =
   35873             :                         synthesize_sf4ext_expression::
   35874          40 :                            template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
   35875             : 
   35876             :                      exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
   35877             : 
   35878          40 :                      return (synthesis_result) ? result : error_node();
   35879             :                   }
   35880             :                   // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
   35881        7590 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   35882             :                   {
   35883             :                      const bool synthesis_result =
   35884             :                         synthesize_sf4ext_expression::
   35885          40 :                            template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
   35886             : 
   35887             :                      exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
   35888             : 
   35889          40 :                      return (synthesis_result) ? result : error_node();
   35890             :                   }
   35891             :                }
   35892             : 
   35893             :                const bool synthesis_result =
   35894             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   35895        7550 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   35896             : 
   35897        7550 :                if (synthesis_result)
   35898        7010 :                   return result;
   35899             : 
   35900         540 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35901         540 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35902         540 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   35903             : 
   35904         540 :                if (!expr_gen.valid_operator(o0,f0))
   35905           0 :                   return error_node();
   35906         540 :                else if (!expr_gen.valid_operator(o1,f1))
   35907           0 :                   return error_node();
   35908         540 :                else if (!expr_gen.valid_operator(o2,f2))
   35909           0 :                   return error_node();
   35910             :                else
   35911         540 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   35912             :             }
   35913             : 
   35914        7550 :             static inline std::string id(expression_generator<Type>& expr_gen,
   35915             :                                          const details::operator_type o0,
   35916             :                                          const details::operator_type o1,
   35917             :                                          const details::operator_type o2)
   35918             :             {
   35919       15100 :                return details::build_string()
   35920       15100 :                   << "(t" << expr_gen.to_str(o0)
   35921       15100 :                   << "t)" << expr_gen.to_str(o1)
   35922       15100 :                   << "(t" << expr_gen.to_str(o2)
   35923       15100 :                   << "t)";
   35924             :             }
   35925             :          };
   35926             : 
   35927             :          struct synthesize_vovocov_expression0
   35928             :          {
   35929             :             typedef typename vovocov_t::type0 node_type;
   35930             :             typedef typename vovocov_t::sf4_type sf4_type;
   35931             :             typedef typename node_type::T0 T0;
   35932             :             typedef typename node_type::T1 T1;
   35933             :             typedef typename node_type::T2 T2;
   35934             :             typedef typename node_type::T3 T3;
   35935             : 
   35936       11567 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   35937             :                                                       const details::operator_type& operation,
   35938             :                                                       expression_node_ptr (&branch)[2])
   35939             :             {
   35940             :                // (v0 o0 v1) o1 (c o2 v2)
   35941       11567 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
   35942       11567 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   35943       11567 :                const Type& v0 = vov->v0();
   35944       11567 :                const Type& v1 = vov->v1();
   35945       11567 :                const Type& v2 = cov->v ();
   35946       11567 :                const Type   c = cov->c ();
   35947       11567 :                const details::operator_type o0 = vov->operation();
   35948       11567 :                const details::operator_type o1 = operation;
   35949       11567 :                const details::operator_type o2 = cov->operation();
   35950             : 
   35951       11567 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   35952       11567 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   35953             : 
   35954       11567 :                expression_node_ptr result = error_node();
   35955             : 
   35956       11567 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   35957             :                {
   35958             :                   // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
   35959       11567 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   35960             :                   {
   35961             :                      const bool synthesis_result =
   35962             :                         synthesize_sf4ext_expression::
   35963          40 :                            template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
   35964             : 
   35965             :                      exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
   35966             : 
   35967          40 :                      return (synthesis_result) ? result : error_node();
   35968             :                   }
   35969             :                   // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
   35970       11527 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   35971             :                   {
   35972             :                      const bool synthesis_result =
   35973             :                         synthesize_sf4ext_expression::
   35974          40 :                            template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
   35975             : 
   35976             :                      exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
   35977             : 
   35978          40 :                      return (synthesis_result) ? result : error_node();
   35979             :                   }
   35980             :                }
   35981             : 
   35982             :                const bool synthesis_result =
   35983             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   35984       11487 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   35985             : 
   35986       11487 :                if (synthesis_result)
   35987       11092 :                   return result;
   35988             : 
   35989         395 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   35990         395 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   35991         395 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   35992             : 
   35993         395 :                if (!expr_gen.valid_operator(o0,f0))
   35994           0 :                   return error_node();
   35995         395 :                else if (!expr_gen.valid_operator(o1,f1))
   35996           0 :                   return error_node();
   35997         395 :                else if (!expr_gen.valid_operator(o2,f2))
   35998           0 :                   return error_node();
   35999             :                else
   36000         395 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   36001             :             }
   36002             : 
   36003       11487 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36004             :                                          const details::operator_type o0,
   36005             :                                          const details::operator_type o1,
   36006             :                                          const details::operator_type o2)
   36007             :             {
   36008       22974 :                return details::build_string()
   36009       22974 :                   << "(t" << expr_gen.to_str(o0)
   36010       22974 :                   << "t)" << expr_gen.to_str(o1)
   36011       22974 :                   << "(t" << expr_gen.to_str(o2)
   36012       22974 :                   << "t)";
   36013             :             }
   36014             :          };
   36015             : 
   36016             :          struct synthesize_vocovov_expression0
   36017             :          {
   36018             :             typedef typename vocovov_t::type0 node_type;
   36019             :             typedef typename vocovov_t::sf4_type sf4_type;
   36020             :             typedef typename node_type::T0 T0;
   36021             :             typedef typename node_type::T1 T1;
   36022             :             typedef typename node_type::T2 T2;
   36023             :             typedef typename node_type::T3 T3;
   36024             : 
   36025        7615 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36026             :                                                       const details::operator_type& operation,
   36027             :                                                       expression_node_ptr (&branch)[2])
   36028             :             {
   36029             :                // (v0 o0 c) o1 (v1 o2 v2)
   36030        7615 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   36031        7615 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   36032        7615 :                const Type   c = voc->c ();
   36033        7615 :                const Type& v0 = voc->v ();
   36034        7615 :                const Type& v1 = vov->v0();
   36035        7615 :                const Type& v2 = vov->v1();
   36036        7615 :                const details::operator_type o0 = voc->operation();
   36037        7615 :                const details::operator_type o1 = operation;
   36038        7615 :                const details::operator_type o2 = vov->operation();
   36039             : 
   36040        7615 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36041        7615 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36042             : 
   36043        7615 :                expression_node_ptr result = error_node();
   36044             : 
   36045        7615 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36046             :                {
   36047             :                   // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
   36048        7615 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   36049             :                   {
   36050             :                      const bool synthesis_result =
   36051             :                         synthesize_sf4ext_expression::
   36052          40 :                            template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
   36053             : 
   36054             :                      exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
   36055             : 
   36056          40 :                      return (synthesis_result) ? result : error_node();
   36057             :                   }
   36058             :                   // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
   36059        7575 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   36060             :                   {
   36061             :                      const bool synthesis_result =
   36062             :                         synthesize_sf4ext_expression::
   36063          40 :                            template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
   36064             : 
   36065             :                      exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
   36066             : 
   36067          40 :                      return (synthesis_result) ? result : error_node();
   36068             :                   }
   36069             :                }
   36070             : 
   36071             :                const bool synthesis_result =
   36072             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   36073        7535 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   36074             : 
   36075        7535 :                if (synthesis_result)
   36076        7100 :                   return result;
   36077             : 
   36078         435 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36079         435 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36080         435 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   36081             : 
   36082         435 :                if (!expr_gen.valid_operator(o0,f0))
   36083           0 :                   return error_node();
   36084         435 :                else if (!expr_gen.valid_operator(o1,f1))
   36085           0 :                   return error_node();
   36086         435 :                else if (!expr_gen.valid_operator(o2,f2))
   36087           0 :                   return error_node();
   36088             :                else
   36089         435 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   36090             :             }
   36091             : 
   36092        7535 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36093             :                                          const details::operator_type o0,
   36094             :                                          const details::operator_type o1,
   36095             :                                          const details::operator_type o2)
   36096             :             {
   36097       15070 :                return details::build_string()
   36098       15070 :                   << "(t" << expr_gen.to_str(o0)
   36099       15070 :                   << "t)" << expr_gen.to_str(o1)
   36100       15070 :                   << "(t" << expr_gen.to_str(o2)
   36101       15070 :                   << "t)";
   36102             :             }
   36103             :          };
   36104             : 
   36105             :          struct synthesize_covovov_expression0
   36106             :          {
   36107             :             typedef typename covovov_t::type0 node_type;
   36108             :             typedef typename covovov_t::sf4_type sf4_type;
   36109             :             typedef typename node_type::T0 T0;
   36110             :             typedef typename node_type::T1 T1;
   36111             :             typedef typename node_type::T2 T2;
   36112             :             typedef typename node_type::T3 T3;
   36113             : 
   36114        7440 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36115             :                                                       const details::operator_type& operation,
   36116             :                                                       expression_node_ptr (&branch)[2])
   36117             :             {
   36118             :                // (c o0 v0) o1 (v1 o2 v2)
   36119        7440 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   36120        7440 :                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
   36121        7440 :                const Type   c = cov->c ();
   36122        7440 :                const Type& v0 = cov->v ();
   36123        7440 :                const Type& v1 = vov->v0();
   36124        7440 :                const Type& v2 = vov->v1();
   36125        7440 :                const details::operator_type o0 = cov->operation();
   36126        7440 :                const details::operator_type o1 = operation;
   36127        7440 :                const details::operator_type o2 = vov->operation();
   36128             : 
   36129        7440 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36130        7440 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36131             : 
   36132        7440 :                expression_node_ptr result = error_node();
   36133             : 
   36134        7440 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36135             :                {
   36136             :                   // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
   36137        7440 :                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   36138             :                   {
   36139             :                      const bool synthesis_result =
   36140             :                         synthesize_sf4ext_expression::
   36141          40 :                            template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
   36142             : 
   36143             :                      exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
   36144             : 
   36145          40 :                      return (synthesis_result) ? result : error_node();
   36146             :                   }
   36147             :                   // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
   36148        7400 :                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   36149             :                   {
   36150             :                      const bool synthesis_result =
   36151             :                         synthesize_sf4ext_expression::
   36152          40 :                            template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
   36153             : 
   36154             :                      exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
   36155             : 
   36156          40 :                      return (synthesis_result) ? result : error_node();
   36157             :                   }
   36158             :                }
   36159             : 
   36160             :                const bool synthesis_result =
   36161             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   36162        7360 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   36163             : 
   36164        7360 :                if (synthesis_result)
   36165        7045 :                   return result;
   36166             : 
   36167         315 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36168         315 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36169         315 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   36170             : 
   36171         315 :                if (!expr_gen.valid_operator(o0,f0))
   36172           0 :                   return error_node();
   36173         315 :                else if (!expr_gen.valid_operator(o1,f1))
   36174           0 :                   return error_node();
   36175         315 :                else if (!expr_gen.valid_operator(o2,f2))
   36176           0 :                   return error_node();
   36177             :                else
   36178         315 :                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   36179             :             }
   36180             : 
   36181        7360 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36182             :                                          const details::operator_type o0,
   36183             :                                          const details::operator_type o1,
   36184             :                                          const details::operator_type o2)
   36185             :             {
   36186       14720 :                return details::build_string()
   36187       14720 :                   << "(t" << expr_gen.to_str(o0)
   36188       14720 :                   << "t)" << expr_gen.to_str(o1)
   36189       14720 :                   << "(t" << expr_gen.to_str(o2)
   36190       14720 :                   << "t)";
   36191             :             }
   36192             :          };
   36193             : 
   36194             :          struct synthesize_covocov_expression0
   36195             :          {
   36196             :             typedef typename covocov_t::type0 node_type;
   36197             :             typedef typename covocov_t::sf4_type sf4_type;
   36198             :             typedef typename node_type::T0 T0;
   36199             :             typedef typename node_type::T1 T1;
   36200             :             typedef typename node_type::T2 T2;
   36201             :             typedef typename node_type::T3 T3;
   36202             : 
   36203        5911 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36204             :                                                       const details::operator_type& operation,
   36205             :                                                       expression_node_ptr (&branch)[2])
   36206             :             {
   36207             :                // (c0 o0 v0) o1 (c1 o2 v1)
   36208        5911 :                const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
   36209        5911 :                const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
   36210        5911 :                const Type  c0 = cov0->c();
   36211        5911 :                const Type& v0 = cov0->v();
   36212        5911 :                const Type  c1 = cov1->c();
   36213        5911 :                const Type& v1 = cov1->v();
   36214        5911 :                const details::operator_type o0 = cov0->operation();
   36215        5911 :                const details::operator_type o1 = operation;
   36216        5911 :                const details::operator_type o2 = cov1->operation();
   36217             : 
   36218        5911 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36219        5911 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36220             : 
   36221        5911 :                expression_node_ptr result = error_node();
   36222             : 
   36223        5911 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36224             :                {
   36225             :                   // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
   36226        5911 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   36227             :                   {
   36228             :                      const bool synthesis_result =
   36229             :                         synthesize_sf3ext_expression::
   36230         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   36231             : 
   36232             :                      exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
   36233             : 
   36234         100 :                      return (synthesis_result) ? result : error_node();
   36235             :                   }
   36236             :                   // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
   36237        5811 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   36238             :                   {
   36239             :                      const bool synthesis_result =
   36240             :                         synthesize_sf3ext_expression::
   36241         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   36242             : 
   36243             :                      exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
   36244             : 
   36245         100 :                      return (synthesis_result) ? result : error_node();
   36246             :                   }
   36247             :                   // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
   36248        5711 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   36249             :                   {
   36250             :                      const bool synthesis_result =
   36251             :                         synthesize_sf3ext_expression::
   36252         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
   36253             : 
   36254             :                      exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
   36255             : 
   36256         100 :                      return (synthesis_result) ? result : error_node();
   36257             :                   }
   36258             :                   // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
   36259        5611 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   36260             :                   {
   36261             :                      const bool synthesis_result =
   36262             :                         synthesize_sf3ext_expression::
   36263         560 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   36264             : 
   36265             :                      exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
   36266             : 
   36267         280 :                      return (synthesis_result) ? result : error_node();
   36268             :                   }
   36269             :                   // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
   36270        5331 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36271             :                   {
   36272             :                      const bool synthesis_result =
   36273             :                         synthesize_sf3ext_expression::
   36274         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   36275             : 
   36276             :                      exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
   36277             : 
   36278         100 :                      return (synthesis_result) ? result : error_node();
   36279             :                   }
   36280             :                   // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
   36281        5231 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   36282             :                   {
   36283             :                      const bool synthesis_result =
   36284             :                         synthesize_sf3ext_expression::
   36285         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
   36286             : 
   36287             :                      exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
   36288             : 
   36289         100 :                      return (synthesis_result) ? result : error_node();
   36290             :                   }
   36291             :                   // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
   36292        5131 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   36293             :                   {
   36294             :                      const bool synthesis_result =
   36295             :                         synthesize_sf3ext_expression::
   36296          90 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
   36297             : 
   36298             :                      exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
   36299             : 
   36300          45 :                      return (synthesis_result) ? result : error_node();
   36301             :                   }
   36302             :                   // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
   36303        5086 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   36304             :                   {
   36305             :                      const bool synthesis_result =
   36306             :                         synthesize_sf3ext_expression::
   36307         220 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
   36308             : 
   36309             :                      exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
   36310             : 
   36311         110 :                      return (synthesis_result) ? result : error_node();
   36312             :                   }
   36313             :                   // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
   36314        4976 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36315             :                   {
   36316             :                      const bool synthesis_result =
   36317             :                         synthesize_sf3ext_expression::
   36318         230 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
   36319             : 
   36320             :                      exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
   36321             : 
   36322         115 :                      return (synthesis_result) ? result : error_node();
   36323             :                   }
   36324             :                   // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
   36325        4861 :                   else if (
   36326        4861 :                             (std::equal_to<T>()(c0,c1)) &&
   36327         720 :                             (details::e_mul == o0)      &&
   36328        6301 :                             (details::e_mul == o2)      &&
   36329             :                             (
   36330         720 :                               (details::e_add == o1) ||
   36331         420 :                               (details::e_sub == o1)
   36332             :                             )
   36333             :                           )
   36334             :                   {
   36335         360 :                      std::string specfunc;
   36336             : 
   36337         360 :                      switch (o1)
   36338             :                      {
   36339         300 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   36340          60 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   36341           0 :                         default             : return error_node();
   36342             :                      }
   36343             : 
   36344             :                      const bool synthesis_result =
   36345             :                         synthesize_sf3ext_expression::
   36346         360 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   36347             : 
   36348             :                      exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
   36349             : 
   36350         360 :                      return (synthesis_result) ? result : error_node();
   36351         360 :                   }
   36352             :                }
   36353             : 
   36354             :                const bool synthesis_result =
   36355             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   36356        4501 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   36357             : 
   36358        4501 :                if (synthesis_result)
   36359        4011 :                   return result;
   36360             : 
   36361         490 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36362         490 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36363         490 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   36364             : 
   36365         490 :                if (!expr_gen.valid_operator(o0,f0))
   36366           0 :                   return error_node();
   36367         490 :                else if (!expr_gen.valid_operator(o1,f1))
   36368           0 :                   return error_node();
   36369         490 :                else if (!expr_gen.valid_operator(o2,f2))
   36370           0 :                   return error_node();
   36371             :                else
   36372         490 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   36373             :             }
   36374             : 
   36375        4501 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36376             :                                          const details::operator_type o0,
   36377             :                                          const details::operator_type o1,
   36378             :                                          const details::operator_type o2)
   36379             :             {
   36380        9002 :                return details::build_string()
   36381        9002 :                   << "(t" << expr_gen.to_str(o0)
   36382        9002 :                   << "t)" << expr_gen.to_str(o1)
   36383        9002 :                   << "(t" << expr_gen.to_str(o2)
   36384        9002 :                   << "t)";
   36385             :             }
   36386             :          };
   36387             : 
   36388             :          struct synthesize_vocovoc_expression0
   36389             :          {
   36390             :             typedef typename vocovoc_t::type0 node_type;
   36391             :             typedef typename vocovoc_t::sf4_type sf4_type;
   36392             :             typedef typename node_type::T0 T0;
   36393             :             typedef typename node_type::T1 T1;
   36394             :             typedef typename node_type::T2 T2;
   36395             :             typedef typename node_type::T3 T3;
   36396             : 
   36397        6463 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36398             :                                                       const details::operator_type& operation,
   36399             :                                                       expression_node_ptr (&branch)[2])
   36400             :             {
   36401             :                // (v0 o0 c0) o1 (v1 o2 c1)
   36402        6463 :                const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
   36403        6463 :                const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
   36404        6463 :                const Type  c0 = voc0->c();
   36405        6463 :                const Type& v0 = voc0->v();
   36406        6463 :                const Type  c1 = voc1->c();
   36407        6463 :                const Type& v1 = voc1->v();
   36408        6463 :                const details::operator_type o0 = voc0->operation();
   36409        6463 :                const details::operator_type o1 = operation;
   36410        6463 :                const details::operator_type o2 = voc1->operation();
   36411             : 
   36412        6463 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36413        6463 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36414             : 
   36415        6463 :                expression_node_ptr result = error_node();
   36416             : 
   36417        6463 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36418             :                {
   36419             :                   // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
   36420        6463 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   36421             :                   {
   36422             :                      const bool synthesis_result =
   36423             :                         synthesize_sf3ext_expression::
   36424         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   36425             : 
   36426             :                      exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
   36427             : 
   36428         100 :                      return (synthesis_result) ? result : error_node();
   36429             :                   }
   36430             :                   // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
   36431        6363 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   36432             :                   {
   36433             :                      const bool synthesis_result =
   36434             :                         synthesize_sf3ext_expression::
   36435         220 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   36436             : 
   36437             :                      exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
   36438             : 
   36439         110 :                      return (synthesis_result) ? result : error_node();
   36440             :                   }
   36441             :                   // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
   36442        6253 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   36443             :                   {
   36444             :                      const bool synthesis_result =
   36445             :                         synthesize_sf3ext_expression::
   36446         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
   36447             : 
   36448             :                      exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
   36449             : 
   36450         100 :                      return (synthesis_result) ? result : error_node();
   36451             :                   }
   36452             :                   // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
   36453        6153 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   36454             :                   {
   36455             :                      const bool synthesis_result =
   36456             :                         synthesize_sf3ext_expression::
   36457          90 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   36458             : 
   36459             :                      exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
   36460             : 
   36461          45 :                      return (synthesis_result) ? result : error_node();
   36462             :                   }
   36463             :                   // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
   36464        6108 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36465             :                   {
   36466             :                      const bool synthesis_result =
   36467             :                         synthesize_sf3ext_expression::
   36468         220 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   36469             : 
   36470             :                      exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
   36471             : 
   36472         110 :                      return (synthesis_result) ? result : error_node();
   36473             :                   }
   36474             :                   // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
   36475        5998 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   36476             :                   {
   36477             :                      const bool synthesis_result =
   36478             :                         synthesize_sf3ext_expression::
   36479         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
   36480             : 
   36481             :                      exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
   36482             : 
   36483         100 :                      return (synthesis_result) ? result : error_node();
   36484             :                   }
   36485             :                   // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
   36486        5898 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   36487             :                   {
   36488             :                      const bool synthesis_result =
   36489             :                         synthesize_sf3ext_expression::
   36490          80 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
   36491             : 
   36492             :                      exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
   36493             : 
   36494          40 :                      return (synthesis_result) ? result : error_node();
   36495             :                   }
   36496             :                   // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
   36497        5858 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   36498             :                   {
   36499             :                      const bool synthesis_result =
   36500             :                         synthesize_sf3ext_expression::
   36501         240 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
   36502             : 
   36503             :                      exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
   36504             : 
   36505         120 :                      return (synthesis_result) ? result : error_node();
   36506             :                   }
   36507             :                   // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
   36508        5738 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36509             :                   {
   36510             :                      const bool synthesis_result =
   36511             :                         synthesize_sf3ext_expression::
   36512         210 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
   36513             : 
   36514             :                      exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
   36515             : 
   36516         105 :                      return (synthesis_result) ? result : error_node();
   36517             :                   }
   36518             :                   // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
   36519        5633 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
   36520             :                   {
   36521             :                      const bool synthesis_result =
   36522             :                         synthesize_sf4ext_expression::
   36523          90 :                            template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
   36524             : 
   36525             :                      exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
   36526             : 
   36527          45 :                      return (synthesis_result) ? result : error_node();
   36528             :                   }
   36529             :                   // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
   36530        5588 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
   36531             :                   {
   36532             :                      const bool synthesis_result =
   36533             :                         synthesize_sf4ext_expression::
   36534          90 :                            template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
   36535             : 
   36536             :                      exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
   36537             : 
   36538          45 :                      return (synthesis_result) ? result : error_node();
   36539             :                   }
   36540             :                   // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
   36541        5543 :                   else if (
   36542        5543 :                             (std::equal_to<T>()(c0,c1)) &&
   36543         500 :                             (details::e_mul == o0)      &&
   36544        6463 :                             (details::e_mul == o2)      &&
   36545             :                             (
   36546         420 :                               (details::e_add == o1) ||
   36547         420 :                               (details::e_sub == o1)
   36548             :                             )
   36549             :                           )
   36550             :                   {
   36551          60 :                      std::string specfunc;
   36552             : 
   36553          60 :                      switch (o1)
   36554             :                      {
   36555           0 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   36556          60 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   36557           0 :                         default             : return error_node();
   36558             :                      }
   36559             : 
   36560             :                      const bool synthesis_result =
   36561             :                         synthesize_sf3ext_expression::
   36562          60 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   36563             : 
   36564             :                      exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
   36565             : 
   36566          60 :                      return (synthesis_result) ? result : error_node();
   36567          60 :                   }
   36568             :                   // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
   36569        5483 :                   else if (
   36570        5483 :                             (std::equal_to<T>()(c0,c1)) &&
   36571         440 :                             (details::e_div == o0)      &&
   36572        5923 :                             (details::e_div == o2)      &&
   36573             :                             (
   36574           0 :                               (details::e_add == o1) ||
   36575           0 :                               (details::e_sub == o1)
   36576             :                             )
   36577             :                           )
   36578             :                   {
   36579           0 :                      std::string specfunc;
   36580             : 
   36581           0 :                      switch (o1)
   36582             :                      {
   36583           0 :                         case details::e_add : specfunc = "(t+t)/t"; break;
   36584           0 :                         case details::e_sub : specfunc = "(t-t)/t"; break;
   36585           0 :                         default             : return error_node();
   36586             :                      }
   36587             : 
   36588             :                      const bool synthesis_result =
   36589             :                         synthesize_sf3ext_expression::
   36590           0 :                            template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result);
   36591             : 
   36592             :                      exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
   36593             : 
   36594           0 :                      return (synthesis_result) ? result : error_node();
   36595           0 :                   }
   36596             :                }
   36597             : 
   36598             :                const bool synthesis_result =
   36599             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   36600        5483 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   36601             : 
   36602        5483 :                if (synthesis_result)
   36603        3250 :                   return result;
   36604             : 
   36605        2233 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36606        2233 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36607        2233 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   36608             : 
   36609        2233 :                if (!expr_gen.valid_operator(o0,f0))
   36610           0 :                   return error_node();
   36611        2233 :                else if (!expr_gen.valid_operator(o1,f1))
   36612           0 :                   return error_node();
   36613        2233 :                else if (!expr_gen.valid_operator(o2,f2))
   36614           0 :                   return error_node();
   36615             :                else
   36616        2233 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   36617             :             }
   36618             : 
   36619        5483 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36620             :                                          const details::operator_type o0,
   36621             :                                          const details::operator_type o1,
   36622             :                                          const details::operator_type o2)
   36623             :             {
   36624       10966 :                return details::build_string()
   36625       10966 :                   << "(t" << expr_gen.to_str(o0)
   36626       10966 :                   << "t)" << expr_gen.to_str(o1)
   36627       10966 :                   << "(t" << expr_gen.to_str(o2)
   36628       10966 :                   << "t)";
   36629             :             }
   36630             :          };
   36631             : 
   36632             :          struct synthesize_covovoc_expression0
   36633             :          {
   36634             :             typedef typename covovoc_t::type0 node_type;
   36635             :             typedef typename covovoc_t::sf4_type sf4_type;
   36636             :             typedef typename node_type::T0 T0;
   36637             :             typedef typename node_type::T1 T1;
   36638             :             typedef typename node_type::T2 T2;
   36639             :             typedef typename node_type::T3 T3;
   36640             : 
   36641        4660 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36642             :                                                       const details::operator_type& operation,
   36643             :                                                       expression_node_ptr (&branch)[2])
   36644             :             {
   36645             :                // (c0 o0 v0) o1 (v1 o2 c1)
   36646        4660 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
   36647        4660 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
   36648        4660 :                const Type  c0 = cov->c();
   36649        4660 :                const Type& v0 = cov->v();
   36650        4660 :                const Type  c1 = voc->c();
   36651        4660 :                const Type& v1 = voc->v();
   36652        4660 :                const details::operator_type o0 = cov->operation();
   36653        4660 :                const details::operator_type o1 = operation;
   36654        4660 :                const details::operator_type o2 = voc->operation();
   36655             : 
   36656        4660 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36657        4660 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36658             : 
   36659        4660 :                expression_node_ptr result = error_node();
   36660             : 
   36661        4660 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36662             :                {
   36663             :                   // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
   36664        4660 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   36665             :                   {
   36666             :                      const bool synthesis_result =
   36667             :                         synthesize_sf3ext_expression::
   36668         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   36669             : 
   36670             :                      exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
   36671             : 
   36672         100 :                      return (synthesis_result) ? result : error_node();
   36673             :                   }
   36674             :                   // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
   36675        4560 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   36676             :                   {
   36677             :                      const bool synthesis_result =
   36678             :                         synthesize_sf3ext_expression::
   36679         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   36680             : 
   36681             :                      exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
   36682             : 
   36683         100 :                      return (synthesis_result) ? result : error_node();
   36684             :                   }
   36685             :                   // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
   36686        4460 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   36687             :                   {
   36688             :                      const bool synthesis_result =
   36689             :                         synthesize_sf3ext_expression::
   36690         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
   36691             : 
   36692             :                      exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
   36693             : 
   36694         100 :                      return (synthesis_result) ? result : error_node();
   36695             :                   }
   36696             :                   // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
   36697        4360 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   36698             :                   {
   36699             :                      const bool synthesis_result =
   36700             :                         synthesize_sf3ext_expression::
   36701          80 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   36702             : 
   36703             :                      exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
   36704             : 
   36705          40 :                      return (synthesis_result) ? result : error_node();
   36706             :                   }
   36707             :                   // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
   36708        4320 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36709             :                   {
   36710             :                      const bool synthesis_result =
   36711             :                         synthesize_sf3ext_expression::
   36712         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   36713             : 
   36714             :                      exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
   36715             : 
   36716         100 :                      return (synthesis_result) ? result : error_node();
   36717             :                   }
   36718             :                   // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
   36719        4220 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   36720             :                   {
   36721             :                      const bool synthesis_result =
   36722             :                         synthesize_sf3ext_expression::
   36723         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
   36724             : 
   36725             :                      exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
   36726             : 
   36727         100 :                      return (synthesis_result) ? result : error_node();
   36728             :                   }
   36729             :                   // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
   36730        4120 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   36731             :                   {
   36732             :                      const bool synthesis_result =
   36733             :                         synthesize_sf3ext_expression::
   36734          80 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
   36735             : 
   36736             :                      exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
   36737             : 
   36738          40 :                      return (synthesis_result) ? result : error_node();
   36739             :                   }
   36740             :                   // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
   36741        4080 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   36742             :                   {
   36743             :                      const bool synthesis_result =
   36744             :                         synthesize_sf3ext_expression::
   36745         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
   36746             : 
   36747             :                      exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
   36748             : 
   36749         100 :                      return (synthesis_result) ? result : error_node();
   36750             :                   }
   36751             :                   // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
   36752        3980 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36753             :                   {
   36754             :                      const bool synthesis_result =
   36755             :                         synthesize_sf3ext_expression::
   36756         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
   36757             : 
   36758             :                      exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
   36759             : 
   36760         100 :                      return (synthesis_result) ? result : error_node();
   36761             :                   }
   36762             :                   // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
   36763        3880 :                   else if (
   36764        3880 :                             (std::equal_to<T>()(c0,c1)) &&
   36765         240 :                             (details::e_mul == o0)      &&
   36766        4225 :                             (details::e_mul == o2)      &&
   36767             :                             (
   36768         105 :                               (details::e_add == o1) ||
   36769          15 :                               (details::e_sub == o1)
   36770             :                             )
   36771             :                           )
   36772             :                   {
   36773         105 :                      std::string specfunc;
   36774             : 
   36775         105 :                      switch (o1)
   36776             :                      {
   36777          90 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   36778          15 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   36779           0 :                         default             : return error_node();
   36780             :                      }
   36781             : 
   36782             :                      const bool synthesis_result =
   36783             :                         synthesize_sf3ext_expression::
   36784         105 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   36785             : 
   36786             :                      exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
   36787             : 
   36788         105 :                      return (synthesis_result) ? result : error_node();
   36789         105 :                   }
   36790             :                }
   36791             : 
   36792             :                const bool synthesis_result =
   36793             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   36794        3775 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   36795             : 
   36796        3775 :                if (synthesis_result)
   36797        3645 :                   return result;
   36798             : 
   36799         130 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36800         130 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36801         130 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   36802             : 
   36803         130 :                if (!expr_gen.valid_operator(o0,f0))
   36804           0 :                   return error_node();
   36805         130 :                else if (!expr_gen.valid_operator(o1,f1))
   36806           0 :                   return error_node();
   36807         130 :                else if (!expr_gen.valid_operator(o2,f2))
   36808           0 :                   return error_node();
   36809             :                else
   36810         130 :                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   36811             :             }
   36812             : 
   36813        3775 :             static inline std::string id(expression_generator<Type>& expr_gen,
   36814             :                                          const details::operator_type o0,
   36815             :                                          const details::operator_type o1,
   36816             :                                          const details::operator_type o2)
   36817             :             {
   36818        7550 :                return details::build_string()
   36819        7550 :                   << "(t" << expr_gen.to_str(o0)
   36820        7550 :                   << "t)" << expr_gen.to_str(o1)
   36821        7550 :                   << "(t" << expr_gen.to_str(o2)
   36822        7550 :                   << "t)";
   36823             :             }
   36824             :          };
   36825             : 
   36826             :          struct synthesize_vococov_expression0
   36827             :          {
   36828             :             typedef typename vococov_t::type0 node_type;
   36829             :             typedef typename vococov_t::sf4_type sf4_type;
   36830             :             typedef typename node_type::T0 T0;
   36831             :             typedef typename node_type::T1 T1;
   36832             :             typedef typename node_type::T2 T2;
   36833             :             typedef typename node_type::T3 T3;
   36834             : 
   36835        4310 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   36836             :                                                       const details::operator_type& operation,
   36837             :                                                       expression_node_ptr (&branch)[2])
   36838             :             {
   36839             :                // (v0 o0 c0) o1 (c1 o2 v1)
   36840        4310 :                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
   36841        4310 :                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
   36842        4310 :                const Type  c0 = voc->c();
   36843        4310 :                const Type& v0 = voc->v();
   36844        4310 :                const Type  c1 = cov->c();
   36845        4310 :                const Type& v1 = cov->v();
   36846        4310 :                const details::operator_type o0 = voc->operation();
   36847        4310 :                const details::operator_type o1 = operation;
   36848        4310 :                const details::operator_type o2 = cov->operation();
   36849             : 
   36850        4310 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   36851        4310 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   36852             : 
   36853        4310 :                expression_node_ptr result = error_node();
   36854             : 
   36855        4310 :                if (expr_gen.parser_->settings_.strength_reduction_enabled())
   36856             :                {
   36857             :                   // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
   36858        4310 :                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
   36859             :                   {
   36860             :                      const bool synthesis_result =
   36861             :                         synthesize_sf3ext_expression::
   36862         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
   36863             : 
   36864             :                      exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
   36865             : 
   36866         100 :                      return (synthesis_result) ? result : error_node();
   36867             :                   }
   36868             :                   // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
   36869        4210 :                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
   36870             :                   {
   36871             :                      const bool synthesis_result =
   36872             :                         synthesize_sf3ext_expression::
   36873         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
   36874             : 
   36875             :                      exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
   36876             : 
   36877         100 :                      return (synthesis_result) ? result : error_node();
   36878             :                   }
   36879             :                   // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
   36880        4110 :                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
   36881             :                   {
   36882             :                      const bool synthesis_result =
   36883             :                         synthesize_sf3ext_expression::
   36884         200 :                            template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
   36885             : 
   36886             :                      exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
   36887             : 
   36888         100 :                      return (synthesis_result) ? result : error_node();
   36889             :                   }
   36890             :                   // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
   36891        4010 :                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
   36892             :                   {
   36893             :                      const bool synthesis_result =
   36894             :                         synthesize_sf3ext_expression::
   36895          80 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
   36896             : 
   36897             :                      exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
   36898             : 
   36899          40 :                      return (synthesis_result) ? result : error_node();
   36900             :                   }
   36901             :                   // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
   36902        3970 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36903             :                   {
   36904             :                      const bool synthesis_result =
   36905             :                         synthesize_sf3ext_expression::
   36906         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
   36907             : 
   36908             :                      exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
   36909             : 
   36910         100 :                      return (synthesis_result) ? result : error_node();
   36911             :                   }
   36912             :                   // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
   36913        3870 :                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
   36914             :                   {
   36915             :                      const bool synthesis_result =
   36916             :                         synthesize_sf3ext_expression::
   36917         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
   36918             : 
   36919             :                      exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
   36920             : 
   36921         100 :                      return (synthesis_result) ? result : error_node();
   36922             :                   }
   36923             :                   // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
   36924        3770 :                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
   36925             :                   {
   36926             :                      const bool synthesis_result =
   36927             :                         synthesize_sf3ext_expression::
   36928         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
   36929             : 
   36930             :                      exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
   36931             : 
   36932         100 :                      return (synthesis_result) ? result : error_node();
   36933             :                   }
   36934             :                   // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
   36935        3670 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
   36936             :                   {
   36937             :                      const bool synthesis_result =
   36938             :                         synthesize_sf3ext_expression::
   36939         200 :                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
   36940             : 
   36941             :                      exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
   36942             : 
   36943         100 :                      return (synthesis_result) ? result : error_node();
   36944             :                   }
   36945             :                   // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
   36946        3570 :                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
   36947             :                   {
   36948             :                      const bool synthesis_result =
   36949             :                         synthesize_sf3ext_expression::
   36950          80 :                            template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
   36951             : 
   36952             :                      exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
   36953             : 
   36954          40 :                      return (synthesis_result) ? result : error_node();
   36955             :                   }
   36956             :                   // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
   36957        3530 :                   else if (
   36958        3530 :                             (std::equal_to<T>()(c0,c1)) &&
   36959         120 :                             (details::e_mul == o0)      &&
   36960        3650 :                             (details::e_mul == o2)      &&
   36961             :                             (
   36962           0 :                               (details::e_add == o1) || (details::e_sub == o1)
   36963             :                             )
   36964             :                           )
   36965             :                   {
   36966           0 :                      std::string specfunc;
   36967             : 
   36968           0 :                      switch (o1)
   36969             :                      {
   36970           0 :                         case details::e_add : specfunc = "t*(t+t)"; break;
   36971           0 :                         case details::e_sub : specfunc = "t*(t-t)"; break;
   36972           0 :                         default             : return error_node();
   36973             :                      }
   36974             : 
   36975             :                      const bool synthesis_result =
   36976             :                         synthesize_sf3ext_expression::
   36977           0 :                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
   36978             : 
   36979             :                      exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
   36980             : 
   36981           0 :                      return (synthesis_result) ? result : error_node();
   36982           0 :                   }
   36983             :                }
   36984             : 
   36985             :                const bool synthesis_result =
   36986             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   36987        3530 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
   36988             : 
   36989        3530 :                if (synthesis_result)
   36990        3285 :                   return result;
   36991             : 
   36992         245 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   36993         245 :                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
   36994         245 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   36995             : 
   36996         245 :                if (!expr_gen.valid_operator(o0,f0))
   36997           0 :                   return error_node();
   36998         245 :                else if (!expr_gen.valid_operator(o1,f1))
   36999           0 :                   return error_node();
   37000         245 :                else if (!expr_gen.valid_operator(o2,f2))
   37001           0 :                   return error_node();
   37002             :                else
   37003         245 :                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
   37004             :             }
   37005             : 
   37006        3530 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37007             :                                          const details::operator_type o0,
   37008             :                                          const details::operator_type o1,
   37009             :                                          const details::operator_type o2)
   37010             :             {
   37011        7060 :                return details::build_string()
   37012        7060 :                   << "(t" << expr_gen.to_str(o0)
   37013        7060 :                   << "t)" << expr_gen.to_str(o1)
   37014        7060 :                   << "(t" << expr_gen.to_str(o2)
   37015        7060 :                   << "t)";
   37016             :             }
   37017             :          };
   37018             : 
   37019             :          struct synthesize_vovovov_expression1
   37020             :          {
   37021             :             typedef typename vovovov_t::type1 node_type;
   37022             :             typedef typename vovovov_t::sf4_type sf4_type;
   37023             :             typedef typename node_type::T0 T0;
   37024             :             typedef typename node_type::T1 T1;
   37025             :             typedef typename node_type::T2 T2;
   37026             :             typedef typename node_type::T3 T3;
   37027             : 
   37028           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37029             :                                                       const details::operator_type& operation,
   37030             :                                                       expression_node_ptr (&branch)[2])
   37031             :             {
   37032             :                // v0 o0 (v1 o1 (v2 o2 v3))
   37033             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   37034             : 
   37035           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   37036           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37037           0 :                const Type& v1 = vovov->t0();
   37038           0 :                const Type& v2 = vovov->t1();
   37039           0 :                const Type& v3 = vovov->t2();
   37040           0 :                const details::operator_type o0 = operation;
   37041           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   37042           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   37043             : 
   37044           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37045           0 :                binary_functor_t f1 = vovov->f0();
   37046           0 :                binary_functor_t f2 = vovov->f1();
   37047             : 
   37048           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37049             : 
   37050           0 :                expression_node_ptr result = error_node();
   37051             : 
   37052             :                const bool synthesis_result =
   37053             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37054           0 :                      (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   37055             : 
   37056           0 :                if (synthesis_result)
   37057           0 :                   return result;
   37058           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37059           0 :                   return error_node();
   37060             : 
   37061             :                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
   37062             : 
   37063           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   37064             :             }
   37065             : 
   37066           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37067             :                                          const details::operator_type o0,
   37068             :                                          const details::operator_type o1,
   37069             :                                          const details::operator_type o2)
   37070             :             {
   37071           0 :                return details::build_string()
   37072           0 :                   << "t"  << expr_gen.to_str(o0)
   37073           0 :                   << "(t" << expr_gen.to_str(o1)
   37074           0 :                   << "(t" << expr_gen.to_str(o2)
   37075           0 :                   << "t))";
   37076             :             }
   37077             :          };
   37078             : 
   37079             :          struct synthesize_vovovoc_expression1
   37080             :          {
   37081             :             typedef typename vovovoc_t::type1 node_type;
   37082             :             typedef typename vovovoc_t::sf4_type sf4_type;
   37083             :             typedef typename node_type::T0 T0;
   37084             :             typedef typename node_type::T1 T1;
   37085             :             typedef typename node_type::T2 T2;
   37086             :             typedef typename node_type::T3 T3;
   37087             : 
   37088           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37089             :                                                       const details::operator_type& operation,
   37090             :                                                       expression_node_ptr (&branch)[2])
   37091             :             {
   37092             :                // v0 o0 (v1 o1 (v2 o2 c))
   37093             :                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
   37094             : 
   37095           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   37096           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37097           0 :                const Type& v1 = vovoc->t0();
   37098           0 :                const Type& v2 = vovoc->t1();
   37099           0 :                const Type   c = vovoc->t2();
   37100           0 :                const details::operator_type o0 = operation;
   37101           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   37102           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   37103             : 
   37104           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37105           0 :                binary_functor_t f1 = vovoc->f0();
   37106           0 :                binary_functor_t f2 = vovoc->f1();
   37107             : 
   37108           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37109             : 
   37110           0 :                expression_node_ptr result = error_node();
   37111             : 
   37112             :                const bool synthesis_result =
   37113             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37114           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   37115             : 
   37116           0 :                if (synthesis_result)
   37117           0 :                   return result;
   37118           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37119           0 :                   return error_node();
   37120             : 
   37121             :                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
   37122             : 
   37123           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   37124             :             }
   37125             : 
   37126           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37127             :                                          const details::operator_type o0,
   37128             :                                          const details::operator_type o1,
   37129             :                                          const details::operator_type o2)
   37130             :             {
   37131           0 :                return details::build_string()
   37132           0 :                   << "t"  << expr_gen.to_str(o0)
   37133           0 :                   << "(t" << expr_gen.to_str(o1)
   37134           0 :                   << "(t" << expr_gen.to_str(o2)
   37135           0 :                   << "t))";
   37136             :             }
   37137             :          };
   37138             : 
   37139             :          struct synthesize_vovocov_expression1
   37140             :          {
   37141             :             typedef typename vovocov_t::type1 node_type;
   37142             :             typedef typename vovocov_t::sf4_type sf4_type;
   37143             :             typedef typename node_type::T0 T0;
   37144             :             typedef typename node_type::T1 T1;
   37145             :             typedef typename node_type::T2 T2;
   37146             :             typedef typename node_type::T3 T3;
   37147             : 
   37148           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37149             :                                                       const details::operator_type& operation,
   37150             :                                                       expression_node_ptr (&branch)[2])
   37151             :             {
   37152             :                // v0 o0 (v1 o1 (c o2 v2))
   37153             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   37154             : 
   37155           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   37156           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37157           0 :                const Type& v1 = vocov->t0();
   37158           0 :                const Type   c = vocov->t1();
   37159           0 :                const Type& v2 = vocov->t2();
   37160           0 :                const details::operator_type o0 = operation;
   37161           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   37162           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   37163             : 
   37164           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37165           0 :                binary_functor_t f1 = vocov->f0();
   37166           0 :                binary_functor_t f2 = vocov->f1();
   37167             : 
   37168           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37169             : 
   37170           0 :                expression_node_ptr result = error_node();
   37171             : 
   37172             :                const bool synthesis_result =
   37173             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37174           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   37175             : 
   37176           0 :                if (synthesis_result)
   37177           0 :                   return result;
   37178           0 :                if (!expr_gen.valid_operator(o0,f0))
   37179           0 :                   return error_node();
   37180             : 
   37181             :                exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
   37182             : 
   37183           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   37184             :             }
   37185             : 
   37186           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37187             :                                          const details::operator_type o0,
   37188             :                                          const details::operator_type o1,
   37189             :                                          const details::operator_type o2)
   37190             :             {
   37191           0 :                return details::build_string()
   37192           0 :                   << "t"  << expr_gen.to_str(o0)
   37193           0 :                   << "(t" << expr_gen.to_str(o1)
   37194           0 :                   << "(t" << expr_gen.to_str(o2)
   37195           0 :                   << "t))";
   37196             :             }
   37197             :          };
   37198             : 
   37199             :          struct synthesize_vocovov_expression1
   37200             :          {
   37201             :             typedef typename vocovov_t::type1 node_type;
   37202             :             typedef typename vocovov_t::sf4_type sf4_type;
   37203             :             typedef typename node_type::T0 T0;
   37204             :             typedef typename node_type::T1 T1;
   37205             :             typedef typename node_type::T2 T2;
   37206             :             typedef typename node_type::T3 T3;
   37207             : 
   37208           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37209             :                                                       const details::operator_type& operation,
   37210             :                                                       expression_node_ptr (&branch)[2])
   37211             :             {
   37212             :                // v0 o0 (c o1 (v1 o2 v2))
   37213             :                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
   37214             : 
   37215           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
   37216           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37217           0 :                const Type   c = covov->t0();
   37218           0 :                const Type& v1 = covov->t1();
   37219           0 :                const Type& v2 = covov->t2();
   37220           0 :                const details::operator_type o0 = operation;
   37221           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
   37222           0 :                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
   37223             : 
   37224           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37225           0 :                binary_functor_t f1 = covov->f0();
   37226           0 :                binary_functor_t f2 = covov->f1();
   37227             : 
   37228           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37229             : 
   37230           0 :                expression_node_ptr result = error_node();
   37231             : 
   37232             :                const bool synthesis_result =
   37233             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37234           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   37235             : 
   37236           0 :                if (synthesis_result)
   37237           0 :                   return result;
   37238           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37239           0 :                   return error_node();
   37240             : 
   37241             :                exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
   37242             : 
   37243           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   37244             :             }
   37245             : 
   37246           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37247             :                                          const details::operator_type o0,
   37248             :                                          const details::operator_type o1,
   37249             :                                          const details::operator_type o2)
   37250             :             {
   37251           0 :                return details::build_string()
   37252           0 :                   << "t"  << expr_gen.to_str(o0)
   37253           0 :                   << "(t" << expr_gen.to_str(o1)
   37254           0 :                   << "(t" << expr_gen.to_str(o2)
   37255           0 :                   << "t))";
   37256             :             }
   37257             :          };
   37258             : 
   37259             :          struct synthesize_covovov_expression1
   37260             :          {
   37261             :             typedef typename covovov_t::type1 node_type;
   37262             :             typedef typename covovov_t::sf4_type sf4_type;
   37263             :             typedef typename node_type::T0 T0;
   37264             :             typedef typename node_type::T1 T1;
   37265             :             typedef typename node_type::T2 T2;
   37266             :             typedef typename node_type::T3 T3;
   37267             : 
   37268           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37269             :                                                       const details::operator_type& operation,
   37270             :                                                       expression_node_ptr (&branch)[2])
   37271             :             {
   37272             :                // c o0 (v0 o1 (v1 o2 v2))
   37273             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   37274             : 
   37275           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   37276           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   37277           0 :                const Type& v0 = vovov->t0();
   37278           0 :                const Type& v1 = vovov->t1();
   37279           0 :                const Type& v2 = vovov->t2();
   37280           0 :                const details::operator_type o0 = operation;
   37281           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   37282           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   37283             : 
   37284           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37285           0 :                binary_functor_t f1 = vovov->f0();
   37286           0 :                binary_functor_t f2 = vovov->f1();
   37287             : 
   37288           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37289           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37290             : 
   37291           0 :                expression_node_ptr result = error_node();
   37292             : 
   37293             :                const bool synthesis_result =
   37294             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37295           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   37296             : 
   37297           0 :                if (synthesis_result)
   37298           0 :                   return result;
   37299           0 :                if (!expr_gen.valid_operator(o0,f0))
   37300           0 :                   return error_node();
   37301             : 
   37302             :                exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
   37303             : 
   37304           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   37305             :             }
   37306             : 
   37307           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37308             :                                          const details::operator_type o0,
   37309             :                                          const details::operator_type o1,
   37310             :                                          const details::operator_type o2)
   37311             :             {
   37312           0 :                return details::build_string()
   37313           0 :                   << "t"  << expr_gen.to_str(o0)
   37314           0 :                   << "(t" << expr_gen.to_str(o1)
   37315           0 :                   << "(t" << expr_gen.to_str(o2)
   37316           0 :                   << "t))";
   37317             :             }
   37318             :          };
   37319             : 
   37320             :          struct synthesize_covocov_expression1
   37321             :          {
   37322             :             typedef typename covocov_t::type1 node_type;
   37323             :             typedef typename covocov_t::sf4_type sf4_type;
   37324             :             typedef typename node_type::T0 T0;
   37325             :             typedef typename node_type::T1 T1;
   37326             :             typedef typename node_type::T2 T2;
   37327             :             typedef typename node_type::T3 T3;
   37328             : 
   37329           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37330             :                                                       const details::operator_type& operation,
   37331             :                                                       expression_node_ptr (&branch)[2])
   37332             :             {
   37333             :                // c0 o0 (v0 o1 (c1 o2 v1))
   37334             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   37335             : 
   37336           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   37337           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   37338           0 :                const Type& v0 = vocov->t0();
   37339           0 :                const Type  c1 = vocov->t1();
   37340           0 :                const Type& v1 = vocov->t2();
   37341           0 :                const details::operator_type o0 = operation;
   37342           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   37343           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   37344             : 
   37345           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37346           0 :                binary_functor_t f1 = vocov->f0();
   37347           0 :                binary_functor_t f2 = vocov->f1();
   37348             : 
   37349           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37350           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37351             : 
   37352           0 :                expression_node_ptr result = error_node();
   37353             : 
   37354             :                const bool synthesis_result =
   37355             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37356           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   37357             : 
   37358           0 :                if (synthesis_result)
   37359           0 :                   return result;
   37360           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37361           0 :                   return error_node();
   37362             : 
   37363             :                exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
   37364             : 
   37365           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   37366             :             }
   37367             : 
   37368           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37369             :                                          const details::operator_type o0,
   37370             :                                          const details::operator_type o1,
   37371             :                                          const details::operator_type o2)
   37372             :             {
   37373           0 :                return details::build_string()
   37374           0 :                   << "t"  << expr_gen.to_str(o0)
   37375           0 :                   << "(t" << expr_gen.to_str(o1)
   37376           0 :                   << "(t" << expr_gen.to_str(o2)
   37377           0 :                   << "t))";
   37378             :             }
   37379             :          };
   37380             : 
   37381             :          struct synthesize_vocovoc_expression1
   37382             :          {
   37383             :             typedef typename vocovoc_t::type1 node_type;
   37384             :             typedef typename vocovoc_t::sf4_type sf4_type;
   37385             :             typedef typename node_type::T0 T0;
   37386             :             typedef typename node_type::T1 T1;
   37387             :             typedef typename node_type::T2 T2;
   37388             :             typedef typename node_type::T3 T3;
   37389             : 
   37390           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37391             :                                                       const details::operator_type& operation,
   37392             :                                                       expression_node_ptr (&branch)[2])
   37393             :             {
   37394             :                // v0 o0 (c0 o1 (v1 o2 c2))
   37395             :                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
   37396             : 
   37397           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
   37398           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37399           0 :                const Type  c0 = covoc->t0();
   37400           0 :                const Type& v1 = covoc->t1();
   37401           0 :                const Type  c1 = covoc->t2();
   37402           0 :                const details::operator_type o0 = operation;
   37403           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
   37404           0 :                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
   37405             : 
   37406           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37407           0 :                binary_functor_t f1 = covoc->f0();
   37408           0 :                binary_functor_t f2 = covoc->f1();
   37409             : 
   37410           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37411             : 
   37412           0 :                expression_node_ptr result = error_node();
   37413             : 
   37414             :                const bool synthesis_result =
   37415             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37416           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   37417             : 
   37418           0 :                if (synthesis_result)
   37419           0 :                   return result;
   37420           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37421           0 :                   return error_node();
   37422             : 
   37423             :                exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
   37424             : 
   37425           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   37426             :             }
   37427             : 
   37428           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37429             :                                          const details::operator_type o0,
   37430             :                                          const details::operator_type o1,
   37431             :                                          const details::operator_type o2)
   37432             :             {
   37433           0 :                return details::build_string()
   37434           0 :                   << "t"  << expr_gen.to_str(o0)
   37435           0 :                   << "(t" << expr_gen.to_str(o1)
   37436           0 :                   << "(t" << expr_gen.to_str(o2)
   37437           0 :                   << "t))";
   37438             :             }
   37439             :          };
   37440             : 
   37441             :          struct synthesize_covovoc_expression1
   37442             :          {
   37443             :             typedef typename covovoc_t::type1 node_type;
   37444             :             typedef typename covovoc_t::sf4_type sf4_type;
   37445             :             typedef typename node_type::T0 T0;
   37446             :             typedef typename node_type::T1 T1;
   37447             :             typedef typename node_type::T2 T2;
   37448             :             typedef typename node_type::T3 T3;
   37449           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37450             :                                                       const details::operator_type& operation,
   37451             :                                                       expression_node_ptr (&branch)[2])
   37452             :             {
   37453             :                // c0 o0 (v0 o1 (v1 o2 c1))
   37454             :                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
   37455             : 
   37456           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   37457           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   37458           0 :                const Type& v0 = vovoc->t0();
   37459           0 :                const Type& v1 = vovoc->t1();
   37460           0 :                const Type  c1 = vovoc->t2();
   37461           0 :                const details::operator_type o0 = operation;
   37462           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   37463           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   37464             : 
   37465           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37466           0 :                binary_functor_t f1 = vovoc->f0();
   37467           0 :                binary_functor_t f2 = vovoc->f1();
   37468             : 
   37469           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37470           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37471             : 
   37472           0 :                expression_node_ptr result = error_node();
   37473             : 
   37474             :                const bool synthesis_result =
   37475             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37476           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   37477             : 
   37478           0 :                if (synthesis_result)
   37479           0 :                   return result;
   37480           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37481           0 :                   return error_node();
   37482             : 
   37483             :                exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
   37484             : 
   37485           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   37486             :             }
   37487             : 
   37488           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37489             :                                          const details::operator_type o0,
   37490             :                                          const details::operator_type o1,
   37491             :                                          const details::operator_type o2)
   37492             :             {
   37493           0 :                return details::build_string()
   37494           0 :                   << "t"  << expr_gen.to_str(o0)
   37495           0 :                   << "(t" << expr_gen.to_str(o1)
   37496           0 :                   << "(t" << expr_gen.to_str(o2)
   37497           0 :                   << "t))";
   37498             :             }
   37499             :          };
   37500             : 
   37501             :          struct synthesize_vococov_expression1
   37502             :          {
   37503             :             typedef typename vococov_t::type1 node_type;
   37504             :             typedef typename vococov_t::sf4_type sf4_type;
   37505             :             typedef typename node_type::T0 T0;
   37506             :             typedef typename node_type::T1 T1;
   37507             :             typedef typename node_type::T2 T2;
   37508             :             typedef typename node_type::T3 T3;
   37509             : 
   37510           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37511             :                                                       const details::operator_type& operation,
   37512             :                                                       expression_node_ptr (&branch)[2])
   37513             :             {
   37514             :                // v0 o0 (c0 o1 (c1 o2 v1))
   37515             :                typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
   37516             : 
   37517           0 :                const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
   37518           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37519           0 :                const Type  c0 = cocov->t0();
   37520           0 :                const Type  c1 = cocov->t1();
   37521           0 :                const Type& v1 = cocov->t2();
   37522           0 :                const details::operator_type o0 = operation;
   37523           0 :                const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
   37524           0 :                const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
   37525             : 
   37526           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37527           0 :                binary_functor_t f1 = cocov->f0();
   37528           0 :                binary_functor_t f2 = cocov->f1();
   37529             : 
   37530           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37531             : 
   37532           0 :                expression_node_ptr result = error_node();
   37533             : 
   37534             :                const bool synthesis_result =
   37535             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37536           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
   37537             : 
   37538           0 :                if (synthesis_result)
   37539           0 :                   return result;
   37540           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37541           0 :                   return error_node();
   37542             : 
   37543             :                exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
   37544             : 
   37545           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
   37546             :             }
   37547             : 
   37548           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37549             :                                          const details::operator_type o0,
   37550             :                                          const details::operator_type o1,
   37551             :                                          const details::operator_type o2)
   37552             :             {
   37553           0 :                return details::build_string()
   37554           0 :                   << "t"  << expr_gen.to_str(o0)
   37555           0 :                   << "(t" << expr_gen.to_str(o1)
   37556           0 :                   << "(t" << expr_gen.to_str(o2)
   37557           0 :                   << "t))";
   37558             :             }
   37559             :          };
   37560             : 
   37561             :          struct synthesize_vovovov_expression2
   37562             :          {
   37563             :             typedef typename vovovov_t::type2 node_type;
   37564             :             typedef typename vovovov_t::sf4_type sf4_type;
   37565             :             typedef typename node_type::T0 T0;
   37566             :             typedef typename node_type::T1 T1;
   37567             :             typedef typename node_type::T2 T2;
   37568             :             typedef typename node_type::T3 T3;
   37569             : 
   37570           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37571             :                                                       const details::operator_type& operation,
   37572             :                                                       expression_node_ptr (&branch)[2])
   37573             :             {
   37574             :                // v0 o0 ((v1 o1 v2) o2 v3)
   37575             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   37576             : 
   37577           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   37578           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37579           0 :                const Type& v1 = vovov->t0();
   37580           0 :                const Type& v2 = vovov->t1();
   37581           0 :                const Type& v3 = vovov->t2();
   37582           0 :                const details::operator_type o0 = operation;
   37583           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   37584           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   37585             : 
   37586           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37587           0 :                binary_functor_t f1 = vovov->f0();
   37588           0 :                binary_functor_t f2 = vovov->f1();
   37589             : 
   37590           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37591             : 
   37592           0 :                expression_node_ptr result = error_node();
   37593             : 
   37594             :                const bool synthesis_result =
   37595             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37596           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   37597             : 
   37598           0 :                if (synthesis_result)
   37599           0 :                   return result;
   37600           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37601           0 :                   return error_node();
   37602             : 
   37603             :                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
   37604             : 
   37605           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   37606             :             }
   37607             : 
   37608           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37609             :                                          const details::operator_type o0,
   37610             :                                          const details::operator_type o1,
   37611             :                                          const details::operator_type o2)
   37612             :             {
   37613           0 :                return details::build_string()
   37614           0 :                   << "t"   << expr_gen.to_str(o0)
   37615           0 :                   << "((t" << expr_gen.to_str(o1)
   37616           0 :                   << "t)"  << expr_gen.to_str(o2)
   37617           0 :                   << "t)";
   37618             :             }
   37619             :          };
   37620             : 
   37621             :          struct synthesize_vovovoc_expression2
   37622             :          {
   37623             :             typedef typename vovovoc_t::type2 node_type;
   37624             :             typedef typename vovovoc_t::sf4_type sf4_type;
   37625             :             typedef typename node_type::T0 T0;
   37626             :             typedef typename node_type::T1 T1;
   37627             :             typedef typename node_type::T2 T2;
   37628             :             typedef typename node_type::T3 T3;
   37629             : 
   37630           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37631             :                                                       const details::operator_type& operation,
   37632             :                                                       expression_node_ptr (&branch)[2])
   37633             :             {
   37634             :                // v0 o0 ((v1 o1 v2) o2 c)
   37635             :                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
   37636             : 
   37637           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   37638           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37639           0 :                const Type& v1 = vovoc->t0();
   37640           0 :                const Type& v2 = vovoc->t1();
   37641           0 :                const Type   c = vovoc->t2();
   37642           0 :                const details::operator_type o0 = operation;
   37643           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   37644           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   37645             : 
   37646           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37647           0 :                binary_functor_t f1 = vovoc->f0();
   37648           0 :                binary_functor_t f2 = vovoc->f1();
   37649             : 
   37650           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37651             : 
   37652           0 :                expression_node_ptr result = error_node();
   37653             : 
   37654             :                const bool synthesis_result =
   37655             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37656           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   37657             : 
   37658           0 :                if (synthesis_result)
   37659           0 :                   return result;
   37660           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37661           0 :                   return error_node();
   37662             : 
   37663             :                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
   37664             : 
   37665           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   37666             :             }
   37667             : 
   37668           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37669             :                                          const details::operator_type o0,
   37670             :                                          const details::operator_type o1,
   37671             :                                          const details::operator_type o2)
   37672             :             {
   37673           0 :                return details::build_string()
   37674           0 :                   << "t"   << expr_gen.to_str(o0)
   37675           0 :                   << "((t" << expr_gen.to_str(o1)
   37676           0 :                   << "t)"  << expr_gen.to_str(o2)
   37677           0 :                   << "t)";
   37678             :             }
   37679             :          };
   37680             : 
   37681             :          struct synthesize_vovocov_expression2
   37682             :          {
   37683             :             typedef typename vovocov_t::type2 node_type;
   37684             :             typedef typename vovocov_t::sf4_type sf4_type;
   37685             :             typedef typename node_type::T0 T0;
   37686             :             typedef typename node_type::T1 T1;
   37687             :             typedef typename node_type::T2 T2;
   37688             :             typedef typename node_type::T3 T3;
   37689             : 
   37690           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37691             :                                                       const details::operator_type& operation,
   37692             :                                                       expression_node_ptr (&branch)[2])
   37693             :             {
   37694             :                // v0 o0 ((v1 o1 c) o2 v2)
   37695             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   37696             : 
   37697           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   37698           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37699           0 :                const Type& v1 = vocov->t0();
   37700           0 :                const Type   c = vocov->t1();
   37701           0 :                const Type& v2 = vocov->t2();
   37702           0 :                const details::operator_type o0 = operation;
   37703           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   37704           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   37705             : 
   37706           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37707           0 :                binary_functor_t f1 = vocov->f0();
   37708           0 :                binary_functor_t f2 = vocov->f1();
   37709             : 
   37710           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37711             : 
   37712           0 :                expression_node_ptr result = error_node();
   37713             : 
   37714             :                const bool synthesis_result =
   37715             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37716           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   37717             : 
   37718           0 :                if (synthesis_result)
   37719           0 :                   return result;
   37720           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37721           0 :                   return error_node();
   37722             : 
   37723             :                exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
   37724             : 
   37725           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   37726             :             }
   37727             : 
   37728           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37729             :                                          const details::operator_type o0,
   37730             :                                          const details::operator_type o1,
   37731             :                                          const details::operator_type o2)
   37732             :             {
   37733           0 :                return details::build_string()
   37734           0 :                   << "t"   << expr_gen.to_str(o0)
   37735           0 :                   << "((t" << expr_gen.to_str(o1)
   37736           0 :                   << "t)"  << expr_gen.to_str(o2)
   37737           0 :                   << "t)";
   37738             :             }
   37739             :          };
   37740             : 
   37741             :          struct synthesize_vocovov_expression2
   37742             :          {
   37743             :             typedef typename vocovov_t::type2 node_type;
   37744             :             typedef typename vocovov_t::sf4_type sf4_type;
   37745             :             typedef typename node_type::T0 T0;
   37746             :             typedef typename node_type::T1 T1;
   37747             :             typedef typename node_type::T2 T2;
   37748             :             typedef typename node_type::T3 T3;
   37749             : 
   37750           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37751             :                                                       const details::operator_type& operation,
   37752             :                                                       expression_node_ptr (&branch)[2])
   37753             :             {
   37754             :                // v0 o0 ((c o1 v1) o2 v2)
   37755             :                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
   37756             : 
   37757           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
   37758           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37759           0 :                const Type   c = covov->t0();
   37760           0 :                const Type& v1 = covov->t1();
   37761           0 :                const Type& v2 = covov->t2();
   37762           0 :                const details::operator_type o0 = operation;
   37763           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
   37764           0 :                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
   37765             : 
   37766           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37767           0 :                binary_functor_t f1 = covov->f0();
   37768           0 :                binary_functor_t f2 = covov->f1();
   37769             : 
   37770           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37771             : 
   37772           0 :                expression_node_ptr result = error_node();
   37773             : 
   37774             :                const bool synthesis_result =
   37775             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37776           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   37777             : 
   37778           0 :                if (synthesis_result)
   37779           0 :                   return result;
   37780           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37781           0 :                   return error_node();
   37782             : 
   37783             :                exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
   37784             : 
   37785           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   37786             :             }
   37787             : 
   37788           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37789             :                                          const details::operator_type o0,
   37790             :                                          const details::operator_type o1,
   37791             :                                          const details::operator_type o2)
   37792             :             {
   37793           0 :                return details::build_string()
   37794           0 :                   << "t"   << expr_gen.to_str(o0)
   37795           0 :                   << "((t" << expr_gen.to_str(o1)
   37796           0 :                   << "t)"  << expr_gen.to_str(o2)
   37797           0 :                   << "t)";
   37798             :             }
   37799             :          };
   37800             : 
   37801             :          struct synthesize_covovov_expression2
   37802             :          {
   37803             :             typedef typename covovov_t::type2 node_type;
   37804             :             typedef typename covovov_t::sf4_type sf4_type;
   37805             :             typedef typename node_type::T0 T0;
   37806             :             typedef typename node_type::T1 T1;
   37807             :             typedef typename node_type::T2 T2;
   37808             :             typedef typename node_type::T3 T3;
   37809             : 
   37810           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37811             :                                                       const details::operator_type& operation,
   37812             :                                                       expression_node_ptr (&branch)[2])
   37813             :             {
   37814             :                // c o0 ((v1 o1 v2) o2 v3)
   37815             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   37816             : 
   37817           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
   37818           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
   37819           0 :                const Type& v0 = vovov->t0();
   37820           0 :                const Type& v1 = vovov->t1();
   37821           0 :                const Type& v2 = vovov->t2();
   37822           0 :                const details::operator_type o0 = operation;
   37823           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
   37824           0 :                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
   37825             : 
   37826           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37827           0 :                binary_functor_t f1 = vovov->f0();
   37828           0 :                binary_functor_t f2 = vovov->f1();
   37829             : 
   37830           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37831           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37832             : 
   37833           0 :                expression_node_ptr result = error_node();
   37834             : 
   37835             :                const bool synthesis_result =
   37836             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37837           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   37838             : 
   37839           0 :                if (synthesis_result)
   37840           0 :                   return result;
   37841           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37842           0 :                   return error_node();
   37843             : 
   37844             :                exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
   37845             : 
   37846           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   37847             :             }
   37848             : 
   37849           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37850             :                                          const details::operator_type o0,
   37851             :                                          const details::operator_type o1,
   37852             :                                          const details::operator_type o2)
   37853             :             {
   37854           0 :                return details::build_string()
   37855           0 :                   << "t"   << expr_gen.to_str(o0)
   37856           0 :                   << "((t" << expr_gen.to_str(o1)
   37857           0 :                   << "t)"  << expr_gen.to_str(o2)
   37858           0 :                   << "t)";
   37859             :             }
   37860             :         };
   37861             : 
   37862             :          struct synthesize_covocov_expression2
   37863             :          {
   37864             :             typedef typename covocov_t::type2 node_type;
   37865             :             typedef typename covocov_t::sf4_type sf4_type;
   37866             :             typedef typename node_type::T0 T0;
   37867             :             typedef typename node_type::T1 T1;
   37868             :             typedef typename node_type::T2 T2;
   37869             :             typedef typename node_type::T3 T3;
   37870             : 
   37871           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37872             :                                                       const details::operator_type& operation,
   37873             :                                                       expression_node_ptr (&branch)[2])
   37874             :             {
   37875             :                // c0 o0 ((v0 o1 c1) o2 v1)
   37876             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   37877             : 
   37878           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
   37879           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   37880           0 :                const Type& v0 = vocov->t0();
   37881           0 :                const Type  c1 = vocov->t1();
   37882           0 :                const Type& v1 = vocov->t2();
   37883           0 :                const details::operator_type o0 = operation;
   37884           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
   37885           0 :                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
   37886             : 
   37887           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37888           0 :                binary_functor_t f1 = vocov->f0();
   37889           0 :                binary_functor_t f2 = vocov->f1();
   37890             : 
   37891           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   37892           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37893             : 
   37894           0 :                expression_node_ptr result = error_node();
   37895             : 
   37896             :                const bool synthesis_result =
   37897             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37898           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   37899             : 
   37900           0 :                if (synthesis_result)
   37901           0 :                   return result;
   37902           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37903           0 :                   return error_node();
   37904             : 
   37905             :                exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
   37906             : 
   37907           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   37908             :             }
   37909             : 
   37910           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37911             :                                          const details::operator_type o0,
   37912             :                                          const details::operator_type o1,
   37913             :                                          const details::operator_type o2)
   37914             :             {
   37915           0 :                return details::build_string()
   37916           0 :                   << "t"   << expr_gen.to_str(o0)
   37917           0 :                   << "((t" << expr_gen.to_str(o1)
   37918           0 :                   << "t)"  << expr_gen.to_str(o2)
   37919           0 :                   << "t)";
   37920             :             }
   37921             :          };
   37922             : 
   37923             :          struct synthesize_vocovoc_expression2
   37924             :          {
   37925             :             typedef typename vocovoc_t::type2 node_type;
   37926             :             typedef typename vocovoc_t::sf4_type sf4_type;
   37927             :             typedef typename node_type::T0 T0;
   37928             :             typedef typename node_type::T1 T1;
   37929             :             typedef typename node_type::T2 T2;
   37930             :             typedef typename node_type::T3 T3;
   37931             : 
   37932           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37933             :                                                       const details::operator_type& operation,
   37934             :                                                       expression_node_ptr (&branch)[2])
   37935             :             {
   37936             :                // v0 o0 ((c0 o1 v1) o2 c1)
   37937             :                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
   37938             : 
   37939           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
   37940           0 :                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
   37941           0 :                const Type  c0 = covoc->t0();
   37942           0 :                const Type& v1 = covoc->t1();
   37943           0 :                const Type  c1 = covoc->t2();
   37944           0 :                const details::operator_type o0 = operation;
   37945           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
   37946           0 :                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
   37947             : 
   37948           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   37949           0 :                binary_functor_t f1 = covoc->f0();
   37950           0 :                binary_functor_t f2 = covoc->f1();
   37951             : 
   37952           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   37953             : 
   37954           0 :                expression_node_ptr result = error_node();
   37955             : 
   37956             :                const bool synthesis_result =
   37957             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   37958           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   37959             : 
   37960           0 :                if (synthesis_result)
   37961           0 :                   return result;
   37962           0 :                else if (!expr_gen.valid_operator(o0,f0))
   37963           0 :                   return error_node();
   37964             : 
   37965             :                exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
   37966             : 
   37967           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   37968             :             }
   37969             : 
   37970           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   37971             :                                          const details::operator_type o0,
   37972             :                                          const details::operator_type o1,
   37973             :                                          const details::operator_type o2)
   37974             :             {
   37975           0 :                return details::build_string()
   37976           0 :                   << "t"   << expr_gen.to_str(o0)
   37977           0 :                   << "((t" << expr_gen.to_str(o1)
   37978           0 :                   << "t)"  << expr_gen.to_str(o2)
   37979           0 :                   << "t)";
   37980             :             }
   37981             :          };
   37982             : 
   37983             :          struct synthesize_covovoc_expression2
   37984             :          {
   37985             :             typedef typename covovoc_t::type2 node_type;
   37986             :             typedef typename covovoc_t::sf4_type sf4_type;
   37987             :             typedef typename node_type::T0 T0;
   37988             :             typedef typename node_type::T1 T1;
   37989             :             typedef typename node_type::T2 T2;
   37990             :             typedef typename node_type::T3 T3;
   37991             : 
   37992           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   37993             :                                                       const details::operator_type& operation,
   37994             :                                                       expression_node_ptr (&branch)[2])
   37995             :             {
   37996             :                // c0 o0 ((v0 o1 v1) o2 c1)
   37997             :                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
   37998             : 
   37999           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
   38000           0 :                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
   38001           0 :                const Type& v0 = vovoc->t0();
   38002           0 :                const Type& v1 = vovoc->t1();
   38003           0 :                const Type  c1 = vovoc->t2();
   38004           0 :                const details::operator_type o0 = operation;
   38005           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
   38006           0 :                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
   38007             : 
   38008           0 :                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
   38009           0 :                binary_functor_t f1 = vovoc->f0();
   38010           0 :                binary_functor_t f2 = vovoc->f1();
   38011             : 
   38012           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38013           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38014             : 
   38015           0 :                expression_node_ptr result = error_node();
   38016             : 
   38017             :                const bool synthesis_result =
   38018             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38019           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   38020             : 
   38021           0 :                if (synthesis_result)
   38022           0 :                   return result;
   38023           0 :                else if (!expr_gen.valid_operator(o0,f0))
   38024           0 :                   return error_node();
   38025             : 
   38026             :                exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
   38027             : 
   38028           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   38029             :             }
   38030             : 
   38031           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38032             :                                          const details::operator_type o0,
   38033             :                                          const details::operator_type o1,
   38034             :                                          const details::operator_type o2)
   38035             :             {
   38036           0 :                return details::build_string()
   38037           0 :                   << "t"   << expr_gen.to_str(o0)
   38038           0 :                   << "((t" << expr_gen.to_str(o1)
   38039           0 :                   << "t)"  << expr_gen.to_str(o2)
   38040           0 :                   << "t)";
   38041             :             }
   38042             :          };
   38043             : 
   38044             :          struct synthesize_vococov_expression2
   38045             :          {
   38046             :             typedef typename vococov_t::type2 node_type;
   38047             :             static inline expression_node_ptr process(expression_generator<Type>&,
   38048             :                                                       const details::operator_type&,
   38049             :                                                       expression_node_ptr (&)[2])
   38050             :             {
   38051             :                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
   38052             :                exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
   38053             :                return error_node();
   38054             :             }
   38055             : 
   38056             :             static inline std::string id(expression_generator<Type>&,
   38057             :                                          const details::operator_type,
   38058             :                                          const details::operator_type,
   38059             :                                          const details::operator_type)
   38060             :             {
   38061             :                return "INVALID";
   38062             :             }
   38063             :          };
   38064             : 
   38065             :          struct synthesize_vovovov_expression3
   38066             :          {
   38067             :             typedef typename vovovov_t::type3 node_type;
   38068             :             typedef typename vovovov_t::sf4_type sf4_type;
   38069             :             typedef typename node_type::T0 T0;
   38070             :             typedef typename node_type::T1 T1;
   38071             :             typedef typename node_type::T2 T2;
   38072             :             typedef typename node_type::T3 T3;
   38073             : 
   38074           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38075             :                                                       const details::operator_type& operation,
   38076             :                                                       expression_node_ptr (&branch)[2])
   38077             :             {
   38078             :                // ((v0 o0 v1) o1 v2) o2 v3
   38079             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   38080             : 
   38081           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   38082           0 :                const Type& v0 = vovov->t0();
   38083           0 :                const Type& v1 = vovov->t1();
   38084           0 :                const Type& v2 = vovov->t2();
   38085           0 :                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38086           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   38087           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   38088           0 :                const details::operator_type o2 = operation;
   38089             : 
   38090           0 :                binary_functor_t f0 = vovov->f0();
   38091           0 :                binary_functor_t f1 = vovov->f1();
   38092           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38093             : 
   38094           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38095             : 
   38096           0 :                expression_node_ptr result = error_node();
   38097             : 
   38098             :                const bool synthesis_result =
   38099             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38100           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   38101             : 
   38102           0 :                if (synthesis_result)
   38103           0 :                   return result;
   38104           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38105           0 :                   return error_node();
   38106             : 
   38107             :                exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
   38108             : 
   38109           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   38110             :             }
   38111             : 
   38112           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38113             :                                          const details::operator_type o0,
   38114             :                                          const details::operator_type o1,
   38115             :                                          const details::operator_type o2)
   38116             :             {
   38117           0 :                return details::build_string()
   38118           0 :                   << "((t" << expr_gen.to_str(o0)
   38119           0 :                   << "t)"  << expr_gen.to_str(o1)
   38120           0 :                   << "t)"  << expr_gen.to_str(o2)
   38121           0 :                   << "t";
   38122             :             }
   38123             :          };
   38124             : 
   38125             :          struct synthesize_vovovoc_expression3
   38126             :          {
   38127             :             typedef typename vovovoc_t::type3 node_type;
   38128             :             typedef typename vovovoc_t::sf4_type sf4_type;
   38129             :             typedef typename node_type::T0 T0;
   38130             :             typedef typename node_type::T1 T1;
   38131             :             typedef typename node_type::T2 T2;
   38132             :             typedef typename node_type::T3 T3;
   38133             : 
   38134           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38135             :                                                       const details::operator_type& operation,
   38136             :                                                       expression_node_ptr (&branch)[2])
   38137             :             {
   38138             :                // ((v0 o0 v1) o1 v2) o2 c
   38139             :                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
   38140             : 
   38141           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   38142           0 :                const Type& v0 = vovov->t0();
   38143           0 :                const Type& v1 = vovov->t1();
   38144           0 :                const Type& v2 = vovov->t2();
   38145           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   38146           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   38147           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   38148           0 :                const details::operator_type o2 = operation;
   38149             : 
   38150           0 :                binary_functor_t f0 = vovov->f0();
   38151           0 :                binary_functor_t f1 = vovov->f1();
   38152           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38153             : 
   38154           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38155           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38156             : 
   38157           0 :                expression_node_ptr result = error_node();
   38158             : 
   38159             :                const bool synthesis_result =
   38160             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38161           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   38162             : 
   38163           0 :                if (synthesis_result)
   38164           0 :                   return result;
   38165           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38166           0 :                   return error_node();
   38167             : 
   38168             :                exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
   38169             : 
   38170           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   38171             :             }
   38172             : 
   38173           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38174             :                                          const details::operator_type o0,
   38175             :                                          const details::operator_type o1,
   38176             :                                          const details::operator_type o2)
   38177             :             {
   38178           0 :                return details::build_string()
   38179           0 :                   << "((t" << expr_gen.to_str(o0)
   38180           0 :                   << "t)"  << expr_gen.to_str(o1)
   38181           0 :                   << "t)"  << expr_gen.to_str(o2)
   38182           0 :                   << "t";
   38183             :             }
   38184             :          };
   38185             : 
   38186             :          struct synthesize_vovocov_expression3
   38187             :          {
   38188             :             typedef typename vovocov_t::type3 node_type;
   38189             :             typedef typename vovocov_t::sf4_type sf4_type;
   38190             :             typedef typename node_type::T0 T0;
   38191             :             typedef typename node_type::T1 T1;
   38192             :             typedef typename node_type::T2 T2;
   38193             :             typedef typename node_type::T3 T3;
   38194             : 
   38195           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38196             :                                                       const details::operator_type& operation,
   38197             :                                                       expression_node_ptr (&branch)[2])
   38198             :             {
   38199             :                // ((v0 o0 v1) o1 c) o2 v2
   38200             :                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
   38201             : 
   38202           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
   38203           0 :                const Type& v0 = vovoc->t0();
   38204           0 :                const Type& v1 = vovoc->t1();
   38205           0 :                const Type   c = vovoc->t2();
   38206           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38207           0 :                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
   38208           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
   38209           0 :                const details::operator_type o2 = operation;
   38210             : 
   38211           0 :                binary_functor_t f0 = vovoc->f0();
   38212           0 :                binary_functor_t f1 = vovoc->f1();
   38213           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38214             : 
   38215           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38216             : 
   38217           0 :                expression_node_ptr result = error_node();
   38218             : 
   38219             :                const bool synthesis_result =
   38220             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38221           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   38222             : 
   38223           0 :                if (synthesis_result)
   38224           0 :                   return result;
   38225           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38226           0 :                   return error_node();
   38227             : 
   38228             :                exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
   38229             : 
   38230           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   38231             :             }
   38232             : 
   38233           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38234             :                                          const details::operator_type o0,
   38235             :                                          const details::operator_type o1,
   38236             :                                          const details::operator_type o2)
   38237             :             {
   38238           0 :                return details::build_string()
   38239           0 :                   << "((t" << expr_gen.to_str(o0)
   38240           0 :                   << "t)"  << expr_gen.to_str(o1)
   38241           0 :                   << "t)"  << expr_gen.to_str(o2)
   38242           0 :                   << "t";
   38243             :             }
   38244             :          };
   38245             : 
   38246             :          struct synthesize_vocovov_expression3
   38247             :          {
   38248             :             typedef typename vocovov_t::type3 node_type;
   38249             :             typedef typename vocovov_t::sf4_type sf4_type;
   38250             :             typedef typename node_type::T0 T0;
   38251             :             typedef typename node_type::T1 T1;
   38252             :             typedef typename node_type::T2 T2;
   38253             :             typedef typename node_type::T3 T3;
   38254             : 
   38255           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38256             :                                                       const details::operator_type& operation,
   38257             :                                                       expression_node_ptr (&branch)[2])
   38258             :             {
   38259             :                // ((v0 o0 c) o1 v1) o2 v2
   38260             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   38261             : 
   38262           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   38263           0 :                const Type& v0 = vocov->t0();
   38264           0 :                const Type   c = vocov->t1();
   38265           0 :                const Type& v1 = vocov->t2();
   38266           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38267           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   38268           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   38269           0 :                const details::operator_type o2 = operation;
   38270             : 
   38271           0 :                binary_functor_t f0 = vocov->f0();
   38272           0 :                binary_functor_t f1 = vocov->f1();
   38273           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38274             : 
   38275           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38276             : 
   38277           0 :                expression_node_ptr result = error_node();
   38278             : 
   38279             :                const bool synthesis_result =
   38280             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38281           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   38282             : 
   38283           0 :                if (synthesis_result)
   38284           0 :                   return result;
   38285           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38286           0 :                   return error_node();
   38287             : 
   38288             :                exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
   38289             : 
   38290           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   38291             :             }
   38292             : 
   38293           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38294             :                                          const details::operator_type o0,
   38295             :                                          const details::operator_type o1,
   38296             :                                          const details::operator_type o2)
   38297             :             {
   38298           0 :                return details::build_string()
   38299           0 :                   << "((t" << expr_gen.to_str(o0)
   38300           0 :                   << "t)"  << expr_gen.to_str(o1)
   38301           0 :                   << "t)"  << expr_gen.to_str(o2)
   38302           0 :                   << "t";
   38303             :             }
   38304             :          };
   38305             : 
   38306             :          struct synthesize_covovov_expression3
   38307             :          {
   38308             :             typedef typename covovov_t::type3 node_type;
   38309             :             typedef typename covovov_t::sf4_type sf4_type;
   38310             :             typedef typename node_type::T0 T0;
   38311             :             typedef typename node_type::T1 T1;
   38312             :             typedef typename node_type::T2 T2;
   38313             :             typedef typename node_type::T3 T3;
   38314             : 
   38315           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38316             :                                                       const details::operator_type& operation,
   38317             :                                                       expression_node_ptr (&branch)[2])
   38318             :             {
   38319             :                // ((c o0 v0) o1 v1) o2 v2
   38320             :                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
   38321             : 
   38322           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   38323           0 :                const Type   c = covov->t0();
   38324           0 :                const Type& v0 = covov->t1();
   38325           0 :                const Type& v1 = covov->t2();
   38326           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38327           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   38328           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   38329           0 :                const details::operator_type o2 = operation;
   38330             : 
   38331           0 :                binary_functor_t f0 = covov->f0();
   38332           0 :                binary_functor_t f1 = covov->f1();
   38333           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38334             : 
   38335           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38336             : 
   38337           0 :                expression_node_ptr result = error_node();
   38338             : 
   38339             :                const bool synthesis_result =
   38340             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38341           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   38342             : 
   38343           0 :                if (synthesis_result)
   38344           0 :                   return result;
   38345           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38346           0 :                   return error_node();
   38347             : 
   38348             :                exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
   38349             : 
   38350           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   38351             :             }
   38352             : 
   38353           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38354             :                                          const details::operator_type o0,
   38355             :                                          const details::operator_type o1,
   38356             :                                          const details::operator_type o2)
   38357             :             {
   38358           0 :                return details::build_string()
   38359           0 :                   << "((t" << expr_gen.to_str(o0)
   38360           0 :                   << "t)"  << expr_gen.to_str(o1)
   38361           0 :                   << "t)"  << expr_gen.to_str(o2)
   38362           0 :                   << "t";
   38363             :             }
   38364             :          };
   38365             : 
   38366             :          struct synthesize_covocov_expression3
   38367             :          {
   38368             :             typedef typename covocov_t::type3 node_type;
   38369             :             typedef typename covocov_t::sf4_type sf4_type;
   38370             :             typedef typename node_type::T0 T0;
   38371             :             typedef typename node_type::T1 T1;
   38372             :             typedef typename node_type::T2 T2;
   38373             :             typedef typename node_type::T3 T3;
   38374             : 
   38375           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38376             :                                                       const details::operator_type& operation,
   38377             :                                                       expression_node_ptr (&branch)[2])
   38378             :             {
   38379             :                // ((c0 o0 v0) o1 c1) o2 v1
   38380             :                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
   38381             : 
   38382           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
   38383           0 :                const Type  c0 = covoc->t0();
   38384           0 :                const Type& v0 = covoc->t1();
   38385           0 :                const Type  c1 = covoc->t2();
   38386           0 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38387           0 :                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
   38388           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
   38389           0 :                const details::operator_type o2 = operation;
   38390             : 
   38391           0 :                binary_functor_t f0 = covoc->f0();
   38392           0 :                binary_functor_t f1 = covoc->f1();
   38393           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38394             : 
   38395           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38396             : 
   38397           0 :                expression_node_ptr result = error_node();
   38398             : 
   38399             :                const bool synthesis_result =
   38400             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38401           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   38402             : 
   38403           0 :                if (synthesis_result)
   38404           0 :                   return result;
   38405           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38406           0 :                   return error_node();
   38407             : 
   38408             :                exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
   38409             : 
   38410           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   38411             :             }
   38412             : 
   38413           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38414             :                                          const details::operator_type o0,
   38415             :                                          const details::operator_type o1,
   38416             :                                          const details::operator_type o2)
   38417             :             {
   38418           0 :                return details::build_string()
   38419           0 :                   << "((t" << expr_gen.to_str(o0)
   38420           0 :                   << "t)"  << expr_gen.to_str(o1)
   38421           0 :                   << "t)"  << expr_gen.to_str(o2)
   38422           0 :                   << "t";
   38423             :             }
   38424             :          };
   38425             : 
   38426             :          struct synthesize_vocovoc_expression3
   38427             :          {
   38428             :             typedef typename vocovoc_t::type3 node_type;
   38429             :             typedef typename vocovoc_t::sf4_type sf4_type;
   38430             :             typedef typename node_type::T0 T0;
   38431             :             typedef typename node_type::T1 T1;
   38432             :             typedef typename node_type::T2 T2;
   38433             :             typedef typename node_type::T3 T3;
   38434             : 
   38435           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38436             :                                                       const details::operator_type& operation,
   38437             :                                                       expression_node_ptr (&branch)[2])
   38438             :             {
   38439             :                // ((v0 o0 c0) o1 v1) o2 c1
   38440             :                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
   38441             : 
   38442           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   38443           0 :                const Type& v0 = vocov->t0();
   38444           0 :                const Type  c0 = vocov->t1();
   38445           0 :                const Type& v1 = vocov->t2();
   38446           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   38447           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   38448           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   38449           0 :                const details::operator_type o2 = operation;
   38450             : 
   38451           0 :                binary_functor_t f0 = vocov->f0();
   38452           0 :                binary_functor_t f1 = vocov->f1();
   38453           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38454             : 
   38455           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38456           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38457             : 
   38458           0 :                expression_node_ptr result = error_node();
   38459             : 
   38460             :                const bool synthesis_result =
   38461             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38462           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   38463             : 
   38464           0 :                if (synthesis_result)
   38465           0 :                   return result;
   38466           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38467           0 :                   return error_node();
   38468             : 
   38469             :                exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
   38470             : 
   38471           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   38472             :             }
   38473             : 
   38474           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38475             :                                          const details::operator_type o0,
   38476             :                                          const details::operator_type o1,
   38477             :                                          const details::operator_type o2)
   38478             :             {
   38479           0 :                return details::build_string()
   38480           0 :                   << "((t" << expr_gen.to_str(o0)
   38481           0 :                   << "t)"  << expr_gen.to_str(o1)
   38482           0 :                   << "t)"  << expr_gen.to_str(o2)
   38483           0 :                   << "t";
   38484             :             }
   38485             :          };
   38486             : 
   38487             :          struct synthesize_covovoc_expression3
   38488             :          {
   38489             :             typedef typename covovoc_t::type3 node_type;
   38490             :             typedef typename covovoc_t::sf4_type sf4_type;
   38491             :             typedef typename node_type::T0 T0;
   38492             :             typedef typename node_type::T1 T1;
   38493             :             typedef typename node_type::T2 T2;
   38494             :             typedef typename node_type::T3 T3;
   38495             : 
   38496           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38497             :                                                       const details::operator_type& operation,
   38498             :                                                       expression_node_ptr (&branch)[2])
   38499             :             {
   38500             :                // ((c0 o0 v0) o1 v1) o2 c1
   38501             :                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
   38502             : 
   38503           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   38504           0 :                const Type  c0 = covov->t0();
   38505           0 :                const Type& v0 = covov->t1();
   38506           0 :                const Type& v1 = covov->t2();
   38507           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   38508           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   38509           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   38510           0 :                const details::operator_type o2 = operation;
   38511             : 
   38512           0 :                binary_functor_t f0 = covov->f0();
   38513           0 :                binary_functor_t f1 = covov->f1();
   38514           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38515             : 
   38516           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38517           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38518             : 
   38519           0 :                expression_node_ptr result = error_node();
   38520             : 
   38521             :                const bool synthesis_result =
   38522             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38523           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   38524             : 
   38525           0 :                if (synthesis_result)
   38526           0 :                   return result;
   38527           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38528           0 :                   return error_node();
   38529             : 
   38530             :                exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
   38531             : 
   38532           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   38533             :             }
   38534             : 
   38535           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38536             :                                          const details::operator_type o0,
   38537             :                                          const details::operator_type o1,
   38538             :                                          const details::operator_type o2)
   38539             :             {
   38540           0 :                return details::build_string()
   38541           0 :                   << "((t" << expr_gen.to_str(o0)
   38542           0 :                   << "t)"  << expr_gen.to_str(o1)
   38543           0 :                   << "t)"  << expr_gen.to_str(o2)
   38544           0 :                   << "t";
   38545             :             }
   38546             :          };
   38547             : 
   38548             :          struct synthesize_vococov_expression3
   38549             :          {
   38550             :             typedef typename vococov_t::type3 node_type;
   38551             :             typedef typename vococov_t::sf4_type sf4_type;
   38552             :             typedef typename node_type::T0 T0;
   38553             :             typedef typename node_type::T1 T1;
   38554             :             typedef typename node_type::T2 T2;
   38555             :             typedef typename node_type::T3 T3;
   38556             : 
   38557           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38558             :                                                       const details::operator_type& operation,
   38559             :                                                       expression_node_ptr (&branch)[2])
   38560             :             {
   38561             :                // ((v0 o0 c0) o1 c1) o2 v1
   38562             :                typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
   38563             : 
   38564           0 :                const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
   38565           0 :                const Type& v0 = vococ->t0();
   38566           0 :                const Type  c0 = vococ->t1();
   38567           0 :                const Type  c1 = vococ->t2();
   38568           0 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38569           0 :                const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
   38570           0 :                const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
   38571           0 :                const details::operator_type o2 = operation;
   38572             : 
   38573           0 :                binary_functor_t f0 = vococ->f0();
   38574           0 :                binary_functor_t f1 = vococ->f1();
   38575           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38576             : 
   38577           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38578             : 
   38579           0 :                expression_node_ptr result = error_node();
   38580             : 
   38581             :                const bool synthesis_result =
   38582             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38583           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
   38584             : 
   38585           0 :                if (synthesis_result)
   38586           0 :                   return result;
   38587           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38588           0 :                   return error_node();
   38589             : 
   38590             :                exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
   38591             : 
   38592           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
   38593             :             }
   38594             : 
   38595           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38596             :                                          const details::operator_type o0,
   38597             :                                          const details::operator_type o1,
   38598             :                                          const details::operator_type o2)
   38599             :             {
   38600           0 :                return details::build_string()
   38601           0 :                   << "((t" << expr_gen.to_str(o0)
   38602           0 :                   << "t)"  << expr_gen.to_str(o1)
   38603           0 :                   << "t)"  << expr_gen.to_str(o2)
   38604           0 :                   << "t";
   38605             :             }
   38606             :          };
   38607             : 
   38608             :          struct synthesize_vovovov_expression4
   38609             :          {
   38610             :             typedef typename vovovov_t::type4 node_type;
   38611             :             typedef typename vovovov_t::sf4_type sf4_type;
   38612             :             typedef typename node_type::T0 T0;
   38613             :             typedef typename node_type::T1 T1;
   38614             :             typedef typename node_type::T2 T2;
   38615             :             typedef typename node_type::T3 T3;
   38616             : 
   38617           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38618             :                                                       const details::operator_type& operation,
   38619             :                                                       expression_node_ptr (&branch)[2])
   38620             :             {
   38621             :                // (v0 o0 (v1 o1 v2)) o2 v3
   38622             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   38623             : 
   38624           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   38625           0 :                const Type& v0 = vovov->t0();
   38626           0 :                const Type& v1 = vovov->t1();
   38627           0 :                const Type& v2 = vovov->t2();
   38628           0 :                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38629           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   38630           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   38631           0 :                const details::operator_type o2 = operation;
   38632             : 
   38633           0 :                binary_functor_t f0 = vovov->f0();
   38634           0 :                binary_functor_t f1 = vovov->f1();
   38635           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38636             : 
   38637           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38638             : 
   38639           0 :                expression_node_ptr result = error_node();
   38640             : 
   38641             :                const bool synthesis_result =
   38642             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38643           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
   38644             : 
   38645           0 :                if (synthesis_result)
   38646           0 :                   return result;
   38647           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38648           0 :                   return error_node();
   38649             : 
   38650             :                exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
   38651             : 
   38652           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
   38653             :             }
   38654             : 
   38655           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38656             :                                          const details::operator_type o0,
   38657             :                                          const details::operator_type o1,
   38658             :                                          const details::operator_type o2)
   38659             :             {
   38660           0 :                return details::build_string()
   38661           0 :                   << "(t" << expr_gen.to_str(o0)
   38662           0 :                   << "(t" << expr_gen.to_str(o1)
   38663           0 :                   << "t)" << expr_gen.to_str(o2)
   38664           0 :                   << "t";
   38665             :             }
   38666             :          };
   38667             : 
   38668             :          struct synthesize_vovovoc_expression4
   38669             :          {
   38670             :             typedef typename vovovoc_t::type4 node_type;
   38671             :             typedef typename vovovoc_t::sf4_type sf4_type;
   38672             :             typedef typename node_type::T0 T0;
   38673             :             typedef typename node_type::T1 T1;
   38674             :             typedef typename node_type::T2 T2;
   38675             :             typedef typename node_type::T3 T3;
   38676             : 
   38677           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38678             :                                                       const details::operator_type& operation,
   38679             :                                                       expression_node_ptr (&branch)[2])
   38680             :             {
   38681             :                // ((v0 o0 (v1 o1 v2)) o2 c)
   38682             :                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
   38683             : 
   38684           0 :                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
   38685           0 :                const Type& v0 = vovov->t0();
   38686           0 :                const Type& v1 = vovov->t1();
   38687           0 :                const Type& v2 = vovov->t2();
   38688           0 :                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
   38689           0 :                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
   38690           0 :                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
   38691           0 :                const details::operator_type o2 = operation;
   38692             : 
   38693           0 :                binary_functor_t f0 = vovov->f0();
   38694           0 :                binary_functor_t f1 = vovov->f1();
   38695           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38696             : 
   38697           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38698           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38699             : 
   38700           0 :                expression_node_ptr result = error_node();
   38701             : 
   38702             :                const bool synthesis_result =
   38703             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38704           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
   38705             : 
   38706           0 :                if (synthesis_result)
   38707           0 :                   return result;
   38708           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38709           0 :                   return error_node();
   38710             : 
   38711             :                exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
   38712             : 
   38713           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
   38714             :             }
   38715             : 
   38716           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38717             :                                          const details::operator_type o0,
   38718             :                                          const details::operator_type o1,
   38719             :                                          const details::operator_type o2)
   38720             :             {
   38721           0 :                return details::build_string()
   38722           0 :                   << "(t" << expr_gen.to_str(o0)
   38723           0 :                   << "(t" << expr_gen.to_str(o1)
   38724           0 :                   << "t)" << expr_gen.to_str(o2)
   38725           0 :                   << "t";
   38726             :             }
   38727             :          };
   38728             : 
   38729             :          struct synthesize_vovocov_expression4
   38730             :          {
   38731             :             typedef typename vovocov_t::type4 node_type;
   38732             :             typedef typename vovocov_t::sf4_type sf4_type;
   38733             :             typedef typename node_type::T0 T0;
   38734             :             typedef typename node_type::T1 T1;
   38735             :             typedef typename node_type::T2 T2;
   38736             :             typedef typename node_type::T3 T3;
   38737             : 
   38738           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38739             :                                                       const details::operator_type& operation,
   38740             :                                                       expression_node_ptr (&branch)[2])
   38741             :             {
   38742             :                // ((v0 o0 (v1 o1 c)) o2 v1)
   38743             :                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
   38744             : 
   38745           0 :                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
   38746           0 :                const Type& v0 = vovoc->t0();
   38747           0 :                const Type& v1 = vovoc->t1();
   38748           0 :                const Type   c = vovoc->t2();
   38749           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38750           0 :                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
   38751           0 :                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
   38752           0 :                const details::operator_type o2 = operation;
   38753             : 
   38754           0 :                binary_functor_t f0 = vovoc->f0();
   38755           0 :                binary_functor_t f1 = vovoc->f1();
   38756           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38757             : 
   38758           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38759             : 
   38760           0 :                expression_node_ptr result = error_node();
   38761             : 
   38762             :                const bool synthesis_result =
   38763             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38764           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
   38765             : 
   38766           0 :                if (synthesis_result)
   38767           0 :                   return result;
   38768           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38769           0 :                   return error_node();
   38770             : 
   38771             :                exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
   38772             : 
   38773           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
   38774             :             }
   38775             : 
   38776           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38777             :                                          const details::operator_type o0,
   38778             :                                          const details::operator_type o1,
   38779             :                                          const details::operator_type o2)
   38780             :             {
   38781           0 :                return details::build_string()
   38782           0 :                   << "(t" << expr_gen.to_str(o0)
   38783           0 :                   << "(t" << expr_gen.to_str(o1)
   38784           0 :                   << "t)" << expr_gen.to_str(o2)
   38785           0 :                   << "t";
   38786             :             }
   38787             :          };
   38788             : 
   38789             :          struct synthesize_vocovov_expression4
   38790             :          {
   38791             :             typedef typename vocovov_t::type4 node_type;
   38792             :             typedef typename vocovov_t::sf4_type sf4_type;
   38793             :             typedef typename node_type::T0 T0;
   38794             :             typedef typename node_type::T1 T1;
   38795             :             typedef typename node_type::T2 T2;
   38796             :             typedef typename node_type::T3 T3;
   38797             : 
   38798           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38799             :                                                       const details::operator_type& operation,
   38800             :                                                       expression_node_ptr (&branch)[2])
   38801             :             {
   38802             :                // ((v0 o0 (c o1 v1)) o2 v2)
   38803             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   38804             : 
   38805           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   38806           0 :                const Type& v0 = vocov->t0();
   38807           0 :                const Type   c = vocov->t1();
   38808           0 :                const Type& v1 = vocov->t2();
   38809           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38810           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   38811           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   38812           0 :                const details::operator_type o2 = operation;
   38813             : 
   38814           0 :                binary_functor_t f0 = vocov->f0();
   38815           0 :                binary_functor_t f1 = vocov->f1();
   38816           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38817             : 
   38818           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38819           0 :                expression_node_ptr result = error_node();
   38820             : 
   38821             :                const bool synthesis_result =
   38822             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38823           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
   38824             : 
   38825           0 :                if (synthesis_result)
   38826           0 :                   return result;
   38827           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38828           0 :                   return error_node();
   38829             : 
   38830             :                exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
   38831             : 
   38832           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
   38833             :             }
   38834             : 
   38835           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38836             :                                          const details::operator_type o0,
   38837             :                                          const details::operator_type o1,
   38838             :                                          const details::operator_type o2)
   38839             :             {
   38840           0 :                return details::build_string()
   38841           0 :                   << "(t" << expr_gen.to_str(o0)
   38842           0 :                   << "(t" << expr_gen.to_str(o1)
   38843           0 :                   << "t)" << expr_gen.to_str(o2)
   38844           0 :                   << "t";
   38845             :             }
   38846             :          };
   38847             : 
   38848             :          struct synthesize_covovov_expression4
   38849             :          {
   38850             :             typedef typename covovov_t::type4 node_type;
   38851             :             typedef typename covovov_t::sf4_type sf4_type;
   38852             :             typedef typename node_type::T0 T0;
   38853             :             typedef typename node_type::T1 T1;
   38854             :             typedef typename node_type::T2 T2;
   38855             :             typedef typename node_type::T3 T3;
   38856             : 
   38857           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38858             :                                                       const details::operator_type& operation,
   38859             :                                                       expression_node_ptr (&branch)[2])
   38860             :             {
   38861             :                // ((c o0 (v0 o1 v1)) o2 v2)
   38862             :                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
   38863             : 
   38864           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   38865           0 :                const Type   c = covov->t0();
   38866           0 :                const Type& v0 = covov->t1();
   38867           0 :                const Type& v1 = covov->t2();
   38868           0 :                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38869           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   38870           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   38871           0 :                const details::operator_type o2 = operation;
   38872             : 
   38873           0 :                binary_functor_t f0 = covov->f0();
   38874           0 :                binary_functor_t f1 = covov->f1();
   38875           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38876             : 
   38877           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38878             : 
   38879           0 :                expression_node_ptr result = error_node();
   38880             : 
   38881             :                const bool synthesis_result =
   38882             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38883           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
   38884             : 
   38885           0 :                if (synthesis_result)
   38886           0 :                   return result;
   38887           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38888           0 :                   return error_node();
   38889             : 
   38890             :                exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
   38891             : 
   38892           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
   38893             :             }
   38894             : 
   38895           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38896             :                                          const details::operator_type o0,
   38897             :                                          const details::operator_type o1,
   38898             :                                          const details::operator_type o2)
   38899             :             {
   38900           0 :                return details::build_string()
   38901           0 :                   << "(t" << expr_gen.to_str(o0)
   38902           0 :                   << "(t" << expr_gen.to_str(o1)
   38903           0 :                   << "t)" << expr_gen.to_str(o2)
   38904           0 :                   << "t";
   38905             :             }
   38906             :          };
   38907             : 
   38908             :          struct synthesize_covocov_expression4
   38909             :          {
   38910             :             typedef typename covocov_t::type4 node_type;
   38911             :             typedef typename covocov_t::sf4_type sf4_type;
   38912             :             typedef typename node_type::T0 T0;
   38913             :             typedef typename node_type::T1 T1;
   38914             :             typedef typename node_type::T2 T2;
   38915             :             typedef typename node_type::T3 T3;
   38916             : 
   38917           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38918             :                                                       const details::operator_type& operation,
   38919             :                                                       expression_node_ptr (&branch)[2])
   38920             :             {
   38921             :                // ((c0 o0 (v0 o1 c1)) o2 v1)
   38922             :                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
   38923             : 
   38924           0 :                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
   38925           0 :                const Type  c0 = covoc->t0();
   38926           0 :                const Type& v0 = covoc->t1();
   38927           0 :                const Type  c1 = covoc->t2();
   38928           0 :                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
   38929           0 :                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
   38930           0 :                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
   38931           0 :                const details::operator_type o2 = operation;
   38932             : 
   38933           0 :                binary_functor_t f0 = covoc->f0();
   38934           0 :                binary_functor_t f1 = covoc->f1();
   38935           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38936             : 
   38937           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38938             : 
   38939           0 :                expression_node_ptr result = error_node();
   38940             : 
   38941             :                const bool synthesis_result =
   38942             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   38943           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
   38944             : 
   38945           0 :                if (synthesis_result)
   38946           0 :                   return result;
   38947           0 :                else if (!expr_gen.valid_operator(o2,f2))
   38948           0 :                   return error_node();
   38949             : 
   38950             :                exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
   38951             : 
   38952           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
   38953             :             }
   38954             : 
   38955           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   38956             :                                          const details::operator_type o0,
   38957             :                                          const details::operator_type o1,
   38958             :                                          const details::operator_type o2)
   38959             :             {
   38960           0 :                return details::build_string()
   38961           0 :                   << "(t" << expr_gen.to_str(o0)
   38962           0 :                   << "(t" << expr_gen.to_str(o1)
   38963           0 :                   << "t)" << expr_gen.to_str(o2)
   38964           0 :                   << "t";
   38965             :             }
   38966             :          };
   38967             : 
   38968             :          struct synthesize_vocovoc_expression4
   38969             :          {
   38970             :             typedef typename vocovoc_t::type4 node_type;
   38971             :             typedef typename vocovoc_t::sf4_type sf4_type;
   38972             :             typedef typename node_type::T0 T0;
   38973             :             typedef typename node_type::T1 T1;
   38974             :             typedef typename node_type::T2 T2;
   38975             :             typedef typename node_type::T3 T3;
   38976             : 
   38977           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   38978             :                                                       const details::operator_type& operation,
   38979             :                                                       expression_node_ptr (&branch)[2])
   38980             :             {
   38981             :                // ((v0 o0 (c0 o1 v1)) o2 c1)
   38982             :                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
   38983             : 
   38984           0 :                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
   38985           0 :                const Type& v0 = vocov->t0();
   38986           0 :                const Type  c0 = vocov->t1();
   38987           0 :                const Type& v1 = vocov->t2();
   38988           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   38989           0 :                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
   38990           0 :                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
   38991           0 :                const details::operator_type o2 = operation;
   38992             : 
   38993           0 :                binary_functor_t f0 = vocov->f0();
   38994           0 :                binary_functor_t f1 = vocov->f1();
   38995           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   38996             : 
   38997           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   38998           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   38999             : 
   39000           0 :                expression_node_ptr result = error_node();
   39001             : 
   39002             :                const bool synthesis_result =
   39003             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39004           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
   39005             : 
   39006           0 :                if (synthesis_result)
   39007           0 :                   return result;
   39008           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39009           0 :                   return error_node();
   39010             : 
   39011             :                exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
   39012             : 
   39013           0 :                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
   39014             :             }
   39015             : 
   39016           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39017             :                                          const details::operator_type o0,
   39018             :                                          const details::operator_type o1,
   39019             :                                          const details::operator_type o2)
   39020             :             {
   39021           0 :                return details::build_string()
   39022           0 :                   << "(t" << expr_gen.to_str(o0)
   39023           0 :                   << "(t" << expr_gen.to_str(o1)
   39024           0 :                   << "t)" << expr_gen.to_str(o2)
   39025           0 :                   << "t";
   39026             :             }
   39027             :          };
   39028             : 
   39029             :          struct synthesize_covovoc_expression4
   39030             :          {
   39031             :             typedef typename covovoc_t::type4 node_type;
   39032             :             typedef typename covovoc_t::sf4_type sf4_type;
   39033             :             typedef typename node_type::T0 T0;
   39034             :             typedef typename node_type::T1 T1;
   39035             :             typedef typename node_type::T2 T2;
   39036             :             typedef typename node_type::T3 T3;
   39037             : 
   39038           0 :             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
   39039             :                                                       const details::operator_type& operation,
   39040             :                                                       expression_node_ptr (&branch)[2])
   39041             :             {
   39042             :                // ((c0 o0 (v0 o1 v1)) o2 c1)
   39043             :                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
   39044             : 
   39045           0 :                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
   39046           0 :                const Type  c0 = covov->t0();
   39047           0 :                const Type& v0 = covov->t1();
   39048           0 :                const Type& v1 = covov->t2();
   39049           0 :                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
   39050           0 :                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
   39051           0 :                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
   39052           0 :                const details::operator_type o2 = operation;
   39053             : 
   39054           0 :                binary_functor_t f0 = covov->f0();
   39055           0 :                binary_functor_t f1 = covov->f1();
   39056           0 :                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
   39057             : 
   39058           0 :                details::free_node(*(expr_gen.node_allocator_),branch[0]);
   39059           0 :                details::free_node(*(expr_gen.node_allocator_),branch[1]);
   39060             : 
   39061           0 :                expression_node_ptr result = error_node();
   39062             : 
   39063             :                const bool synthesis_result =
   39064             :                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
   39065           0 :                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
   39066             : 
   39067           0 :                if (synthesis_result)
   39068           0 :                   return result;
   39069           0 :                else if (!expr_gen.valid_operator(o2,f2))
   39070           0 :                   return error_node();
   39071             : 
   39072             :                exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
   39073             : 
   39074           0 :                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
   39075             :             }
   39076             : 
   39077           0 :             static inline std::string id(expression_generator<Type>& expr_gen,
   39078             :                                          const details::operator_type o0,
   39079             :                                          const details::operator_type o1,
   39080             :                                          const details::operator_type o2)
   39081             :             {
   39082           0 :                return details::build_string()
   39083           0 :                   << "(t" << expr_gen.to_str(o0)
   39084           0 :                   << "(t" << expr_gen.to_str(o1)
   39085           0 :                   << "t)" << expr_gen.to_str(o2)
   39086           0 :                   << "t";
   39087             :             }
   39088             :          };
   39089             : 
   39090             :          struct synthesize_vococov_expression4
   39091             :          {
   39092             :             typedef typename vococov_t::type4 node_type;
   39093             :             static inline expression_node_ptr process(expression_generator<Type>&,
   39094             :                                                       const details::operator_type&,
   39095             :                                                       expression_node_ptr (&)[2])
   39096             :             {
   39097             :                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
   39098             :                exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
   39099             :                return error_node();
   39100             :             }
   39101             : 
   39102             :             static inline std::string id(expression_generator<Type>&,
   39103             :                                          const details::operator_type,
   39104             :                                          const details::operator_type,
   39105             :                                          const details::operator_type)
   39106             :             {
   39107             :                return "INVALID";
   39108             :             }
   39109             :          };
   39110             :          #endif
   39111             : 
   39112         810 :          inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   39113             :          {
   39114             :             // Definition: uv o uv
   39115         810 :             details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
   39116         810 :             details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
   39117         810 :             const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
   39118         810 :             const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
   39119         810 :             unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
   39120         810 :             unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
   39121         810 :             binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
   39122             : 
   39123         810 :             if (!valid_operator(o0,u0))
   39124           0 :                return error_node();
   39125         810 :             else if (!valid_operator(o1,u1))
   39126           0 :                return error_node();
   39127         810 :             else if (!valid_operator(operation,f))
   39128           0 :                return error_node();
   39129             : 
   39130         810 :             expression_node_ptr result = error_node();
   39131             : 
   39132         810 :             if (
   39133         810 :                  (details::e_neg == o0) &&
   39134         200 :                  (details::e_neg == o1)
   39135             :                )
   39136             :             {
   39137         200 :                switch (operation)
   39138             :                {
   39139             :                   // (-v0 + -v1) --> -(v0 + v1)
   39140           0 :                   case details::e_add : result = (*this)(details::e_neg,
   39141           0 :                                                     node_allocator_->
   39142             :                                                        allocate_rr<typename details::
   39143             :                                                           vov_node<Type,details::add_op<Type> > >(v0, v1));
   39144             :                                         exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
   39145           0 :                                         break;
   39146             : 
   39147             :                   // (-v0 - -v1) --> (v1 - v0)
   39148           0 :                   case details::e_sub : result = node_allocator_->
   39149             :                                                     allocate_rr<typename details::
   39150           0 :                                                        vov_node<Type,details::sub_op<Type> > >(v1, v0);
   39151             :                                         exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
   39152           0 :                                         break;
   39153             : 
   39154             :                   // (-v0 * -v1) --> (v0 * v1)
   39155         120 :                   case details::e_mul : result = node_allocator_->
   39156             :                                                     allocate_rr<typename details::
   39157         120 :                                                        vov_node<Type,details::mul_op<Type> > >(v0, v1);
   39158             :                                         exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
   39159         120 :                                         break;
   39160             : 
   39161             :                   // (-v0 / -v1) --> (v0 / v1)
   39162          80 :                   case details::e_div : result = node_allocator_->
   39163             :                                                     allocate_rr<typename details::
   39164          80 :                                                        vov_node<Type,details::div_op<Type> > >(v0, v1);
   39165             :                                         exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
   39166          80 :                                         break;
   39167             : 
   39168           0 :                   default             : break;
   39169             :                }
   39170             :             }
   39171             : 
   39172         810 :             if (0 == result)
   39173             :             {
   39174         610 :                result = node_allocator_->
   39175         610 :                             allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
   39176             :             }
   39177             : 
   39178         810 :             details::free_all_nodes(*node_allocator_,branch);
   39179         810 :             return result;
   39180             :          }
   39181             : 
   39182             :          #undef basic_opr_switch_statements
   39183             :          #undef extended_opr_switch_statements
   39184             :          #undef unary_opr_switch_statements
   39185             : 
   39186             :          #ifndef exprtk_disable_string_capabilities
   39187             : 
   39188             :          #define string_opr_switch_statements            \
   39189             :          case_stmt(details::e_lt    , details::lt_op   ) \
   39190             :          case_stmt(details::e_lte   , details::lte_op  ) \
   39191             :          case_stmt(details::e_gt    , details::gt_op   ) \
   39192             :          case_stmt(details::e_gte   , details::gte_op  ) \
   39193             :          case_stmt(details::e_eq    , details::eq_op   ) \
   39194             :          case_stmt(details::e_ne    , details::ne_op   ) \
   39195             :          case_stmt(details::e_in    , details::in_op   ) \
   39196             :          case_stmt(details::e_like  , details::like_op ) \
   39197             :          case_stmt(details::e_ilike , details::ilike_op) \
   39198             : 
   39199             :          template <typename T0, typename T1>
   39200        3550 :          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
   39201             :                                                                         T0 s0, T1 s1,
   39202             :                                                                         range_t rp0)
   39203             :          {
   39204        3550 :             switch (opr)
   39205             :             {
   39206             :                #define case_stmt(op0, op1)                                                                      \
   39207             :                case op0 : return node_allocator_->                                                              \
   39208             :                              allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
   39209             :                                 (s0, s1, rp0);                                                                  \
   39210             : 
   39211        3550 :                string_opr_switch_statements
   39212             :                #undef case_stmt
   39213           0 :                default : return error_node();
   39214             :             }
   39215             :          }
   39216             : 
   39217             :          template <typename T0, typename T1>
   39218        3450 :          inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
   39219             :                                                                         T0 s0, T1 s1,
   39220             :                                                                         range_t rp1)
   39221             :          {
   39222        3450 :             switch (opr)
   39223             :             {
   39224             :                #define case_stmt(op0, op1)                                                                      \
   39225             :                case op0 : return node_allocator_->                                                              \
   39226             :                              allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
   39227             :                                 (s0, s1, rp1);                                                                  \
   39228             : 
   39229        3450 :                string_opr_switch_statements
   39230             :                #undef case_stmt
   39231           0 :                default : return error_node();
   39232             :             }
   39233             :          }
   39234             : 
   39235             :          template <typename T0, typename T1>
   39236        3350 :          inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
   39237             :                                                                          T0 s0, T1 s1,
   39238             :                                                                          range_t rp0, range_t rp1)
   39239             :          {
   39240        3350 :             switch (opr)
   39241             :             {
   39242             :                #define case_stmt(op0, op1)                                                                        \
   39243             :                case op0 : return node_allocator_->                                                                \
   39244             :                              allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
   39245             :                                 (s0, s1, rp0, rp1);                                                               \
   39246             : 
   39247        3350 :                string_opr_switch_statements
   39248             :                #undef case_stmt
   39249           0 :                default : return error_node();
   39250             :             }
   39251             :          }
   39252             : 
   39253             :          template <typename T0, typename T1>
   39254       20042 :          inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
   39255             :          {
   39256       20042 :             switch (opr)
   39257             :             {
   39258             :                #define case_stmt(op0, op1)                                                                 \
   39259             :                case op0 : return node_allocator_->                                                         \
   39260             :                              allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
   39261             : 
   39262       20042 :                string_opr_switch_statements
   39263             :                #undef case_stmt
   39264           0 :                default : return error_node();
   39265             :             }
   39266             :          }
   39267             : 
   39268        6111 :          inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39269             :          {
   39270        6111 :             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
   39271        6111 :             std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
   39272             : 
   39273        6111 :             return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
   39274             :          }
   39275             : 
   39276        1100 :          inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39277             :          {
   39278        1100 :             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
   39279        1100 :             std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
   39280        1100 :             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
   39281             : 
   39282        1100 :             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
   39283             : 
   39284        1100 :             details::free_node(*node_allocator_,branch[0]);
   39285             : 
   39286        2200 :             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
   39287             :          }
   39288             : 
   39289        1100 :          inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39290             :          {
   39291        1100 :             std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
   39292        1100 :             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
   39293        1100 :             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
   39294             : 
   39295        1100 :             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
   39296             : 
   39297        1100 :             details::free_node(*node_allocator_,branch[1]);
   39298             : 
   39299        2200 :             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
   39300             :          }
   39301             : 
   39302         150 :          inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39303             :          {
   39304         150 :             std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
   39305         150 :             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   39306         150 :             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   39307             : 
   39308         150 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   39309             : 
   39310         150 :             details::free_node(*node_allocator_,branch[1]);
   39311             : 
   39312         300 :             return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
   39313         150 :          }
   39314             : 
   39315        1250 :          inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39316             :          {
   39317        1250 :             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
   39318        1250 :             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
   39319        1250 :             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
   39320        1250 :             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
   39321             : 
   39322        1250 :             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
   39323        1250 :             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
   39324             : 
   39325        1250 :             details::free_node(*node_allocator_,branch[0]);
   39326        1250 :             details::free_node(*node_allocator_,branch[1]);
   39327             : 
   39328        2500 :             return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
   39329             :          }
   39330             : 
   39331       10196 :          inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39332             :          {
   39333       10196 :             std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
   39334       10196 :             std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   39335             : 
   39336       10196 :             details::free_node(*node_allocator_,branch[1]);
   39337             : 
   39338       20392 :             return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
   39339       10196 :          }
   39340             : 
   39341        1930 :          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39342             :          {
   39343        1930 :             std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   39344        1930 :             std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   39345             : 
   39346        1930 :             details::free_node(*node_allocator_,branch[0]);
   39347             : 
   39348        3860 :             return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
   39349        1930 :          }
   39350             : 
   39351        1500 :          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39352             :          {
   39353        1500 :             std::string  s0  = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
   39354        1500 :             std::string& s1  = static_cast<details::string_range_node<Type>*  >(branch[1])->ref  ();
   39355        1500 :             range_t      rp1 = static_cast<details::string_range_node<Type>*  >(branch[1])->range();
   39356             : 
   39357        1500 :             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
   39358             : 
   39359        1500 :             details::free_node(*node_allocator_,branch[0]);
   39360        1500 :             details::free_node(*node_allocator_,branch[1]);
   39361             : 
   39362        3000 :             return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
   39363        1500 :          }
   39364             : 
   39365        1500 :          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39366             :          {
   39367        1500 :             std::string&  s0 = static_cast<details::string_range_node<Type>*  >(branch[0])->ref  ();
   39368        1500 :             std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
   39369        1500 :             range_t      rp0 = static_cast<details::string_range_node<Type>*  >(branch[0])->range();
   39370             : 
   39371        1500 :             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
   39372             : 
   39373        1500 :             details::free_node(*node_allocator_,branch[0]);
   39374        1500 :             details::free_node(*node_allocator_,branch[1]);
   39375             : 
   39376        3000 :             return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
   39377        1500 :          }
   39378             : 
   39379         500 :          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39380             :          {
   39381         500 :             std::string&  s0 = static_cast<details::string_range_node<Type>*      >(branch[0])->ref  ();
   39382         500 :             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   39383         500 :             range_t      rp0 = static_cast<details::string_range_node<Type>*      >(branch[0])->range();
   39384         500 :             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   39385             : 
   39386         500 :             static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
   39387         500 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   39388             : 
   39389         500 :             details::free_node(*node_allocator_,branch[0]);
   39390         500 :             details::free_node(*node_allocator_,branch[1]);
   39391             : 
   39392        1000 :             return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
   39393         500 :          }
   39394             : 
   39395        5969 :          inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39396             :          {
   39397        5969 :             const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   39398        5969 :             const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   39399             : 
   39400        5969 :             expression_node_ptr result = error_node();
   39401             : 
   39402        5969 :             if (details::e_add == opr)
   39403        2974 :                result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
   39404        2995 :             else if (details::e_in == opr)
   39405         160 :                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op   <Type>::process(s0,s1));
   39406        2835 :             else if (details::e_like == opr)
   39407         515 :                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
   39408        2320 :             else if (details::e_ilike == opr)
   39409         515 :                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
   39410             :             else
   39411             :             {
   39412        1805 :                expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
   39413             : 
   39414        1805 :                const Type v = temp->value();
   39415             : 
   39416        1805 :                details::free_node(*node_allocator_,temp);
   39417             : 
   39418        1805 :                result = node_allocator_->allocate<literal_node_t>(v);
   39419             :             }
   39420             : 
   39421        5969 :             details::free_all_nodes(*node_allocator_,branch);
   39422             : 
   39423        5969 :             return result;
   39424        5969 :          }
   39425             : 
   39426         700 :          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39427             :          {
   39428         700 :             const std::string s0 = static_cast<details::string_literal_node<Type>*    >(branch[0])->str  ();
   39429         700 :                   std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   39430         700 :             range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   39431             : 
   39432         700 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   39433             : 
   39434         700 :             details::free_node(*node_allocator_,branch[0]);
   39435         700 :             details::free_node(*node_allocator_,branch[1]);
   39436             : 
   39437        1400 :             return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
   39438         700 :          }
   39439             : 
   39440         250 :          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39441             :          {
   39442         250 :             std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   39443         250 :             std::string&  s1 = static_cast<details::stringvar_node<Type>*         >(branch[1])->ref  ();
   39444         250 :             range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   39445             : 
   39446         250 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   39447             : 
   39448         250 :             details::free_node(*node_allocator_,branch[0]);
   39449             : 
   39450         500 :             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
   39451         250 :          }
   39452             : 
   39453         500 :          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39454             :          {
   39455         500 :             const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   39456         500 :                   std::string& s1 = static_cast<details::string_range_node<Type>*      >(branch[1])->ref  ();
   39457         500 :             const range_t     rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   39458         500 :             const range_t     rp1 = static_cast<details::string_range_node<Type>*      >(branch[1])->range();
   39459             : 
   39460         500 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   39461         500 :             static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
   39462             : 
   39463         500 :             details::free_node(*node_allocator_,branch[0]);
   39464         500 :             details::free_node(*node_allocator_,branch[1]);
   39465             : 
   39466        1000 :             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
   39467         500 :          }
   39468             : 
   39469         700 :          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39470             :          {
   39471         700 :             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   39472         700 :             const std::string s1 = static_cast<details::string_literal_node<Type>*    >(branch[1])->str  ();
   39473         700 :             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   39474             : 
   39475         700 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   39476             : 
   39477         700 :             details::free_all_nodes(*node_allocator_,branch);
   39478             : 
   39479        1400 :             return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
   39480         700 :          }
   39481             : 
   39482        1100 :          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39483             :          {
   39484        1100 :             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
   39485        1100 :             const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
   39486        1100 :             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
   39487        1100 :             const range_t    rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
   39488             : 
   39489        1100 :             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
   39490        1100 :             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
   39491             : 
   39492        1100 :             details::free_all_nodes(*node_allocator_,branch);
   39493             : 
   39494        2200 :             return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
   39495        1100 :          }
   39496             : 
   39497        4846 :          inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39498             :          {
   39499        4846 :             switch (opr)
   39500             :             {
   39501             :                #define case_stmt(op0, op1)                                                      \
   39502             :                case op0 : return node_allocator_->                                              \
   39503             :                              allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
   39504             :                                 (opr, branch[0], branch[1]);                                    \
   39505             : 
   39506        4846 :                string_opr_switch_statements
   39507             :                #undef case_stmt
   39508           0 :                default : return error_node();
   39509             :             }
   39510             :          }
   39511             : 
   39512             :          #undef string_opr_switch_statements
   39513             :          #endif
   39514             : 
   39515             :          #ifndef exprtk_disable_string_capabilities
   39516       44568 :          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
   39517             :          {
   39518       44568 :             if ((0 == branch[0]) || (0 == branch[1]))
   39519             :             {
   39520           0 :                details::free_all_nodes(*node_allocator_,branch);
   39521             : 
   39522           0 :                return error_node();
   39523             :             }
   39524             : 
   39525       44568 :             const bool b0_is_s   = details::is_string_node            (branch[0]);
   39526       44568 :             const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
   39527       44568 :             const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
   39528       44568 :             const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
   39529             : 
   39530       44568 :             const bool b1_is_s   = details::is_string_node            (branch[1]);
   39531       44568 :             const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
   39532       44568 :             const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
   39533       44568 :             const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
   39534             : 
   39535       44568 :             const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
   39536       44268 :                                    details::is_genricstring_range_node(branch[0]) ||
   39537       42968 :                                    details::is_string_concat_node     (branch[0]) ||
   39538       41168 :                                    details::is_string_function_node   (branch[0]) ||
   39539       41150 :                                    details::is_string_condition_node  (branch[0]) ||
   39540      129286 :                                    details::is_string_ccondition_node (branch[0]) ||
   39541       40450 :                                    details::is_string_vararg_node     (branch[0]) ;
   39542             : 
   39543       44568 :             const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
   39544       44568 :                                    details::is_genricstring_range_node(branch[1]) ||
   39545       44568 :                                    details::is_string_concat_node     (branch[1]) ||
   39546       43712 :                                    details::is_string_function_node   (branch[1]) ||
   39547       43700 :                                    details::is_string_condition_node  (branch[1]) ||
   39548      132436 :                                    details::is_string_ccondition_node (branch[1]) ||
   39549       43300 :                                    details::is_string_vararg_node     (branch[1]) ;
   39550             : 
   39551       44568 :             if (details::e_add == opr)
   39552             :             {
   39553        8140 :                if (!b0_is_cs || !b1_is_cs)
   39554             :                {
   39555        5166 :                   return synthesize_expression<string_concat_node_t,2>(opr,branch);
   39556             :                }
   39557             :             }
   39558             : 
   39559       39402 :             if (b0_is_gen || b1_is_gen)
   39560             :             {
   39561        4846 :                return synthesize_strogen_expression(opr,branch);
   39562             :             }
   39563       34556 :             else if (b0_is_s)
   39564             :             {
   39565       17557 :                if      (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
   39566       11446 :                else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
   39567        1250 :                else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
   39568         150 :                else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
   39569             :             }
   39570       16999 :             else if (b0_is_cs)
   39571             :             {
   39572       10099 :                if      (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
   39573        8169 :                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
   39574        2200 :                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
   39575         700 :                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
   39576             :             }
   39577        6900 :             else if (b0_is_sr)
   39578             :             {
   39579        4350 :                if      (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
   39580        3250 :                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
   39581        2000 :                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
   39582         500 :                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
   39583             :             }
   39584        2550 :             else if (b0_is_csr)
   39585             :             {
   39586        2550 :                if      (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
   39587        2300 :                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
   39588        1800 :                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
   39589        1100 :                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
   39590             :             }
   39591             : 
   39592           0 :             return error_node();
   39593             :          }
   39594             :          #else
   39595             :          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
   39596             :          {
   39597             :             details::free_all_nodes(*node_allocator_,branch);
   39598             :             return error_node();
   39599             :          }
   39600             :          #endif
   39601             : 
   39602             :          #ifndef exprtk_disable_string_capabilities
   39603         355 :          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
   39604             :          {
   39605         355 :             if (details::e_inrange != opr)
   39606           0 :                return error_node();
   39607         355 :             else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
   39608             :             {
   39609           0 :                details::free_all_nodes(*node_allocator_,branch);
   39610             : 
   39611           0 :                return error_node();
   39612             :             }
   39613         355 :             else if (
   39614         355 :                       details::is_const_string_node(branch[0]) &&
   39615         410 :                       details::is_const_string_node(branch[1]) &&
   39616          55 :                       details::is_const_string_node(branch[2])
   39617             :                     )
   39618             :             {
   39619          55 :                const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   39620          55 :                const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   39621          55 :                const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
   39622             : 
   39623          55 :                const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
   39624             : 
   39625          55 :                details::free_all_nodes(*node_allocator_,branch);
   39626             : 
   39627          55 :                return node_allocator_->allocate_c<details::literal_node<Type> >(v);
   39628          55 :             }
   39629         300 :             else if (
   39630         300 :                       details::is_string_node(branch[0]) &&
   39631         400 :                       details::is_string_node(branch[1]) &&
   39632         100 :                       details::is_string_node(branch[2])
   39633             :                     )
   39634             :             {
   39635          50 :                std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
   39636          50 :                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
   39637          50 :                std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
   39638             : 
   39639             :                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
   39640             : 
   39641          50 :                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
   39642             :             }
   39643         250 :             else if (
   39644         250 :                       details::is_const_string_node(branch[0]) &&
   39645         400 :                             details::is_string_node(branch[1]) &&
   39646         150 :                       details::is_const_string_node(branch[2])
   39647             :                     )
   39648             :             {
   39649          50 :                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   39650          50 :                std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   39651          50 :                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
   39652             : 
   39653             :                typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
   39654             : 
   39655          50 :                details::free_node(*node_allocator_,branch[0]);
   39656          50 :                details::free_node(*node_allocator_,branch[2]);
   39657             : 
   39658          50 :                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
   39659          50 :             }
   39660         200 :             else if (
   39661         200 :                             details::is_string_node(branch[0]) &&
   39662         250 :                       details::is_const_string_node(branch[1]) &&
   39663          50 :                             details::is_string_node(branch[2])
   39664             :                     )
   39665             :             {
   39666          50 :                std::string&  s0 = static_cast<details::stringvar_node<Type>*     >(branch[0])->ref();
   39667          50 :                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
   39668          50 :                std::string&  s2 = static_cast<details::stringvar_node<Type>*     >(branch[2])->ref();
   39669             : 
   39670             :                typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
   39671             : 
   39672          50 :                details::free_node(*node_allocator_,branch[1]);
   39673             : 
   39674          50 :                return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
   39675          50 :             }
   39676         150 :             else if (
   39677         150 :                       details::is_string_node(branch[0]) &&
   39678         200 :                       details::is_string_node(branch[1]) &&
   39679          50 :                       details::is_const_string_node(branch[2])
   39680             :                     )
   39681             :             {
   39682          50 :                std::string& s0 = static_cast<details::stringvar_node<Type>*     >(branch[0])->ref();
   39683          50 :                std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   39684          50 :                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
   39685             : 
   39686             :                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
   39687             : 
   39688          50 :                details::free_node(*node_allocator_,branch[2]);
   39689             : 
   39690          50 :                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
   39691          50 :             }
   39692         100 :             else if (
   39693         100 :                       details::is_const_string_node(branch[0]) &&
   39694         200 :                       details::      is_string_node(branch[1]) &&
   39695         100 :                       details::      is_string_node(branch[2])
   39696             :                     )
   39697             :             {
   39698         100 :                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
   39699         100 :                std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
   39700         100 :                std::string& s2 = static_cast<details::stringvar_node<Type>*     >(branch[2])->ref();
   39701             : 
   39702             :                typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
   39703             : 
   39704         100 :                details::free_node(*node_allocator_,branch[0]);
   39705             : 
   39706         100 :                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
   39707         100 :             }
   39708             :             else
   39709           0 :                return error_node();
   39710             :          }
   39711             :          #else
   39712             :          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
   39713             :          {
   39714             :             details::free_all_nodes(*node_allocator_,branch);
   39715             :             return error_node();
   39716             :          }
   39717             :          #endif
   39718             : 
   39719         255 :          inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
   39720             :          {
   39721             :             /*
   39722             :              Note: The following are the type promotion rules
   39723             :              that relate to operations that include 'null':
   39724             :              0. null ==/!=     null --> true false
   39725             :              1. null operation null --> null
   39726             :              2. x    ==/!=     null --> true/false
   39727             :              3. null ==/!=     x    --> true/false
   39728             :              4. x   operation  null --> x
   39729             :              5. null operation x    --> x
   39730             :             */
   39731             : 
   39732             :             typedef typename details::null_eq_node<T> nulleq_node_t;
   39733             : 
   39734         255 :             const bool b0_null = details::is_null_node(branch[0]);
   39735         255 :             const bool b1_null = details::is_null_node(branch[1]);
   39736             : 
   39737         255 :             if (b0_null && b1_null)
   39738             :             {
   39739          60 :                expression_node_ptr result = error_node();
   39740             : 
   39741          60 :                if (details::e_eq == operation)
   39742          60 :                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
   39743           0 :                else if (details::e_ne == operation)
   39744           0 :                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
   39745             : 
   39746          60 :                if (result)
   39747             :                {
   39748          60 :                   details::free_node(*node_allocator_,branch[0]);
   39749          60 :                   details::free_node(*node_allocator_,branch[1]);
   39750             : 
   39751          60 :                   return result;
   39752             :                }
   39753             : 
   39754           0 :                details::free_node(*node_allocator_,branch[1]);
   39755             : 
   39756           0 :                return branch[0];
   39757             :             }
   39758         195 :             else if (details::e_eq == operation)
   39759             :             {
   39760         195 :                expression_node_ptr result = node_allocator_->
   39761         195 :                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
   39762             : 
   39763         195 :                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
   39764             : 
   39765         195 :                return result;
   39766             :             }
   39767           0 :             else if (details::e_ne == operation)
   39768             :             {
   39769           0 :                expression_node_ptr result = node_allocator_->
   39770           0 :                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
   39771             : 
   39772           0 :                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
   39773             : 
   39774           0 :                return result;
   39775             :             }
   39776           0 :             else if (b0_null)
   39777             :             {
   39778           0 :                details::free_node(*node_allocator_,branch[0]);
   39779           0 :                branch[0] = branch[1];
   39780           0 :                branch[1] = error_node();
   39781             :             }
   39782           0 :             else if (b1_null)
   39783             :             {
   39784           0 :                details::free_node(*node_allocator_,branch[1]);
   39785           0 :                branch[1] = error_node();
   39786             :             }
   39787             : 
   39788           0 :             if (
   39789           0 :                  (details::e_add == operation) || (details::e_sub == operation) ||
   39790           0 :                  (details::e_mul == operation) || (details::e_div == operation) ||
   39791           0 :                  (details::e_mod == operation) || (details::e_pow == operation)
   39792             :                )
   39793             :             {
   39794           0 :                return branch[0];
   39795             :             }
   39796             : 
   39797           0 :             details::free_node(*node_allocator_, branch[0]);
   39798             : 
   39799           0 :             if (
   39800           0 :                  (details::e_lt    == operation) || (details::e_lte  == operation) ||
   39801           0 :                  (details::e_gt    == operation) || (details::e_gte  == operation) ||
   39802           0 :                  (details::e_and   == operation) || (details::e_nand == operation) ||
   39803           0 :                  (details::e_or    == operation) || (details::e_nor  == operation) ||
   39804           0 :                  (details::e_xor   == operation) || (details::e_xnor == operation) ||
   39805           0 :                  (details::e_in    == operation) || (details::e_like == operation) ||
   39806           0 :                  (details::e_ilike == operation)
   39807             :                )
   39808             :             {
   39809           0 :                return node_allocator_->allocate_c<literal_node_t>(T(0));
   39810             :             }
   39811             : 
   39812           0 :             return node_allocator_->allocate<details::null_node<Type> >();
   39813             :          }
   39814             : 
   39815             :          template <typename NodeType, std::size_t N>
   39816      591857 :          inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
   39817             :          {
   39818      591857 :             if (
   39819      591857 :                  (details::e_in    == operation) ||
   39820      591845 :                  (details::e_like  == operation) ||
   39821      591845 :                  (details::e_ilike == operation)
   39822             :                )
   39823             :             {
   39824          12 :                free_all_nodes(*node_allocator_,branch);
   39825             : 
   39826          12 :                return error_node();
   39827             :             }
   39828      591845 :             else if (!details::all_nodes_valid<N>(branch))
   39829             :             {
   39830           0 :                free_all_nodes(*node_allocator_,branch);
   39831             : 
   39832           0 :                return error_node();
   39833             :             }
   39834      591845 :             else if ((details::e_default != operation))
   39835             :             {
   39836             :                // Attempt simple constant folding optimisation.
   39837      591845 :                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
   39838             : 
   39839      591845 :                if (is_constant_foldable<N>(branch))
   39840             :                {
   39841      291443 :                   const Type v = expression_point->value();
   39842      291443 :                   details::free_node(*node_allocator_,expression_point);
   39843             : 
   39844      291443 :                   return node_allocator_->allocate<literal_node_t>(v);
   39845             :                }
   39846             : 
   39847      300402 :                if (expression_point && expression_point->valid())
   39848             :                {
   39849      300402 :                   return expression_point;
   39850             :                }
   39851             : 
   39852           0 :                parser_->set_error(parser_error::make_error(
   39853             :                   parser_error::e_parser,
   39854           0 :                   token_t(),
   39855             :                   "ERR249 - Failed to synthesize node: NodeType",
   39856             :                   exprtk_error_location));
   39857             : 
   39858           0 :                details::free_node(*node_allocator_, expression_point);
   39859             :             }
   39860             : 
   39861           0 :             return error_node();
   39862             :          }
   39863             : 
   39864             :          template <typename NodeType, std::size_t N>
   39865       60380 :          inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
   39866             :          {
   39867       60380 :             if (!details::all_nodes_valid<N>(branch))
   39868             :             {
   39869           0 :                free_all_nodes(*node_allocator_,branch);
   39870             : 
   39871           0 :                return error_node();
   39872             :             }
   39873             : 
   39874             :             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
   39875             : 
   39876             :             // Attempt simple constant folding optimisation.
   39877             : 
   39878       60380 :             expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
   39879       60380 :             function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
   39880             : 
   39881       60380 :             if (0 == func_node_ptr)
   39882             :             {
   39883           0 :                free_all_nodes(*node_allocator_,branch);
   39884             : 
   39885           0 :                return error_node();
   39886             :             }
   39887             :             else
   39888       60380 :                func_node_ptr->init_branches(branch);
   39889             : 
   39890       60380 :             if (is_constant_foldable<N>(branch) && !f->has_side_effects())
   39891             :             {
   39892         120 :                Type v = expression_point->value();
   39893         120 :                details::free_node(*node_allocator_,expression_point);
   39894             : 
   39895         120 :                return node_allocator_->allocate<literal_node_t>(v);
   39896             :             }
   39897             : 
   39898      120520 :             parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
   39899             : 
   39900       60260 :             return expression_point;
   39901             :          }
   39902             : 
   39903             :          bool                     strength_reduction_enabled_;
   39904             :          details::node_allocator* node_allocator_;
   39905             :          synthesize_map_t         synthesize_map_;
   39906             :          unary_op_map_t*          unary_op_map_;
   39907             :          binary_op_map_t*         binary_op_map_;
   39908             :          inv_binary_op_map_t*     inv_binary_op_map_;
   39909             :          sf3_map_t*               sf3_map_;
   39910             :          sf4_map_t*               sf4_map_;
   39911             :          parser_t*                parser_;
   39912             :       }; // class expression_generator
   39913             : 
   39914       43680 :       inline void set_error(const parser_error::type& error_type)
   39915             :       {
   39916       43680 :          error_list_.push_back(error_type);
   39917       43680 :       }
   39918             : 
   39919             :       inline void remove_last_error()
   39920             :       {
   39921             :          if (!error_list_.empty())
   39922             :          {
   39923             :             error_list_.pop_back();
   39924             :          }
   39925             :       }
   39926             : 
   39927           0 :       inline void set_synthesis_error(const std::string& synthesis_error_message)
   39928             :       {
   39929           0 :          if (synthesis_error_.empty())
   39930             :          {
   39931           0 :             synthesis_error_ = synthesis_error_message;
   39932             :          }
   39933           0 :       }
   39934             : 
   39935      349926 :       inline void register_local_vars(expression<T>& e)
   39936             :       {
   39937      414013 :          for (std::size_t i = 0; i < sem_.size(); ++i)
   39938             :          {
   39939       64087 :             scope_element& se = sem_.get_element(i);
   39940             : 
   39941       64087 :             if (
   39942       64087 :                  (scope_element::e_variable == se.type) ||
   39943       37655 :                  (scope_element::e_vecelem  == se.type)
   39944             :                )
   39945             :             {
   39946       35841 :                if (se.var_node)
   39947             :                {
   39948       35841 :                   e.register_local_var(se.var_node);
   39949             :                }
   39950             : 
   39951       35841 :                if (se.data)
   39952             :                {
   39953       26432 :                   e.register_local_data(se.data, 1, 0);
   39954             :                }
   39955             :             }
   39956       28246 :             else if (scope_element::e_vector == se.type)
   39957             :             {
   39958       18761 :                if (se.vec_node)
   39959             :                {
   39960       18761 :                   e.register_local_var(se.vec_node);
   39961             :                }
   39962             : 
   39963       18761 :                if (se.data)
   39964             :                {
   39965       18761 :                   e.register_local_data(se.data, se.size, 1);
   39966             :                }
   39967             :             }
   39968             :             #ifndef exprtk_disable_string_capabilities
   39969        9485 :             else if (scope_element::e_string == se.type)
   39970             :             {
   39971        9485 :                if (se.str_node)
   39972             :                {
   39973        9485 :                   e.register_local_var(se.str_node);
   39974             :                }
   39975             : 
   39976        9485 :                if (se.data)
   39977             :                {
   39978        9485 :                   e.register_local_data(se.data, se.size, 2);
   39979             :                }
   39980             :             }
   39981             :             #endif
   39982             : 
   39983       64087 :             se.var_node  = 0;
   39984       64087 :             se.vec_node  = 0;
   39985             :             #ifndef exprtk_disable_string_capabilities
   39986       64087 :             se.str_node  = 0;
   39987             :             #endif
   39988       64087 :             se.data      = 0;
   39989       64087 :             se.ref_count = 0;
   39990       64087 :             se.active    = false;
   39991             :          }
   39992      349926 :       }
   39993             : 
   39994      349926 :       inline void register_return_results(expression<T>& e)
   39995             :       {
   39996      349926 :          e.register_return_results(results_context_);
   39997      349926 :          results_context_ = 0;
   39998      349926 :       }
   39999             : 
   40000      106542 :       inline void load_unary_operations_map(unary_op_map_t& m)
   40001             :       {
   40002             :          #define register_unary_op(Op, UnaryFunctor)            \
   40003             :          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
   40004             : 
   40005      106542 :          register_unary_op(details::e_abs   , details::abs_op  )
   40006      106542 :          register_unary_op(details::e_acos  , details::acos_op )
   40007      106542 :          register_unary_op(details::e_acosh , details::acosh_op)
   40008      106542 :          register_unary_op(details::e_asin  , details::asin_op )
   40009      106542 :          register_unary_op(details::e_asinh , details::asinh_op)
   40010      106542 :          register_unary_op(details::e_atanh , details::atanh_op)
   40011      106542 :          register_unary_op(details::e_ceil  , details::ceil_op )
   40012      106542 :          register_unary_op(details::e_cos   , details::cos_op  )
   40013      106542 :          register_unary_op(details::e_cosh  , details::cosh_op )
   40014      106542 :          register_unary_op(details::e_exp   , details::exp_op  )
   40015      106542 :          register_unary_op(details::e_expm1 , details::expm1_op)
   40016      106542 :          register_unary_op(details::e_floor , details::floor_op)
   40017      106542 :          register_unary_op(details::e_log   , details::log_op  )
   40018      106542 :          register_unary_op(details::e_log10 , details::log10_op)
   40019      106542 :          register_unary_op(details::e_log2  , details::log2_op )
   40020      106542 :          register_unary_op(details::e_log1p , details::log1p_op)
   40021      106542 :          register_unary_op(details::e_neg   , details::neg_op  )
   40022      106542 :          register_unary_op(details::e_pos   , details::pos_op  )
   40023      106542 :          register_unary_op(details::e_round , details::round_op)
   40024      106542 :          register_unary_op(details::e_sin   , details::sin_op  )
   40025      106542 :          register_unary_op(details::e_sinc  , details::sinc_op )
   40026      106542 :          register_unary_op(details::e_sinh  , details::sinh_op )
   40027      106542 :          register_unary_op(details::e_sqrt  , details::sqrt_op )
   40028      106542 :          register_unary_op(details::e_tan   , details::tan_op  )
   40029      106542 :          register_unary_op(details::e_tanh  , details::tanh_op )
   40030      106542 :          register_unary_op(details::e_cot   , details::cot_op  )
   40031      106542 :          register_unary_op(details::e_sec   , details::sec_op  )
   40032      106542 :          register_unary_op(details::e_csc   , details::csc_op  )
   40033      106542 :          register_unary_op(details::e_r2d   , details::r2d_op  )
   40034      106542 :          register_unary_op(details::e_d2r   , details::d2r_op  )
   40035      106542 :          register_unary_op(details::e_d2g   , details::d2g_op  )
   40036      106542 :          register_unary_op(details::e_g2d   , details::g2d_op  )
   40037      106542 :          register_unary_op(details::e_notl  , details::notl_op )
   40038      106542 :          register_unary_op(details::e_sgn   , details::sgn_op  )
   40039      106542 :          register_unary_op(details::e_erf   , details::erf_op  )
   40040      106542 :          register_unary_op(details::e_erfc  , details::erfc_op )
   40041      106542 :          register_unary_op(details::e_ncdf  , details::ncdf_op )
   40042      106542 :          register_unary_op(details::e_frac  , details::frac_op )
   40043      106542 :          register_unary_op(details::e_trunc , details::trunc_op)
   40044             :          #undef register_unary_op
   40045      106542 :       }
   40046             : 
   40047      106542 :       inline void load_binary_operations_map(binary_op_map_t& m)
   40048             :       {
   40049             :          typedef typename binary_op_map_t::value_type value_type;
   40050             : 
   40051             :          #define register_binary_op(Op, BinaryFunctor)       \
   40052             :          m.insert(value_type(Op,BinaryFunctor<T>::process)); \
   40053             : 
   40054      106542 :          register_binary_op(details::e_add  , details::add_op )
   40055      106542 :          register_binary_op(details::e_sub  , details::sub_op )
   40056      106542 :          register_binary_op(details::e_mul  , details::mul_op )
   40057      106542 :          register_binary_op(details::e_div  , details::div_op )
   40058      106542 :          register_binary_op(details::e_mod  , details::mod_op )
   40059      106542 :          register_binary_op(details::e_pow  , details::pow_op )
   40060      106542 :          register_binary_op(details::e_lt   , details::lt_op  )
   40061      106542 :          register_binary_op(details::e_lte  , details::lte_op )
   40062      106542 :          register_binary_op(details::e_gt   , details::gt_op  )
   40063      106542 :          register_binary_op(details::e_gte  , details::gte_op )
   40064      106542 :          register_binary_op(details::e_eq   , details::eq_op  )
   40065      106542 :          register_binary_op(details::e_ne   , details::ne_op  )
   40066      106542 :          register_binary_op(details::e_and  , details::and_op )
   40067      106542 :          register_binary_op(details::e_nand , details::nand_op)
   40068      106542 :          register_binary_op(details::e_or   , details::or_op  )
   40069      106542 :          register_binary_op(details::e_nor  , details::nor_op )
   40070      106542 :          register_binary_op(details::e_xor  , details::xor_op )
   40071      106542 :          register_binary_op(details::e_xnor , details::xnor_op)
   40072             :          #undef register_binary_op
   40073      106542 :       }
   40074             : 
   40075      106542 :       inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
   40076             :       {
   40077             :          typedef typename inv_binary_op_map_t::value_type value_type;
   40078             : 
   40079             :          #define register_binary_op(Op, BinaryFunctor)       \
   40080             :          m.insert(value_type(BinaryFunctor<T>::process,Op)); \
   40081             : 
   40082      106542 :          register_binary_op(details::e_add  , details::add_op )
   40083      106542 :          register_binary_op(details::e_sub  , details::sub_op )
   40084      106542 :          register_binary_op(details::e_mul  , details::mul_op )
   40085      106542 :          register_binary_op(details::e_div  , details::div_op )
   40086      106542 :          register_binary_op(details::e_mod  , details::mod_op )
   40087      106542 :          register_binary_op(details::e_pow  , details::pow_op )
   40088      106542 :          register_binary_op(details::e_lt   , details::lt_op  )
   40089      106542 :          register_binary_op(details::e_lte  , details::lte_op )
   40090      106542 :          register_binary_op(details::e_gt   , details::gt_op  )
   40091      106542 :          register_binary_op(details::e_gte  , details::gte_op )
   40092      106542 :          register_binary_op(details::e_eq   , details::eq_op  )
   40093      106542 :          register_binary_op(details::e_ne   , details::ne_op  )
   40094      106542 :          register_binary_op(details::e_and  , details::and_op )
   40095      106542 :          register_binary_op(details::e_nand , details::nand_op)
   40096      106542 :          register_binary_op(details::e_or   , details::or_op  )
   40097      106542 :          register_binary_op(details::e_nor  , details::nor_op )
   40098      106542 :          register_binary_op(details::e_xor  , details::xor_op )
   40099      106542 :          register_binary_op(details::e_xnor , details::xnor_op)
   40100             :          #undef register_binary_op
   40101      106542 :       }
   40102             : 
   40103      106542 :       inline void load_sf3_map(sf3_map_t& sf3_map)
   40104             :       {
   40105             :          typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
   40106             : 
   40107             :          #define register_sf3(Op)                                                                             \
   40108             :          sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
   40109             : 
   40110      106542 :          register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
   40111      106542 :          register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
   40112      106542 :          register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
   40113      106542 :          register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
   40114      106542 :          register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
   40115      106542 :          register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
   40116      106542 :          register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
   40117      106542 :          register_sf3(28) register_sf3(29) register_sf3(30)
   40118             :          #undef register_sf3
   40119             : 
   40120             :          #define register_sf3_extid(Id, Op)                                        \
   40121             :          sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
   40122             : 
   40123      213084 :          register_sf3_extid("(t-t)-t",23)  // (t-t)-t --> t-(t+t)
   40124             :          #undef register_sf3_extid
   40125      106542 :       }
   40126             : 
   40127      106542 :       inline void load_sf4_map(sf4_map_t& sf4_map)
   40128             :       {
   40129             :          typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
   40130             : 
   40131             :          #define register_sf4(Op)                                                                             \
   40132             :          sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
   40133             : 
   40134      106542 :          register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
   40135      106542 :          register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
   40136      106542 :          register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
   40137      106542 :          register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
   40138      106542 :          register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
   40139      106542 :          register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
   40140      106542 :          register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
   40141      106542 :          register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
   40142      106542 :          register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
   40143             :          #undef register_sf4
   40144             : 
   40145             :          #define register_sf4ext(Op)                                                                                    \
   40146             :          sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
   40147             : 
   40148      106542 :          register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
   40149      106542 :          register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
   40150      106542 :          register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
   40151      106542 :          register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
   40152      106542 :          register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
   40153      106542 :          register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
   40154      106542 :          register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
   40155      106542 :          register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
   40156      106542 :          register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
   40157      106542 :          register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
   40158      106542 :          register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
   40159      106542 :          register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
   40160      106542 :          register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
   40161      106542 :          register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
   40162      106542 :          register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
   40163      106542 :          register_sf4ext(60) register_sf4ext(61)
   40164             :          #undef register_sf4ext
   40165      106542 :       }
   40166             : 
   40167         116 :       inline results_context_t& results_ctx()
   40168             :       {
   40169         116 :          if (0 == results_context_)
   40170             :          {
   40171         111 :             results_context_ = new results_context_t();
   40172             :          }
   40173             : 
   40174         116 :          return (*results_context_);
   40175             :       }
   40176             : 
   40177      382452 :       inline void return_cleanup()
   40178             :       {
   40179             :          #ifndef exprtk_disable_return_statement
   40180      382452 :          if (results_context_)
   40181             :          {
   40182           0 :             delete results_context_;
   40183           0 :             results_context_ = 0;
   40184             :          }
   40185             : 
   40186      382452 :          state_.return_stmt_present = false;
   40187             :          #endif
   40188      382452 :       }
   40189             : 
   40190             :    private:
   40191             : 
   40192             :       parser(const parser<T>&) exprtk_delete;
   40193             :       parser<T>& operator=(const parser<T>&) exprtk_delete;
   40194             : 
   40195             :       settings_store settings_;
   40196             :       expression_generator<T> expression_generator_;
   40197             :       details::node_allocator node_allocator_;
   40198             :       symtab_store symtab_store_;
   40199             :       dependent_entity_collector dec_;
   40200             :       std::deque<parser_error::type> error_list_;
   40201             :       std::deque<bool> brkcnt_list_;
   40202             :       parser_state state_;
   40203             :       bool resolve_unknown_symbol_;
   40204             :       results_context_t* results_context_;
   40205             :       unknown_symbol_resolver* unknown_symbol_resolver_;
   40206             :       unknown_symbol_resolver default_usr_;
   40207             :       base_ops_map_t base_ops_map_;
   40208             :       unary_op_map_t unary_op_map_;
   40209             :       binary_op_map_t binary_op_map_;
   40210             :       inv_binary_op_map_t inv_binary_op_map_;
   40211             :       sf3_map_t sf3_map_;
   40212             :       sf4_map_t sf4_map_;
   40213             :       std::string synthesis_error_;
   40214             :       scope_element_manager sem_;
   40215             :       std::vector<state_t> current_state_stack_;
   40216             : 
   40217             :       immutable_memory_map_t immutable_memory_map_;
   40218             :       immutable_symtok_map_t immutable_symtok_map_;
   40219             : 
   40220             :       lexer::helper::helper_assembly helper_assembly_;
   40221             : 
   40222             :       lexer::helper::commutative_inserter       commutative_inserter_;
   40223             :       lexer::helper::operator_joiner            operator_joiner_2_;
   40224             :       lexer::helper::operator_joiner            operator_joiner_3_;
   40225             :       lexer::helper::symbol_replacer            symbol_replacer_;
   40226             :       lexer::helper::bracket_checker            bracket_checker_;
   40227             :       lexer::helper::numeric_checker<T>         numeric_checker_;
   40228             :       lexer::helper::sequence_validator         sequence_validator_;
   40229             :       lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
   40230             : 
   40231             :       loop_runtime_check_ptr          loop_runtime_check_;
   40232             :       vector_access_runtime_check_ptr vector_access_runtime_check_;
   40233             :       compilation_check_ptr           compilation_check_ptr_;
   40234             : 
   40235             :       template <typename ParserType>
   40236             :       friend void details::disable_type_checking(ParserType& p);
   40237             :    }; // class parser
   40238             : 
   40239             :    namespace details
   40240             :    {
   40241             :       template <typename T>
   40242             :       struct collector_helper
   40243             :       {
   40244             :          typedef exprtk::symbol_table<T> symbol_table_t;
   40245             :          typedef exprtk::expression<T>   expression_t;
   40246             :          typedef exprtk::parser<T>       parser_t;
   40247             :          typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
   40248             :          typedef typename parser_t::unknown_symbol_resolver usr_t;
   40249             : 
   40250             :          struct resolve_as_vector : public parser_t::unknown_symbol_resolver
   40251             :          {
   40252             :             typedef exprtk::parser<T> parser_t;
   40253             : 
   40254           4 :             resolve_as_vector()
   40255           4 :             : usr_t(usr_t::e_usrmode_extended)
   40256           4 :             {}
   40257             : 
   40258           6 :             virtual bool process(const std::string& unknown_symbol,
   40259             :                                  symbol_table_t& symbol_table,
   40260             :                                  std::string&) exprtk_override
   40261             :             {
   40262             :                static T v[1];
   40263           6 :                symbol_table.add_vector(unknown_symbol,v);
   40264           6 :                return true;
   40265             :             }
   40266             :          };
   40267             : 
   40268           4 :          static inline bool collection_pass(const std::string& expression_string,
   40269             :                                             std::set<std::string>& symbol_set,
   40270             :                                             const bool collect_variables,
   40271             :                                             const bool collect_functions,
   40272             :                                             const bool vector_pass,
   40273             :                                             symbol_table_t& ext_symbol_table)
   40274             :          {
   40275           4 :             symbol_table_t symbol_table;
   40276           4 :             expression_t   expression;
   40277           4 :             parser_t       parser;
   40278             : 
   40279           4 :             resolve_as_vector vect_resolver;
   40280             : 
   40281           4 :             expression.register_symbol_table(symbol_table    );
   40282           4 :             expression.register_symbol_table(ext_symbol_table);
   40283             : 
   40284           4 :             if (vector_pass)
   40285           2 :                parser.enable_unknown_symbol_resolver(&vect_resolver);
   40286             :             else
   40287           2 :                parser.enable_unknown_symbol_resolver();
   40288             : 
   40289           4 :             if (collect_variables)
   40290           2 :                parser.dec().collect_variables() = true;
   40291             : 
   40292           4 :             if (collect_functions)
   40293           2 :                parser.dec().collect_functions() = true;
   40294             : 
   40295           4 :             bool pass_result = false;
   40296             : 
   40297           4 :             details::disable_type_checking(parser);
   40298             : 
   40299           4 :             if (parser.compile(expression_string, expression))
   40300             :             {
   40301           2 :                pass_result = true;
   40302             : 
   40303           2 :                std::deque<symbol_t> symb_list;
   40304           2 :                parser.dec().symbols(symb_list);
   40305             : 
   40306           9 :                for (std::size_t i = 0; i < symb_list.size(); ++i)
   40307             :                {
   40308           7 :                   symbol_set.insert(symb_list[i].first);
   40309             :                }
   40310           2 :             }
   40311             : 
   40312           4 :             return pass_result;
   40313           4 :          }
   40314             :       };
   40315             :    }
   40316             : 
   40317             :    template <typename Allocator,
   40318             :              template <typename, typename> class Sequence>
   40319           1 :    inline bool collect_variables(const std::string& expression,
   40320             :                                  Sequence<std::string, Allocator>& symbol_list)
   40321             :    {
   40322             :       typedef double T;
   40323             :       typedef details::collector_helper<T> collect_t;
   40324             : 
   40325           1 :       collect_t::symbol_table_t null_symbol_table;
   40326             : 
   40327           1 :       std::set<std::string> symbol_set;
   40328             : 
   40329             :       const bool variable_pass = collect_t::collection_pass
   40330           1 :                                     (expression, symbol_set, true, false, false, null_symbol_table);
   40331             :       const bool vector_pass   = collect_t::collection_pass
   40332           1 :                                     (expression, symbol_set, true, false,  true, null_symbol_table);
   40333             : 
   40334           1 :       if (!variable_pass && !vector_pass)
   40335           0 :          return false;
   40336             : 
   40337           1 :       std::set<std::string>::iterator itr = symbol_set.begin();
   40338             : 
   40339           5 :       while (symbol_set.end() != itr)
   40340             :       {
   40341           4 :          symbol_list.push_back(*itr);
   40342           4 :          ++itr;
   40343             :       }
   40344             : 
   40345           1 :       return true;
   40346           1 :    }
   40347             : 
   40348             :    template <typename T,
   40349             :              typename Allocator,
   40350             :              template <typename, typename> class Sequence>
   40351             :    inline bool collect_variables(const std::string& expression,
   40352             :                                  exprtk::symbol_table<T>& extrnl_symbol_table,
   40353             :                                  Sequence<std::string, Allocator>& symbol_list)
   40354             :    {
   40355             :       typedef details::collector_helper<T> collect_t;
   40356             : 
   40357             :       std::set<std::string> symbol_set;
   40358             : 
   40359             :       const bool variable_pass = collect_t::collection_pass
   40360             :                                     (expression, symbol_set, true, false, false, extrnl_symbol_table);
   40361             :       const bool vector_pass   = collect_t::collection_pass
   40362             :                                     (expression, symbol_set, true, false,  true, extrnl_symbol_table);
   40363             : 
   40364             :       if (!variable_pass && !vector_pass)
   40365             :          return false;
   40366             : 
   40367             :       std::set<std::string>::iterator itr = symbol_set.begin();
   40368             : 
   40369             :       while (symbol_set.end() != itr)
   40370             :       {
   40371             :          symbol_list.push_back(*itr);
   40372             :          ++itr;
   40373             :       }
   40374             : 
   40375             :       return true;
   40376             :    }
   40377             : 
   40378             :    template <typename Allocator,
   40379             :              template <typename, typename> class Sequence>
   40380           1 :    inline bool collect_functions(const std::string& expression,
   40381             :                                  Sequence<std::string, Allocator>& symbol_list)
   40382             :    {
   40383             :       typedef double T;
   40384             :       typedef details::collector_helper<T> collect_t;
   40385             : 
   40386           1 :       collect_t::symbol_table_t null_symbol_table;
   40387             : 
   40388           1 :       std::set<std::string> symbol_set;
   40389             : 
   40390             :       const bool variable_pass = collect_t::collection_pass
   40391           1 :                                     (expression, symbol_set, false, true, false, null_symbol_table);
   40392             :       const bool vector_pass   = collect_t::collection_pass
   40393           1 :                                     (expression, symbol_set, false, true,  true, null_symbol_table);
   40394             : 
   40395           1 :       if (!variable_pass && !vector_pass)
   40396           0 :          return false;
   40397             : 
   40398           1 :       std::set<std::string>::iterator itr = symbol_set.begin();
   40399             : 
   40400           4 :       while (symbol_set.end() != itr)
   40401             :       {
   40402           3 :          symbol_list.push_back(*itr);
   40403           3 :          ++itr;
   40404             :       }
   40405             : 
   40406           1 :       return true;
   40407           1 :    }
   40408             : 
   40409             :    template <typename T,
   40410             :              typename Allocator,
   40411             :              template <typename, typename> class Sequence>
   40412             :    inline bool collect_functions(const std::string& expression,
   40413             :                                  exprtk::symbol_table<T>& extrnl_symbol_table,
   40414             :                                  Sequence<std::string, Allocator>& symbol_list)
   40415             :    {
   40416             :       typedef details::collector_helper<T> collect_t;
   40417             : 
   40418             :       std::set<std::string> symbol_set;
   40419             : 
   40420             :       const bool variable_pass = collect_t::collection_pass
   40421             :                                     (expression, symbol_set, false, true, false, extrnl_symbol_table);
   40422             :       const bool vector_pass   = collect_t::collection_pass
   40423             :                                     (expression, symbol_set, false, true,  true, extrnl_symbol_table);
   40424             : 
   40425             :       if (!variable_pass && !vector_pass)
   40426             :          return false;
   40427             : 
   40428             :       std::set<std::string>::iterator itr = symbol_set.begin();
   40429             : 
   40430             :       while (symbol_set.end() != itr)
   40431             :       {
   40432             :          symbol_list.push_back(*itr);
   40433             :          ++itr;
   40434             :       }
   40435             : 
   40436             :       return true;
   40437             :    }
   40438             : 
   40439             :    template <typename T>
   40440           2 :    inline T integrate(const expression<T>& e,
   40441             :                       T& x,
   40442             :                       const T& r0, const T& r1,
   40443             :                       const std::size_t number_of_intervals = 1000000)
   40444             :    {
   40445           2 :       if (r0 > r1)
   40446           0 :          return T(0);
   40447             : 
   40448           2 :       const T h = (r1 - r0) / (T(2) * number_of_intervals);
   40449           2 :       T total_area = T(0);
   40450             : 
   40451     2000002 :       for (std::size_t i = 0; i < number_of_intervals; ++i)
   40452             :       {
   40453     2000000 :          x = r0 + T(2) * i * h;
   40454     2000000 :          const T y0 = e.value(); x += h;
   40455     2000000 :          const T y1 = e.value(); x += h;
   40456     2000000 :          const T y2 = e.value(); x += h;
   40457     2000000 :          total_area += h * (y0 + T(4) * y1 + y2) / T(3);
   40458             :       }
   40459             : 
   40460           2 :       return total_area;
   40461             :    }
   40462             : 
   40463             :    template <typename T>
   40464           1 :    inline T integrate(const expression<T>& e,
   40465             :                       const std::string& variable_name,
   40466             :                       const T& r0, const T& r1,
   40467             :                       const std::size_t number_of_intervals = 1000000)
   40468             :    {
   40469           1 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   40470             : 
   40471           1 :       if (!sym_table.valid())
   40472             :       {
   40473           0 :          return std::numeric_limits<T>::quiet_NaN();
   40474             :       }
   40475             : 
   40476           1 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   40477             : 
   40478           1 :       if (var)
   40479             :       {
   40480           1 :          T& x = var->ref();
   40481           1 :          const T x_original = x;
   40482           1 :          const T result = integrate(e, x, r0, r1, number_of_intervals);
   40483           1 :          x = x_original;
   40484             : 
   40485           1 :          return result;
   40486             :       }
   40487             : 
   40488           0 :       return std::numeric_limits<T>::quiet_NaN();
   40489             :    }
   40490             : 
   40491             :    template <typename T>
   40492     8000000 :    inline T derivative(const expression<T>& e,
   40493             :                        T& x,
   40494     4000000 :                        const T& h = T(0.00000001))
   40495             :    {
   40496     8000000 :       const T x_init = x;
   40497     8000000 :       const T _2h    = T(2) * h;
   40498             : 
   40499     8000000 :       x = x_init + _2h;
   40500     8000000 :       const T y0 = e.value();
   40501     8000000 :       x = x_init + h;
   40502     8000000 :       const T y1 = e.value();
   40503     8000000 :       x = x_init - h;
   40504     8000000 :       const T y2 = e.value();
   40505     8000000 :       x = x_init - _2h;
   40506     8000000 :       const T y3 = e.value();
   40507     8000000 :       x = x_init;
   40508             : 
   40509     8000000 :       return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
   40510             :    }
   40511             : 
   40512             :    template <typename T>
   40513     8000000 :    inline T second_derivative(const expression<T>& e,
   40514             :                               T& x,
   40515     4000000 :                               const T& h = T(0.00001))
   40516             :    {
   40517     8000000 :       const T x_init = x;
   40518     8000000 :       const T _2h    = T(2) * h;
   40519             : 
   40520     8000000 :       const T y = e.value();
   40521     8000000 :       x = x_init + _2h;
   40522     8000000 :       const T y0 = e.value();
   40523     8000000 :       x = x_init + h;
   40524     8000000 :       const T y1 = e.value();
   40525     8000000 :       x = x_init - h;
   40526     8000000 :       const T y2 = e.value();
   40527     8000000 :       x = x_init - _2h;
   40528     8000000 :       const T y3 = e.value();
   40529     8000000 :       x = x_init;
   40530             : 
   40531     8000000 :       return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
   40532             :    }
   40533             : 
   40534             :    template <typename T>
   40535     8000000 :    inline T third_derivative(const expression<T>& e,
   40536             :                              T& x,
   40537     4000000 :                              const T& h = T(0.0001))
   40538             :    {
   40539     8000000 :       const T x_init = x;
   40540     8000000 :       const T _2h    = T(2) * h;
   40541             : 
   40542     8000000 :       x = x_init + _2h;
   40543     8000000 :       const T y0 = e.value();
   40544     8000000 :       x = x_init + h;
   40545     8000000 :       const T y1 = e.value();
   40546     8000000 :       x = x_init - h;
   40547     8000000 :       const T y2 = e.value();
   40548     8000000 :       x = x_init - _2h;
   40549     8000000 :       const T y3 = e.value();
   40550     8000000 :       x = x_init;
   40551             : 
   40552     8000000 :       return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
   40553             :    }
   40554             : 
   40555             :    template <typename T>
   40556     4000000 :    inline T derivative(const expression<T>& e,
   40557             :                        const std::string& variable_name,
   40558     8000000 :                        const T& h = T(0.00000001))
   40559             :    {
   40560     4000000 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   40561             : 
   40562     4000000 :       if (!sym_table.valid())
   40563             :       {
   40564           0 :          return std::numeric_limits<T>::quiet_NaN();
   40565             :       }
   40566             : 
   40567     4000000 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   40568             : 
   40569     4000000 :       if (var)
   40570             :       {
   40571     4000000 :          T& x = var->ref();
   40572     4000000 :          const T x_original = x;
   40573     4000000 :          const T result = derivative(e, x, h);
   40574     4000000 :          x = x_original;
   40575             : 
   40576     4000000 :          return result;
   40577             :       }
   40578             : 
   40579           0 :       return std::numeric_limits<T>::quiet_NaN();
   40580             :    }
   40581             : 
   40582             :    template <typename T>
   40583     4000000 :    inline T second_derivative(const expression<T>& e,
   40584             :                               const std::string& variable_name,
   40585     8000000 :                               const T& h = T(0.00001))
   40586             :    {
   40587     4000000 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   40588             : 
   40589     4000000 :       if (!sym_table.valid())
   40590             :       {
   40591           0 :          return std::numeric_limits<T>::quiet_NaN();
   40592             :       }
   40593             : 
   40594     4000000 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   40595             : 
   40596     4000000 :       if (var)
   40597             :       {
   40598     4000000 :          T& x = var->ref();
   40599     4000000 :          const T x_original = x;
   40600     4000000 :          const T result = second_derivative(e, x, h);
   40601     4000000 :          x = x_original;
   40602             : 
   40603     4000000 :          return result;
   40604             :       }
   40605             : 
   40606           0 :       return std::numeric_limits<T>::quiet_NaN();
   40607             :    }
   40608             : 
   40609             :    template <typename T>
   40610     4000000 :    inline T third_derivative(const expression<T>& e,
   40611             :                              const std::string& variable_name,
   40612     8000000 :                              const T& h = T(0.0001))
   40613             :    {
   40614     4000000 :       const symbol_table<T>& sym_table = e.get_symbol_table();
   40615             : 
   40616     4000000 :       if (!sym_table.valid())
   40617             :       {
   40618           0 :          return std::numeric_limits<T>::quiet_NaN();
   40619             :       }
   40620             : 
   40621     4000000 :       details::variable_node<T>* var = sym_table.get_variable(variable_name);
   40622             : 
   40623     4000000 :       if (var)
   40624             :       {
   40625     4000000 :          T& x = var->ref();
   40626     4000000 :          const T x_original = x;
   40627     4000000 :          const T result = third_derivative(e, x, h);
   40628     4000000 :          x = x_original;
   40629             : 
   40630     4000000 :          return result;
   40631             :       }
   40632             : 
   40633           0 :       return std::numeric_limits<T>::quiet_NaN();
   40634             :    }
   40635             : 
   40636             :    /*
   40637             :       Note: The following 'compute' routines are simple helpers,
   40638             :       for quickly setting up the required pieces of code in order
   40639             :       to evaluate an expression. By virtue of how they operate
   40640             :       there will be an overhead with regards to their setup and
   40641             :       teardown and hence should not be used in time critical
   40642             :       sections of code.
   40643             :       Furthermore they only assume a small sub set of variables,
   40644             :       no string variables or user defined functions.
   40645             :    */
   40646             :    template <typename T>
   40647             :    inline bool compute(const std::string& expression_string, T& result)
   40648             :    {
   40649             :       // No variables
   40650             :       symbol_table<T> symbol_table;
   40651             :       symbol_table.add_constants();
   40652             : 
   40653             :       expression<T> expression;
   40654             :       expression.register_symbol_table(symbol_table);
   40655             : 
   40656             :       parser<T> parser;
   40657             : 
   40658             :       if (parser.compile(expression_string,expression))
   40659             :       {
   40660             :          result = expression.value();
   40661             : 
   40662             :          return true;
   40663             :       }
   40664             :       else
   40665             :          return false;
   40666             :    }
   40667             : 
   40668             :    template <typename T>
   40669             :    inline bool compute(const std::string& expression_string,
   40670             :                        const T& x,
   40671             :                        T& result)
   40672             :    {
   40673             :       // Only 'x'
   40674             :       static const std::string x_var("x");
   40675             : 
   40676             :       symbol_table<T> symbol_table;
   40677             :       symbol_table.add_constants();
   40678             :       symbol_table.add_constant(x_var,x);
   40679             : 
   40680             :       expression<T> expression;
   40681             :       expression.register_symbol_table(symbol_table);
   40682             : 
   40683             :       parser<T> parser;
   40684             : 
   40685             :       if (parser.compile(expression_string,expression))
   40686             :       {
   40687             :          result = expression.value();
   40688             : 
   40689             :          return true;
   40690             :       }
   40691             :       else
   40692             :          return false;
   40693             :    }
   40694             : 
   40695             :    template <typename T>
   40696             :    inline bool compute(const std::string& expression_string,
   40697             :                        const T&x, const T& y,
   40698             :                        T& result)
   40699             :    {
   40700             :       // Only 'x' and 'y'
   40701             :       static const std::string x_var("x");
   40702             :       static const std::string y_var("y");
   40703             : 
   40704             :       symbol_table<T> symbol_table;
   40705             :       symbol_table.add_constants();
   40706             :       symbol_table.add_constant(x_var,x);
   40707             :       symbol_table.add_constant(y_var,y);
   40708             : 
   40709             :       expression<T> expression;
   40710             :       expression.register_symbol_table(symbol_table);
   40711             : 
   40712             :       parser<T> parser;
   40713             : 
   40714             :       if (parser.compile(expression_string,expression))
   40715             :       {
   40716             :          result = expression.value();
   40717             : 
   40718             :          return true;
   40719             :       }
   40720             :       else
   40721             :          return false;
   40722             :    }
   40723             : 
   40724             :    template <typename T>
   40725             :    inline bool compute(const std::string& expression_string,
   40726             :                        const T& x, const T& y, const T& z,
   40727             :                        T& result)
   40728             :    {
   40729             :       // Only 'x', 'y' or 'z'
   40730             :       static const std::string x_var("x");
   40731             :       static const std::string y_var("y");
   40732             :       static const std::string z_var("z");
   40733             : 
   40734             :       symbol_table<T> symbol_table;
   40735             :       symbol_table.add_constants();
   40736             :       symbol_table.add_constant(x_var,x);
   40737             :       symbol_table.add_constant(y_var,y);
   40738             :       symbol_table.add_constant(z_var,z);
   40739             : 
   40740             :       expression<T> expression;
   40741             :       expression.register_symbol_table(symbol_table);
   40742             : 
   40743             :       parser<T> parser;
   40744             : 
   40745             :       if (parser.compile(expression_string,expression))
   40746             :       {
   40747             :          result = expression.value();
   40748             : 
   40749             :          return true;
   40750             :       }
   40751             :       else
   40752             :          return false;
   40753             :    }
   40754             : 
   40755             :    template <typename T, std::size_t N>
   40756             :    class polynomial : public ifunction<T>
   40757             :    {
   40758             :    private:
   40759             : 
   40760             :       template <typename Type, std::size_t NumberOfCoefficients>
   40761             :       struct poly_impl { };
   40762             : 
   40763             :       template <typename Type>
   40764             :       struct poly_impl <Type,12>
   40765             :       {
   40766        1015 :          static inline T evaluate(const Type x,
   40767             :                                   const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
   40768             :                                   const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
   40769             :                                   const Type  c2, const Type  c1, const Type  c0)
   40770             :          {
   40771             :             // 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
   40772        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);
   40773             :          }
   40774             :       };
   40775             : 
   40776             :       template <typename Type>
   40777             :       struct poly_impl <Type,11>
   40778             :       {
   40779        1015 :          static inline T evaluate(const Type x,
   40780             :                                   const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
   40781             :                                   const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
   40782             :                                   const Type c1,  const Type  c0)
   40783             :          {
   40784             :             // 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
   40785        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);
   40786             :          }
   40787             :       };
   40788             : 
   40789             :       template <typename Type>
   40790             :       struct poly_impl <Type,10>
   40791             :       {
   40792        1015 :          static inline T evaluate(const Type x,
   40793             :                                   const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
   40794             :                                   const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
   40795             :                                   const Type c0)
   40796             :          {
   40797             :             // 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
   40798        1015 :             return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   40799             :          }
   40800             :       };
   40801             : 
   40802             :       template <typename Type>
   40803             :       struct poly_impl <Type,9>
   40804             :       {
   40805        1015 :          static inline T evaluate(const Type x,
   40806             :                                   const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
   40807             :                                   const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
   40808             :          {
   40809             :             // 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
   40810        1015 :             return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   40811             :          }
   40812             :       };
   40813             : 
   40814             :       template <typename Type>
   40815             :       struct poly_impl <Type,8>
   40816             :       {
   40817        1015 :          static inline T evaluate(const Type x,
   40818             :                                   const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
   40819             :                                   const Type c3, const Type c2, const Type c1, const Type c0)
   40820             :          {
   40821             :             // 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
   40822        1015 :             return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   40823             :          }
   40824             :       };
   40825             : 
   40826             :       template <typename Type>
   40827             :       struct poly_impl <Type,7>
   40828             :       {
   40829        1015 :          static inline T evaluate(const Type x,
   40830             :                                   const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
   40831             :                                   const Type c2, const Type c1, const Type c0)
   40832             :          {
   40833             :             // 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
   40834        1015 :             return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   40835             :          }
   40836             :       };
   40837             : 
   40838             :       template <typename Type>
   40839             :       struct poly_impl <Type,6>
   40840             :       {
   40841        1015 :          static inline T evaluate(const Type x,
   40842             :                                   const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
   40843             :                                   const Type c1, const Type c0)
   40844             :          {
   40845             :             // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   40846        1015 :             return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   40847             :          }
   40848             :       };
   40849             : 
   40850             :       template <typename Type>
   40851             :       struct poly_impl <Type,5>
   40852             :       {
   40853        1015 :          static inline T evaluate(const Type x,
   40854             :                                   const Type c5, const Type c4, const Type c3, const Type c2,
   40855             :                                   const Type c1, const Type c0)
   40856             :          {
   40857             :             // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   40858        1015 :             return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
   40859             :          }
   40860             :       };
   40861             : 
   40862             :       template <typename Type>
   40863             :       struct poly_impl <Type,4>
   40864             :       {
   40865        1015 :          static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
   40866             :          {
   40867             :             // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   40868        1015 :             return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
   40869             :          }
   40870             :       };
   40871             : 
   40872             :       template <typename Type>
   40873             :       struct poly_impl <Type,3>
   40874             :       {
   40875        1015 :          static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
   40876             :          {
   40877             :             // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
   40878        1015 :             return (((c3 * x + c2) * x + c1) * x + c0);
   40879             :          }
   40880             :       };
   40881             : 
   40882             :       template <typename Type>
   40883             :       struct poly_impl <Type,2>
   40884             :       {
   40885        1015 :          static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
   40886             :          {
   40887             :             // p(x) = c_2x^2 + c_1x^1 + c_0x^0
   40888        1015 :             return ((c2 * x + c1) * x + c0);
   40889             :          }
   40890             :       };
   40891             : 
   40892             :       template <typename Type>
   40893             :       struct poly_impl <Type,1>
   40894             :       {
   40895        1015 :          static inline T evaluate(const Type x, const Type c1, const Type c0)
   40896             :          {
   40897             :             // p(x) = c_1x^1 + c_0x^0
   40898        1015 :             return (c1 * x + c0);
   40899             :          }
   40900             :       };
   40901             : 
   40902             :    public:
   40903             : 
   40904             :       using ifunction<T>::operator();
   40905             : 
   40906      128736 :       polynomial()
   40907      128736 :       : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
   40908             :       {
   40909      128736 :          disable_has_side_effects(*this);
   40910      128736 :       }
   40911             : 
   40912      128736 :       virtual ~polynomial()
   40913      128736 :       {}
   40914             : 
   40915             :       #define poly_rtrn(NN) \
   40916             :       return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
   40917             : 
   40918        1015 :       inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override
   40919             :       {
   40920        1015 :          poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
   40921             :       }
   40922             : 
   40923        1015 :       inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override
   40924             :       {
   40925        1015 :          poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
   40926             :       }
   40927             : 
   40928        1015 :       inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   40929             :       {
   40930        1015 :          poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
   40931             :       }
   40932             : 
   40933        1015 :       inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1,
   40934             :                                    const T& c0) exprtk_override
   40935             :       {
   40936        1015 :          poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
   40937             :       }
   40938             : 
   40939        1015 :       inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2,
   40940             :                                    const T& c1, const T& c0) exprtk_override
   40941             :       {
   40942        1015 :          poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
   40943             :       }
   40944             : 
   40945        1015 :       inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3,
   40946             :                                    const T& c2, const T& c1, const T& c0) exprtk_override
   40947             :       {
   40948        1015 :          poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
   40949             :       }
   40950             : 
   40951        1015 :       inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4,
   40952             :                                    const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   40953             :       {
   40954        1015 :          poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
   40955             :       }
   40956             : 
   40957        1015 :       inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5,
   40958             :                                    const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   40959             :       {
   40960        1015 :          poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   40961             :       }
   40962             : 
   40963        1015 :       inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6,
   40964             :                                    const T& c5, const T& c4, const T& c3, const T& c2, const T& c1,
   40965             :                                    const T& c0) exprtk_override
   40966             :       {
   40967        1015 :          poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   40968             :       }
   40969             : 
   40970        1015 :       inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7,
   40971             :                                    const T& c6, const T& c5, const T& c4, const T& c3, const T& c2,
   40972             :                                    const T& c1, const T& c0) exprtk_override
   40973             :       {
   40974        1015 :          poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   40975             :       }
   40976             : 
   40977        1015 :       inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8,
   40978             :                                    const T& c7, const T& c6, const T& c5, const T& c4, const T& c3,
   40979             :                                    const T& c2, const T& c1, const T& c0) exprtk_override
   40980             :       {
   40981        1015 :          poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   40982             :       }
   40983             : 
   40984        1015 :       inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9,
   40985             :                                    const T& c8, const T& c7, const T& c6, const T& c5, const T& c4,
   40986             :                                    const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
   40987             :       {
   40988        1015 :          poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
   40989             :       }
   40990             : 
   40991             :       #undef poly_rtrn
   40992             : 
   40993           0 :       inline virtual T operator() () exprtk_override
   40994             :       {
   40995           0 :          return std::numeric_limits<T>::quiet_NaN();
   40996             :       }
   40997             : 
   40998           0 :       inline virtual T operator() (const T&) exprtk_override
   40999             :       {
   41000           0 :          return std::numeric_limits<T>::quiet_NaN();
   41001             :       }
   41002             : 
   41003           0 :       inline virtual T operator() (const T&, const T&) exprtk_override
   41004             :       {
   41005           0 :          return std::numeric_limits<T>::quiet_NaN();
   41006             :       }
   41007             :    };
   41008             : 
   41009             :    template <typename T>
   41010             :    class function_compositor
   41011             :    {
   41012             :    public:
   41013             : 
   41014             :       typedef exprtk::expression<T>             expression_t;
   41015             :       typedef exprtk::symbol_table<T>           symbol_table_t;
   41016             :       typedef exprtk::parser<T>                 parser_t;
   41017             :       typedef typename parser_t::settings_store settings_t;
   41018             : 
   41019             :       struct function
   41020             :       {
   41021             :          function()
   41022             :          {}
   41023             : 
   41024         700 :          function(const std::string& n)
   41025         700 :          : name_(n)
   41026         700 :          {}
   41027             : 
   41028           1 :          function(const std::string& name,
   41029             :                   const std::string& expression)
   41030           1 :          : name_(name)
   41031           1 :          , expression_(expression)
   41032           1 :          {}
   41033             : 
   41034          19 :          function(const std::string& name,
   41035             :                   const std::string& expression,
   41036             :                   const std::string& v0)
   41037          19 :          : name_(name)
   41038          19 :          , expression_(expression)
   41039             :          {
   41040          19 :             v_.push_back(v0);
   41041          19 :          }
   41042             : 
   41043           4 :          function(const std::string& name,
   41044             :                   const std::string& expression,
   41045             :                   const std::string& v0, const std::string& v1)
   41046           4 :          : name_(name)
   41047           4 :          , expression_(expression)
   41048             :          {
   41049           4 :             v_.push_back(v0); v_.push_back(v1);
   41050           4 :          }
   41051             : 
   41052           1 :          function(const std::string& name,
   41053             :                   const std::string& expression,
   41054             :                   const std::string& v0, const std::string& v1,
   41055             :                   const std::string& v2)
   41056           1 :          : name_(name)
   41057           1 :          , expression_(expression)
   41058             :          {
   41059           1 :             v_.push_back(v0); v_.push_back(v1);
   41060           1 :             v_.push_back(v2);
   41061           1 :          }
   41062             : 
   41063           2 :          function(const std::string& name,
   41064             :                   const std::string& expression,
   41065             :                   const std::string& v0, const std::string& v1,
   41066             :                   const std::string& v2, const std::string& v3)
   41067           2 :          : name_(name)
   41068           2 :          , expression_(expression)
   41069             :          {
   41070           2 :             v_.push_back(v0); v_.push_back(v1);
   41071           2 :             v_.push_back(v2); v_.push_back(v3);
   41072           2 :          }
   41073             : 
   41074             :          function(const std::string& name,
   41075             :                   const std::string& expression,
   41076             :                   const std::string& v0, const std::string& v1,
   41077             :                   const std::string& v2, const std::string& v3,
   41078             :                   const std::string& v4)
   41079             :          : name_(name)
   41080             :          , expression_(expression)
   41081             :          {
   41082             :             v_.push_back(v0); v_.push_back(v1);
   41083             :             v_.push_back(v2); v_.push_back(v3);
   41084             :             v_.push_back(v4);
   41085             :          }
   41086             : 
   41087             :          inline function& name(const std::string& n)
   41088             :          {
   41089             :             name_ = n;
   41090             :             return (*this);
   41091             :          }
   41092             : 
   41093         700 :          inline function& expression(const std::string& e)
   41094             :          {
   41095         700 :             expression_ = e;
   41096         700 :             return (*this);
   41097             :          }
   41098             : 
   41099        2100 :          inline function& var(const std::string& v)
   41100             :          {
   41101        2100 :             v_.push_back(v);
   41102        2100 :             return (*this);
   41103             :          }
   41104             : 
   41105             :          inline function& vars(const std::string& v0,
   41106             :                                const std::string& v1)
   41107             :          {
   41108             :             v_.push_back(v0);
   41109             :             v_.push_back(v1);
   41110             :             return (*this);
   41111             :          }
   41112             : 
   41113             :          inline function& vars(const std::string& v0,
   41114             :                                const std::string& v1,
   41115             :                                const std::string& v2)
   41116             :          {
   41117             :             v_.push_back(v0);
   41118             :             v_.push_back(v1);
   41119             :             v_.push_back(v2);
   41120             :             return (*this);
   41121             :          }
   41122             : 
   41123             :          inline function& vars(const std::string& v0,
   41124             :                                const std::string& v1,
   41125             :                                const std::string& v2,
   41126             :                                const std::string& v3)
   41127             :          {
   41128             :             v_.push_back(v0);
   41129             :             v_.push_back(v1);
   41130             :             v_.push_back(v2);
   41131             :             v_.push_back(v3);
   41132             :             return (*this);
   41133             :          }
   41134             : 
   41135             :          inline function& vars(const std::string& v0,
   41136             :                                const std::string& v1,
   41137             :                                const std::string& v2,
   41138             :                                const std::string& v3,
   41139             :                                const std::string& v4)
   41140             :          {
   41141             :             v_.push_back(v0);
   41142             :             v_.push_back(v1);
   41143             :             v_.push_back(v2);
   41144             :             v_.push_back(v3);
   41145             :             v_.push_back(v4);
   41146             :             return (*this);
   41147             :          }
   41148             : 
   41149             :          std::string name_;
   41150             :          std::string expression_;
   41151             :          std::deque<std::string> v_;
   41152             :       };
   41153             : 
   41154             :    private:
   41155             : 
   41156             :       struct base_func : public exprtk::ifunction<T>
   41157             :       {
   41158             :          typedef const T&                       type;
   41159             :          typedef exprtk::ifunction<T>     function_t;
   41160             :          typedef std::vector<T*>            varref_t;
   41161             :          typedef std::vector<T>                var_t;
   41162             :          typedef std::pair<T*,std::size_t> lvarref_t;
   41163             :          typedef std::vector<lvarref_t>    lvr_vec_t;
   41164             : 
   41165             :          using exprtk::ifunction<T>::operator();
   41166             : 
   41167         727 :          base_func(const std::size_t& pc = 0)
   41168             :          : exprtk::ifunction<T>(pc)
   41169         727 :          , local_var_stack_size(0)
   41170         727 :          , stack_depth(0)
   41171             :          {
   41172         727 :             v.resize(pc);
   41173         727 :          }
   41174             : 
   41175         727 :          virtual ~base_func()
   41176         727 :          {}
   41177             : 
   41178             :          #define exprtk_assign(Index) \
   41179             :          (*v[Index]) = v##Index;      \
   41180             : 
   41181    45706176 :          inline void update(const T& v0)
   41182             :          {
   41183    45706176 :             exprtk_assign(0)
   41184    45706176 :          }
   41185             : 
   41186      116833 :          inline void update(const T& v0, const T& v1)
   41187             :          {
   41188      116833 :             exprtk_assign(0) exprtk_assign(1)
   41189      116833 :          }
   41190             : 
   41191       12900 :          inline void update(const T& v0, const T& v1, const T& v2)
   41192             :          {
   41193       12900 :             exprtk_assign(0) exprtk_assign(1)
   41194       12900 :             exprtk_assign(2)
   41195       12900 :          }
   41196             : 
   41197        4264 :          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
   41198             :          {
   41199        4264 :             exprtk_assign(0) exprtk_assign(1)
   41200        4264 :             exprtk_assign(2) exprtk_assign(3)
   41201        4264 :          }
   41202             : 
   41203        1000 :          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
   41204             :          {
   41205        1000 :             exprtk_assign(0) exprtk_assign(1)
   41206        1000 :             exprtk_assign(2) exprtk_assign(3)
   41207        1000 :             exprtk_assign(4)
   41208        1000 :          }
   41209             : 
   41210         200 :          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
   41211             :          {
   41212         200 :             exprtk_assign(0) exprtk_assign(1)
   41213         200 :             exprtk_assign(2) exprtk_assign(3)
   41214         200 :             exprtk_assign(4) exprtk_assign(5)
   41215         200 :          }
   41216             : 
   41217             :          #ifdef exprtk_assign
   41218             :          #undef exprtk_assign
   41219             :          #endif
   41220             : 
   41221         727 :          inline function_t& setup(expression_t& expr)
   41222             :          {
   41223         727 :             expression = expr;
   41224             : 
   41225             :             typedef typename expression_t::control_block::local_data_list_t ldl_t;
   41226             : 
   41227         727 :             const ldl_t ldl = expr.local_data_list();
   41228             : 
   41229         727 :             std::vector<std::size_t> index_list;
   41230             : 
   41231        5043 :             for (std::size_t i = 0; i < ldl.size(); ++i)
   41232             :             {
   41233        4316 :                if (ldl[i].size)
   41234             :                {
   41235        2158 :                   index_list.push_back(i);
   41236             :                }
   41237             :             }
   41238             : 
   41239         727 :             std::size_t input_param_count = 0;
   41240             : 
   41241        2885 :             for (std::size_t i = 0; i < index_list.size(); ++i)
   41242             :             {
   41243        2158 :                const std::size_t index = index_list[i];
   41244             : 
   41245        2158 :                if (i < (index_list.size() - v.size()))
   41246             :                {
   41247          20 :                   lv.push_back(
   41248           0 :                         std::make_pair(
   41249          20 :                            reinterpret_cast<T*>(ldl[index].pointer),
   41250          20 :                            ldl[index].size));
   41251             : 
   41252          20 :                   local_var_stack_size += ldl[index].size;
   41253             :                }
   41254             :                else
   41255        2138 :                   v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
   41256             :             }
   41257             : 
   41258         727 :             clear_stack();
   41259             : 
   41260         727 :             return (*this);
   41261         727 :          }
   41262             : 
   41263    45841373 :          inline void pre()
   41264             :          {
   41265    45841373 :             if (stack_depth++)
   41266             :             {
   41267    45705335 :                if (!v.empty())
   41268             :                {
   41269    45705335 :                   var_t var_stack(v.size(),T(0));
   41270    45705335 :                   copy(v,var_stack);
   41271    45705335 :                   param_stack.push_back(var_stack);
   41272    45705335 :                }
   41273             : 
   41274    45705335 :                if (!lv.empty())
   41275             :                {
   41276        4950 :                   var_t local_var_stack(local_var_stack_size,T(0));
   41277        4950 :                   copy(lv,local_var_stack);
   41278        4950 :                   local_stack.push_back(local_var_stack);
   41279        4950 :                }
   41280             :             }
   41281    45841373 :          }
   41282             : 
   41283    45841373 :          inline void post()
   41284             :          {
   41285    45841373 :             if (--stack_depth)
   41286             :             {
   41287    45705335 :                if (!v.empty())
   41288             :                {
   41289    45705335 :                   copy(param_stack.back(),v);
   41290    45705335 :                   param_stack.pop_back();
   41291             :                }
   41292             : 
   41293    45705335 :                if (!lv.empty())
   41294             :                {
   41295        4950 :                   copy(local_stack.back(),lv);
   41296        4950 :                   local_stack.pop_back();
   41297             :                }
   41298             :             }
   41299    45841373 :          }
   41300             : 
   41301    45705335 :          void copy(const varref_t& src_v, var_t& dest_v)
   41302             :          {
   41303    91488223 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   41304             :             {
   41305    45782888 :                dest_v[i] = (*src_v[i]);
   41306             :             }
   41307    45705335 :          }
   41308             : 
   41309    45705335 :          void copy(const var_t& src_v, varref_t& dest_v)
   41310             :          {
   41311    91488223 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   41312             :             {
   41313    45782888 :                (*dest_v[i]) = src_v[i];
   41314             :             }
   41315    45705335 :          }
   41316             : 
   41317        4950 :          void copy(const lvr_vec_t& src_v, var_t& dest_v)
   41318             :          {
   41319        4950 :             typename var_t::iterator itr = dest_v.begin();
   41320             :             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
   41321             : 
   41322        9900 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   41323             :             {
   41324        4950 :                lvarref_t vr = src_v[i];
   41325             : 
   41326        4950 :                if (1 == vr.second)
   41327        4950 :                   *itr++ = (*vr.first);
   41328             :                else
   41329             :                {
   41330           0 :                   std::copy(vr.first, vr.first + vr.second, itr);
   41331           0 :                   itr += static_cast<diff_t>(vr.second);
   41332             :                }
   41333             :             }
   41334        4950 :          }
   41335             : 
   41336        4950 :          void copy(const var_t& src_v, lvr_vec_t& dest_v)
   41337             :          {
   41338        4950 :             typename var_t::const_iterator itr = src_v.begin();
   41339             :             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
   41340             : 
   41341        9900 :             for (std::size_t i = 0; i < src_v.size(); ++i)
   41342             :             {
   41343        4950 :                lvarref_t vr = dest_v[i];
   41344             : 
   41345        4950 :                if (1 == vr.second)
   41346        4950 :                   (*vr.first) = *itr++;
   41347             :                else
   41348             :                {
   41349           0 :                   std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
   41350           0 :                   itr += static_cast<diff_t>(vr.second);
   41351             :                }
   41352             :             }
   41353        4950 :          }
   41354             : 
   41355         727 :          inline void clear_stack()
   41356             :          {
   41357        2865 :             for (std::size_t i = 0; i < v.size(); ++i)
   41358             :             {
   41359        2138 :                (*v[i]) = 0;
   41360             :             }
   41361         727 :          }
   41362             : 
   41363    45918873 :          inline virtual T value(expression_t& e)
   41364             :          {
   41365    45918873 :             return e.value();
   41366             :          }
   41367             : 
   41368             :          expression_t expression;
   41369             :          varref_t v;
   41370             :          lvr_vec_t lv;
   41371             :          std::size_t local_var_stack_size;
   41372             :          std::size_t stack_depth;
   41373             :          std::deque<var_t> param_stack;
   41374             :          std::deque<var_t> local_stack;
   41375             :       };
   41376             : 
   41377             :       typedef std::map<std::string,base_func*> funcparam_t;
   41378             : 
   41379             :       struct func_0param : public base_func
   41380             :       {
   41381             :          using exprtk::ifunction<T>::operator();
   41382             : 
   41383         101 :          func_0param() : base_func(0) {}
   41384             : 
   41385       77500 :          inline T operator() () exprtk_override
   41386             :          {
   41387       77500 :             return this->value(base_func::expression);
   41388             :          }
   41389             :       };
   41390             : 
   41391             :       typedef const T& type;
   41392             : 
   41393             :       template <typename BaseFuncType>
   41394             :       struct scoped_bft
   41395             :       {
   41396    45841373 :          explicit scoped_bft(BaseFuncType& bft)
   41397    45841373 :          : bft_(bft)
   41398             :          {
   41399    45841373 :             bft_.pre ();
   41400    45841373 :          }
   41401             : 
   41402    45841373 :         ~scoped_bft()
   41403             :          {
   41404    45841373 :             bft_.post();
   41405    45841373 :          }
   41406             : 
   41407             :          BaseFuncType& bft_;
   41408             : 
   41409             :       private:
   41410             : 
   41411             :          scoped_bft(const scoped_bft&) exprtk_delete;
   41412             :          scoped_bft& operator=(const scoped_bft&) exprtk_delete;
   41413             :       };
   41414             : 
   41415             :       struct func_1param : public base_func
   41416             :       {
   41417             :          using exprtk::ifunction<T>::operator();
   41418             : 
   41419         119 :          func_1param() : base_func(1) {}
   41420             : 
   41421    45706176 :          inline T operator() (type v0) exprtk_override
   41422             :          {
   41423    45706176 :             scoped_bft<func_1param> sb(*this);
   41424    45706176 :             base_func::update(v0);
   41425    91412352 :             return this->value(base_func::expression);
   41426    45706176 :          }
   41427             :       };
   41428             : 
   41429             :       struct func_2param : public base_func
   41430             :       {
   41431             :          using exprtk::ifunction<T>::operator();
   41432             : 
   41433         104 :          func_2param() : base_func(2) {}
   41434             : 
   41435      116833 :          inline T operator() (type v0, type v1) exprtk_override
   41436             :          {
   41437      116833 :             scoped_bft<func_2param> sb(*this);
   41438      116833 :             base_func::update(v0, v1);
   41439      233666 :             return this->value(base_func::expression);
   41440      116833 :          }
   41441             :       };
   41442             : 
   41443             :       struct func_3param : public base_func
   41444             :       {
   41445             :          using exprtk::ifunction<T>::operator();
   41446             : 
   41447         101 :          func_3param() : base_func(3) {}
   41448             : 
   41449       12900 :          inline T operator() (type v0, type v1, type v2) exprtk_override
   41450             :          {
   41451       12900 :             scoped_bft<func_3param> sb(*this);
   41452       12900 :             base_func::update(v0, v1, v2);
   41453       25800 :             return this->value(base_func::expression);
   41454       12900 :          }
   41455             :       };
   41456             : 
   41457             :       struct func_4param : public base_func
   41458             :       {
   41459             :          using exprtk::ifunction<T>::operator();
   41460             : 
   41461         102 :          func_4param() : base_func(4) {}
   41462             : 
   41463        4264 :          inline T operator() (type v0, type v1, type v2, type v3) exprtk_override
   41464             :          {
   41465        4264 :             scoped_bft<func_4param> sb(*this);
   41466        4264 :             base_func::update(v0, v1, v2, v3);
   41467        8528 :             return this->value(base_func::expression);
   41468        4264 :          }
   41469             :       };
   41470             : 
   41471             :       struct func_5param : public base_func
   41472             :       {
   41473             :          using exprtk::ifunction<T>::operator();
   41474             : 
   41475         100 :          func_5param() : base_func(5) {}
   41476             : 
   41477        1000 :          inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override
   41478             :          {
   41479        1000 :             scoped_bft<func_5param> sb(*this);
   41480        1000 :             base_func::update(v0, v1, v2, v3, v4);
   41481        2000 :             return this->value(base_func::expression);
   41482        1000 :          }
   41483             :       };
   41484             : 
   41485             :       struct func_6param : public base_func
   41486             :       {
   41487             :          using exprtk::ifunction<T>::operator();
   41488             : 
   41489         100 :          func_6param() : base_func(6) {}
   41490             : 
   41491         200 :          inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override
   41492             :          {
   41493         200 :             scoped_bft<func_6param> sb(*this);
   41494         200 :             base_func::update(v0, v1, v2, v3, v4, v5);
   41495         400 :             return this->value(base_func::expression);
   41496         200 :          }
   41497             :       };
   41498             : 
   41499           0 :       static T return_value(expression_t& e)
   41500             :       {
   41501             :          typedef exprtk::results_context<T> results_context_t;
   41502             :          typedef typename results_context_t::type_store_t type_t;
   41503             :          typedef typename type_t::scalar_view scalar_t;
   41504             : 
   41505           0 :          const T result = e.value();
   41506             : 
   41507           0 :          if (e.return_invoked())
   41508             :          {
   41509             :             // Due to the post compilation checks, it can be safely
   41510             :             // assumed that there will be at least one parameter
   41511             :             // and that the first parameter will always be scalar.
   41512           0 :             return scalar_t(e.results()[0])();
   41513             :          }
   41514             : 
   41515           0 :          return result;
   41516             :       }
   41517             : 
   41518             :       #define def_fp_retval(N)                                            \
   41519             :       struct func_##N##param_retval exprtk_final : public func_##N##param \
   41520             :       {                                                                   \
   41521             :          inline T value(expression_t& e) exprtk_override                  \
   41522             :          {                                                                \
   41523             :             return return_value(e);                                       \
   41524             :          }                                                                \
   41525             :       };                                                                  \
   41526             : 
   41527           0 :       def_fp_retval(0)
   41528           0 :       def_fp_retval(1)
   41529           0 :       def_fp_retval(2)
   41530           0 :       def_fp_retval(3)
   41531           0 :       def_fp_retval(4)
   41532           0 :       def_fp_retval(5)
   41533           0 :       def_fp_retval(6)
   41534             : 
   41535             :       #undef def_fp_retval
   41536             : 
   41537             :       template <typename Allocator,
   41538             :                 template <typename, typename> class Sequence>
   41539         727 :       inline bool add(const std::string& name,
   41540             :                       const std::string& expression,
   41541             :                       const Sequence<std::string,Allocator>& var_list,
   41542             :                       const bool override = false)
   41543             :       {
   41544         727 :          const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
   41545             : 
   41546         727 :          if (expr_map_.end() != itr)
   41547             :          {
   41548           0 :             if (!override)
   41549             :             {
   41550             :                exprtk_debug(("Compositor error(add): function '%s' already defined\n",
   41551             :                              name.c_str()));
   41552             : 
   41553           0 :                return false;
   41554             :             }
   41555             : 
   41556           0 :             remove(name, var_list.size());
   41557             :          }
   41558             : 
   41559         727 :          if (compile_expression(name, expression, var_list))
   41560             :          {
   41561         727 :             const std::size_t n = var_list.size();
   41562             : 
   41563         727 :             fp_map_[n][name]->setup(expr_map_[name]);
   41564             : 
   41565         727 :             return true;
   41566             :          }
   41567             :          else
   41568             :          {
   41569             :             exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
   41570             :                           name.c_str()));
   41571             : 
   41572           0 :             return false;
   41573             :          }
   41574             :       }
   41575             : 
   41576             :    public:
   41577             : 
   41578         103 :       function_compositor()
   41579         103 :       : parser_(settings_t::default_compile_all_opts +
   41580             :                 settings_t::e_disable_zero_return)
   41581         206 :       , fp_map_(7)
   41582         103 :       , load_variables_(false)
   41583         309 :       , load_vectors_(false)
   41584         103 :       {}
   41585             : 
   41586           3 :       explicit function_compositor(const symbol_table_t& st)
   41587           3 :       : symbol_table_(st)
   41588           3 :       , parser_(settings_t::default_compile_all_opts +
   41589             :                 settings_t::e_disable_zero_return)
   41590           6 :       , fp_map_(7)
   41591           3 :       , load_variables_(false)
   41592           6 :       , load_vectors_(false)
   41593           3 :       {}
   41594             : 
   41595         106 :      ~function_compositor()
   41596             :       {
   41597         106 :          clear();
   41598         106 :       }
   41599             : 
   41600         103 :       inline symbol_table_t& symbol_table()
   41601             :       {
   41602         103 :          return symbol_table_;
   41603             :       }
   41604             : 
   41605             :       inline const symbol_table_t& symbol_table() const
   41606             :       {
   41607             :          return symbol_table_;
   41608             :       }
   41609             : 
   41610             :       inline void add_auxiliary_symtab(symbol_table_t& symtab)
   41611             :       {
   41612             :          auxiliary_symtab_list_.push_back(&symtab);
   41613             :       }
   41614             : 
   41615             :       void load_variables(const bool load = true)
   41616             :       {
   41617             :          load_variables_ = load;
   41618             :       }
   41619             : 
   41620             :       void load_vectors(const bool load = true)
   41621             :       {
   41622             :          load_vectors_ = load;
   41623             :       }
   41624             : 
   41625         106 :       void clear()
   41626             :       {
   41627         106 :          symbol_table_.clear();
   41628         106 :          expr_map_    .clear();
   41629             : 
   41630         848 :          for (std::size_t i = 0; i < fp_map_.size(); ++i)
   41631             :          {
   41632         742 :             typename funcparam_t::iterator itr = fp_map_[i].begin();
   41633         742 :             typename funcparam_t::iterator end = fp_map_[i].end  ();
   41634             : 
   41635        1469 :             while (itr != end)
   41636             :             {
   41637         727 :                delete itr->second;
   41638         727 :                ++itr;
   41639             :             }
   41640             : 
   41641         742 :             fp_map_[i].clear();
   41642             :          }
   41643         106 :       }
   41644             : 
   41645         727 :       inline bool add(const function& f, const bool override = false)
   41646             :       {
   41647         727 :          return add(f.name_, f.expression_, f.v_,override);
   41648             :       }
   41649             : 
   41650             :       inline std::string error() const
   41651             :       {
   41652             :          if (!error_list_.empty())
   41653             :          {
   41654             :             return error_list_[0].diagnostic;
   41655             :          }
   41656             :          else
   41657             :             return std::string("No Error");
   41658             :       }
   41659             : 
   41660             :       inline std::size_t error_count() const
   41661             :       {
   41662             :          return error_list_.size();
   41663             :       }
   41664             : 
   41665             :       inline parser_error::type get_error(const std::size_t& index) const
   41666             :       {
   41667             :          if (index < error_list_.size())
   41668             :             return error_list_[index];
   41669             :          else
   41670             :             throw std::invalid_argument("compositor::get_error() - Invalid error index specified");
   41671             :       }
   41672             : 
   41673             :    private:
   41674             : 
   41675             :       template <typename Allocator,
   41676             :                 template <typename, typename> class Sequence>
   41677         727 :       bool compile_expression(const std::string& name,
   41678             :                               const std::string& expression,
   41679             :                               const Sequence<std::string,Allocator>& input_var_list,
   41680             :                               bool  return_present = false)
   41681             :       {
   41682         727 :          expression_t compiled_expression;
   41683         727 :          symbol_table_t local_symbol_table;
   41684             : 
   41685         727 :          local_symbol_table.load_from(symbol_table_);
   41686         727 :          local_symbol_table.add_constants();
   41687             : 
   41688         727 :          if (load_variables_)
   41689             :          {
   41690           0 :             local_symbol_table.load_variables_from(symbol_table_);
   41691             :          }
   41692             : 
   41693         727 :          if (load_vectors_)
   41694             :          {
   41695           0 :             local_symbol_table.load_vectors_from(symbol_table_);
   41696             :          }
   41697             : 
   41698         727 :          error_list_.clear();
   41699             : 
   41700         727 :          if (!valid(name,input_var_list.size()))
   41701             :          {
   41702           0 :             parser_error::type error =
   41703             :                parser_error::make_error(
   41704             :                   parser_error::e_parser,
   41705           0 :                   lexer::token(),
   41706             :                   "ERR250 - Function '" + name + "' is an invalid overload",
   41707             :                   exprtk_error_location);
   41708             : 
   41709           0 :             error_list_.push_back(error);
   41710           0 :             return false;
   41711           0 :          }
   41712             : 
   41713        2181 :          if (!forward(name,
   41714         727 :                       input_var_list.size(),
   41715             :                       local_symbol_table,
   41716             :                       return_present))
   41717           0 :             return false;
   41718             : 
   41719         727 :          compiled_expression.register_symbol_table(local_symbol_table);
   41720             : 
   41721         727 :          for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
   41722             :          {
   41723           0 :             compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
   41724             :          }
   41725             : 
   41726         727 :          std::string mod_expression;
   41727             : 
   41728        2865 :          for (std::size_t i = 0; i < input_var_list.size(); ++i)
   41729             :          {
   41730        2138 :             mod_expression += " var " + input_var_list[i] + "{};\n";
   41731             :          }
   41732             : 
   41733         727 :          if (
   41734         727 :               ('{' == details::front(expression)) &&
   41735           0 :               ('}' == details::back (expression))
   41736             :             )
   41737           0 :             mod_expression += "~" + expression + ";";
   41738             :          else
   41739         727 :             mod_expression += "~{" + expression + "};";
   41740             : 
   41741         727 :          if (!parser_.compile(mod_expression,compiled_expression))
   41742             :          {
   41743             :             exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str()));
   41744             :             exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str()));
   41745             : 
   41746           0 :             remove(name,input_var_list.size());
   41747             : 
   41748           0 :             for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index)
   41749             :             {
   41750           0 :                error_list_.push_back(parser_.get_error(err_index));
   41751             :             }
   41752             : 
   41753           0 :             return false;
   41754             :          }
   41755             : 
   41756         727 :          if (!return_present && parser_.dec().return_present())
   41757             :          {
   41758           0 :             remove(name,input_var_list.size());
   41759           0 :             return compile_expression(name, expression, input_var_list, true);
   41760             :          }
   41761             : 
   41762             :          // Make sure every return point has a scalar as its first parameter
   41763         727 :          if (parser_.dec().return_present())
   41764             :          {
   41765             :             typedef std::vector<std::string> str_list_t;
   41766             : 
   41767           0 :             str_list_t ret_param_list = parser_.dec().return_param_type_list();
   41768             : 
   41769           0 :             for (std::size_t i = 0; i < ret_param_list.size(); ++i)
   41770             :             {
   41771           0 :                const std::string& params = ret_param_list[i];
   41772             : 
   41773           0 :                if (params.empty() || ('T' != params[0]))
   41774             :                {
   41775             :                   exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
   41776             :                                 name.c_str()));
   41777             : 
   41778           0 :                   remove(name,input_var_list.size());
   41779             : 
   41780           0 :                   return false;
   41781             :                }
   41782             :             }
   41783           0 :          }
   41784             : 
   41785         727 :          expr_map_[name] = compiled_expression;
   41786             : 
   41787         727 :          exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
   41788             : 
   41789         727 :          if (symbol_table_.add_function(name,ifunc))
   41790         727 :             return true;
   41791             :          else
   41792             :          {
   41793             :             exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
   41794             :                           name.c_str()));
   41795           0 :             return false;
   41796             :          }
   41797         727 :       }
   41798             : 
   41799         727 :       inline bool symbol_used(const std::string& symbol) const
   41800             :       {
   41801             :          return (
   41802         727 :                   symbol_table_.is_variable       (symbol) ||
   41803         727 :                   symbol_table_.is_stringvar      (symbol) ||
   41804         727 :                   symbol_table_.is_function       (symbol) ||
   41805        2181 :                   symbol_table_.is_vector         (symbol) ||
   41806         727 :                   symbol_table_.is_vararg_function(symbol)
   41807         727 :                 );
   41808             :       }
   41809             : 
   41810         727 :       inline bool valid(const std::string& name,
   41811             :                         const std::size_t& arg_count) const
   41812             :       {
   41813         727 :          if (arg_count > 6)
   41814           0 :             return false;
   41815         727 :          else if (symbol_used(name))
   41816           0 :             return false;
   41817         727 :          else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
   41818           0 :             return false;
   41819             :          else
   41820         727 :             return true;
   41821             :       }
   41822             : 
   41823         727 :       inline bool forward(const std::string& name,
   41824             :                           const std::size_t& arg_count,
   41825             :                           symbol_table_t& sym_table,
   41826             :                           const bool ret_present = false)
   41827             :       {
   41828         727 :          switch (arg_count)
   41829             :          {
   41830             :             #define case_stmt(N)                                     \
   41831             :             case N : (fp_map_[arg_count])[name] =                    \
   41832             :                      (!ret_present) ? static_cast<base_func*>        \
   41833             :                                       (new func_##N##param) :        \
   41834             :                                       static_cast<base_func*>        \
   41835             :                                       (new func_##N##param_retval) ; \
   41836             :                      break;                                          \
   41837             : 
   41838         324 :             case_stmt(0) case_stmt(1) case_stmt(2)
   41839         303 :             case_stmt(3) case_stmt(4) case_stmt(5)
   41840         100 :             case_stmt(6)
   41841             :             #undef case_stmt
   41842             :          }
   41843             : 
   41844         727 :          exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
   41845             : 
   41846         727 :          return sym_table.add_function(name,ifunc);
   41847             :       }
   41848             : 
   41849           0 :       inline void remove(const std::string& name, const std::size_t& arg_count)
   41850             :       {
   41851           0 :          if (arg_count > 6)
   41852           0 :             return;
   41853             : 
   41854           0 :          const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
   41855             : 
   41856           0 :          if (expr_map_.end() != em_itr)
   41857             :          {
   41858           0 :             expr_map_.erase(em_itr);
   41859             :          }
   41860             : 
   41861           0 :          const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
   41862             : 
   41863           0 :          if (fp_map_[arg_count].end() != fp_itr)
   41864             :          {
   41865           0 :             delete fp_itr->second;
   41866           0 :             fp_map_[arg_count].erase(fp_itr);
   41867             :          }
   41868             : 
   41869           0 :          symbol_table_.remove_function(name);
   41870             :       }
   41871             : 
   41872             :    private:
   41873             : 
   41874             :       symbol_table_t symbol_table_;
   41875             :       parser_t parser_;
   41876             :       std::map<std::string,expression_t> expr_map_;
   41877             :       std::vector<funcparam_t> fp_map_;
   41878             :       std::vector<symbol_table_t*> auxiliary_symtab_list_;
   41879             :       std::deque<parser_error::type> error_list_;
   41880             :       bool load_variables_;
   41881             :       bool load_vectors_;
   41882             :    }; // class function_compositor
   41883             : 
   41884             : } // namespace exprtk
   41885             : 
   41886             : #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
   41887             : #   ifndef NOMINMAX
   41888             : #      define NOMINMAX
   41889             : #   endif
   41890             : #   ifndef WIN32_LEAN_AND_MEAN
   41891             : #      define WIN32_LEAN_AND_MEAN
   41892             : #   endif
   41893             : #   include <windows.h>
   41894             : #   include <ctime>
   41895             : #else
   41896             : #   include <ctime>
   41897             : #   include <sys/time.h>
   41898             : #   include <sys/types.h>
   41899             : #endif
   41900             : 
   41901             : namespace exprtk
   41902             : {
   41903             :    class timer
   41904             :    {
   41905             :    public:
   41906             : 
   41907             :       #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
   41908             :       timer()
   41909             :       : in_use_(false)
   41910             :       , start_time_{ 0 }
   41911             :       , stop_time_ { 0 }
   41912             :       {
   41913             :          QueryPerformanceFrequency(&clock_frequency_);
   41914             :       }
   41915             : 
   41916             :       inline void start()
   41917             :       {
   41918             :          in_use_ = true;
   41919             :          QueryPerformanceCounter(&start_time_);
   41920             :       }
   41921             : 
   41922             :       inline void stop()
   41923             :       {
   41924             :          QueryPerformanceCounter(&stop_time_);
   41925             :          in_use_ = false;
   41926             :       }
   41927             : 
   41928             :       inline double time() const
   41929             :       {
   41930             :          return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
   41931             :       }
   41932             : 
   41933             :       #else
   41934             : 
   41935          22 :       timer()
   41936          22 :       : in_use_(false)
   41937             :       {
   41938          22 :          start_time_.tv_sec  = 0;
   41939          22 :          start_time_.tv_usec = 0;
   41940             : 
   41941          22 :          stop_time_.tv_sec   = 0;
   41942          22 :          stop_time_.tv_usec  = 0;
   41943          22 :       }
   41944             : 
   41945          22 :       inline void start()
   41946             :       {
   41947          22 :          in_use_ = true;
   41948          22 :          gettimeofday(&start_time_,0);
   41949          22 :       }
   41950             : 
   41951          22 :       inline void stop()
   41952             :       {
   41953          22 :          gettimeofday(&stop_time_, 0);
   41954          22 :          in_use_ = false;
   41955          22 :       }
   41956             : 
   41957          22 :       inline unsigned long long int usec_time() const
   41958             :       {
   41959          22 :          if (!in_use_)
   41960             :          {
   41961          22 :             if (stop_time_.tv_sec >= start_time_.tv_sec)
   41962             :             {
   41963          22 :                return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec  - start_time_.tv_sec ) +
   41964          22 :                                    static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
   41965             :             }
   41966             :             else
   41967           0 :                return std::numeric_limits<details::_uint64_t>::max();
   41968             :          }
   41969             :          else
   41970           0 :             return std::numeric_limits<details::_uint64_t>::max();
   41971             :       }
   41972             : 
   41973          22 :       inline double time() const
   41974             :       {
   41975          22 :          return usec_time() * 0.000001;
   41976             :       }
   41977             : 
   41978             :       #endif
   41979             : 
   41980             :       inline bool in_use() const
   41981             :       {
   41982             :          return in_use_;
   41983             :       }
   41984             : 
   41985             :    private:
   41986             : 
   41987             :       bool in_use_;
   41988             : 
   41989             :       #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
   41990             :          LARGE_INTEGER start_time_;
   41991             :          LARGE_INTEGER stop_time_;
   41992             :          LARGE_INTEGER clock_frequency_;
   41993             :       #else
   41994             :          struct timeval start_time_;
   41995             :          struct timeval stop_time_;
   41996             :       #endif
   41997             :    };
   41998             : 
   41999             :    template <typename T>
   42000             :    struct type_defs
   42001             :    {
   42002             :       typedef symbol_table<T>         symbol_table_t;
   42003             :       typedef expression<T>           expression_t;
   42004             :       typedef parser<T>               parser_t;
   42005             :       typedef parser_error::type      error_t;
   42006             :       typedef function_compositor<T>  compositor_t;
   42007             :       typedef typename compositor_t::function function_t;
   42008             :    };
   42009             : 
   42010             : } // namespace exprtk
   42011             : 
   42012             : #ifndef exprtk_disable_rtl_io
   42013             : namespace exprtk
   42014             : {
   42015             :    namespace rtl { namespace io { namespace details
   42016             :    {
   42017             :       template <typename T>
   42018           0 :       inline void print_type(const std::string& fmt,
   42019             :                              const T v,
   42020             :                              exprtk::details::numeric::details::real_type_tag)
   42021             :       {
   42022             :          #if defined(__clang__)
   42023             :             #pragma clang diagnostic push
   42024             :             #pragma clang diagnostic ignored "-Wformat-nonliteral"
   42025             :          #elif defined(__GNUC__) || defined(__GNUG__)
   42026             :             #pragma GCC diagnostic push
   42027             :             #pragma GCC diagnostic ignored "-Wformat-nonliteral"
   42028             :          #elif defined(_MSC_VER)
   42029             :          #endif
   42030             : 
   42031           0 :          printf(fmt.c_str(), v);
   42032             : 
   42033             :          #if defined(__clang__)
   42034             :             #pragma clang diagnostic pop
   42035             :          #elif defined(__GNUC__) || defined(__GNUG__)
   42036             :             #pragma GCC diagnostic pop
   42037             :          #elif defined(_MSC_VER)
   42038             :          #endif
   42039           0 :       }
   42040             : 
   42041             :       template <typename T>
   42042             :       struct print_impl
   42043             :       {
   42044             :          typedef typename igeneric_function<T>::generic_type generic_type;
   42045             :          typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
   42046             :          typedef typename generic_type::scalar_view scalar_t;
   42047             :          typedef typename generic_type::vector_view vector_t;
   42048             :          typedef typename generic_type::string_view string_t;
   42049             :          typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
   42050             : 
   42051           0 :          static void process(const std::string& scalar_format, parameter_list_t parameters)
   42052             :          {
   42053           0 :             for (std::size_t i = 0; i < parameters.size(); ++i)
   42054             :             {
   42055           0 :                generic_type& gt = parameters[i];
   42056             : 
   42057           0 :                switch (gt.type)
   42058             :                {
   42059           0 :                   case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
   42060           0 :                                                 break;
   42061             : 
   42062           0 :                   case generic_type::e_vector : print(scalar_format,vector_t(gt));
   42063           0 :                                                 break;
   42064             : 
   42065           0 :                   case generic_type::e_string : print(string_t(gt));
   42066           0 :                                                 break;
   42067             : 
   42068           0 :                   default                     : continue;
   42069             :                }
   42070             :             }
   42071           0 :          }
   42072             : 
   42073           0 :          static inline void print(const std::string& scalar_format, const scalar_t& s)
   42074             :          {
   42075           0 :             print_type(scalar_format,s(),num_type());
   42076           0 :          }
   42077             : 
   42078           0 :          static inline void print(const std::string& scalar_format, const vector_t& v)
   42079             :          {
   42080           0 :             for (std::size_t i = 0; i < v.size(); ++i)
   42081             :             {
   42082           0 :                print_type(scalar_format,v[i],num_type());
   42083             : 
   42084           0 :                if ((i + 1) < v.size())
   42085           0 :                   printf(" ");
   42086             :             }
   42087           0 :          }
   42088             : 
   42089           0 :          static inline void print(const string_t& s)
   42090             :          {
   42091           0 :             printf("%s",to_str(s).c_str());
   42092           0 :          }
   42093             :       };
   42094             : 
   42095             :    } // namespace exprtk::rtl::io::details
   42096             : 
   42097             :    template <typename T>
   42098             :    struct print exprtk_final : public exprtk::igeneric_function<T>
   42099             :    {
   42100             :       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
   42101             : 
   42102             :       using exprtk::igeneric_function<T>::operator();
   42103             : 
   42104          30 :       explicit print(const std::string& scalar_format = "%10.5f")
   42105          90 :       : scalar_format_(scalar_format)
   42106             :       {
   42107          30 :          exprtk::enable_zero_parameters(*this);
   42108          30 :       }
   42109             : 
   42110           0 :       inline T operator() (parameter_list_t parameters) exprtk_override
   42111             :       {
   42112           0 :          details::print_impl<T>::process(scalar_format_,parameters);
   42113           0 :          return T(0);
   42114             :       }
   42115             : 
   42116             :       std::string scalar_format_;
   42117             :    };
   42118             : 
   42119             :    template <typename T>
   42120             :    struct println exprtk_final : public exprtk::igeneric_function<T>
   42121             :    {
   42122             :       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
   42123             : 
   42124             :       using exprtk::igeneric_function<T>::operator();
   42125             : 
   42126          30 :       explicit println(const std::string& scalar_format = "%10.5f")
   42127          90 :       : scalar_format_(scalar_format)
   42128             :       {
   42129          30 :          exprtk::enable_zero_parameters(*this);
   42130          30 :       }
   42131             : 
   42132           0 :       inline T operator() (parameter_list_t parameters) exprtk_override
   42133             :       {
   42134           0 :          details::print_impl<T>::process(scalar_format_,parameters);
   42135           0 :          printf("\n");
   42136           0 :          return T(0);
   42137             :       }
   42138             : 
   42139             :       std::string scalar_format_;
   42140             :    };
   42141             : 
   42142             :    template <typename T>
   42143             :    struct package
   42144             :    {
   42145             :       print  <T> p;
   42146             :       println<T> pl;
   42147             : 
   42148          30 :       bool register_package(exprtk::symbol_table<T>& symtab)
   42149             :       {
   42150             :          #define exprtk_register_function(FunctionName, FunctionType)             \
   42151             :          if (!symtab.add_function(FunctionName,FunctionType))                     \
   42152             :          {                                                                        \
   42153             :             exprtk_debug((                                                        \
   42154             :               "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
   42155             :               FunctionName));                                                     \
   42156             :             return false;                                                         \
   42157             :          }                                                                        \
   42158             : 
   42159          90 :          exprtk_register_function("print"  , p )
   42160          90 :          exprtk_register_function("println", pl)
   42161             :          #undef exprtk_register_function
   42162             : 
   42163          30 :          return true;
   42164             :       }
   42165             :    };
   42166             : 
   42167             :    } // namespace exprtk::rtl::io
   42168             :    } // namespace exprtk::rtl
   42169             : }    // namespace exprtk
   42170             : #endif
   42171             : 
   42172             : #ifndef exprtk_disable_rtl_io_file
   42173             : #include <fstream>
   42174             : namespace exprtk
   42175             : {
   42176             :    namespace rtl { namespace io { namespace file { namespace details
   42177             :    {
   42178             :       using ::exprtk::details::char_ptr;
   42179             :       using ::exprtk::details::char_cptr;
   42180             : 
   42181             :       enum file_mode
   42182             :       {
   42183             :          e_error = 0,
   42184             :          e_read  = 1,
   42185             :          e_write = 2,
   42186             :          e_rdwrt = 4
   42187             :       };
   42188             : 
   42189             :       struct file_descriptor
   42190             :       {
   42191             :          file_descriptor(const std::string& fname, const std::string& access)
   42192             :          : stream_ptr(0)
   42193             :          , mode(get_file_mode(access))
   42194             :          , file_name(fname)
   42195             :          {}
   42196             : 
   42197             :          void*       stream_ptr;
   42198             :          file_mode   mode;
   42199             :          std::string file_name;
   42200             : 
   42201             :          bool open()
   42202             :          {
   42203             :             if (e_read == mode)
   42204             :             {
   42205             :                std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
   42206             : 
   42207             :                if (!(*stream))
   42208             :                {
   42209             :                   file_name.clear();
   42210             :                   delete stream;
   42211             : 
   42212             :                   return false;
   42213             :                }
   42214             : 
   42215             :                stream_ptr = stream;
   42216             : 
   42217             :                return true;
   42218             :             }
   42219             :             else if (e_write == mode)
   42220             :             {
   42221             :                std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
   42222             : 
   42223             :                if (!(*stream))
   42224             :                {
   42225             :                   file_name.clear();
   42226             :                   delete stream;
   42227             : 
   42228             :                   return false;
   42229             :                }
   42230             : 
   42231             :                stream_ptr = stream;
   42232             : 
   42233             :                return true;
   42234             :             }
   42235             :             else if (e_rdwrt == mode)
   42236             :             {
   42237             :                std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
   42238             : 
   42239             :                if (!(*stream))
   42240             :                {
   42241             :                   file_name.clear();
   42242             :                   delete stream;
   42243             : 
   42244             :                   return false;
   42245             :                }
   42246             : 
   42247             :                stream_ptr = stream;
   42248             : 
   42249             :                return true;
   42250             :             }
   42251             : 
   42252             :             return false;
   42253             :          }
   42254             : 
   42255             :          template <typename Stream, typename Ptr>
   42256             :          void close(Ptr& p)
   42257             :          {
   42258             :             Stream* stream = reinterpret_cast<Stream*>(p);
   42259             :             stream->close();
   42260             :             delete stream;
   42261             :             p = reinterpret_cast<Ptr>(0);
   42262             :          }
   42263             : 
   42264             :          bool close()
   42265             :          {
   42266             :             switch (mode)
   42267             :             {
   42268             :                case e_read  : close<std::ifstream>(stream_ptr);
   42269             :                               break;
   42270             : 
   42271             :                case e_write : close<std::ofstream>(stream_ptr);
   42272             :                               break;
   42273             : 
   42274             :                case e_rdwrt : close<std::fstream> (stream_ptr);
   42275             :                               break;
   42276             : 
   42277             :                default      : return false;
   42278             :             }
   42279             : 
   42280             :             return true;
   42281             :          }
   42282             : 
   42283             :          template <typename View>
   42284             :          bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
   42285             :          {
   42286             :             switch (mode)
   42287             :             {
   42288             :                case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
   42289             :                                  write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
   42290             :                               break;
   42291             : 
   42292             :                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
   42293             :                                  write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
   42294             :                               break;
   42295             : 
   42296             :                default      : return false;
   42297             :             }
   42298             : 
   42299             :             return true;
   42300             :          }
   42301             : 
   42302             :          template <typename View>
   42303             :          bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
   42304             :          {
   42305             :             switch (mode)
   42306             :             {
   42307             :                case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
   42308             :                                  read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
   42309             :                               break;
   42310             : 
   42311             :                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
   42312             :                                  read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
   42313             :                               break;
   42314             : 
   42315             :                default      : return false;
   42316             :             }
   42317             : 
   42318             :             return true;
   42319             :          }
   42320             : 
   42321             :          bool getline(std::string& s)
   42322             :          {
   42323             :             switch (mode)
   42324             :             {
   42325             :                case e_read  : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
   42326             :                case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
   42327             :                default      : return false;
   42328             :             }
   42329             :          }
   42330             : 
   42331             :          bool eof() const
   42332             :          {
   42333             :             switch (mode)
   42334             :             {
   42335             :                case e_read  : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
   42336             :                case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
   42337             :                case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
   42338             :                default      : return true;
   42339             :             }
   42340             :          }
   42341             : 
   42342             :          file_mode get_file_mode(const std::string& access) const
   42343             :          {
   42344             :             if (access.empty() || access.size() > 2)
   42345             :                return e_error;
   42346             : 
   42347             :             std::size_t w_cnt = 0;
   42348             :             std::size_t r_cnt = 0;
   42349             : 
   42350             :             for (std::size_t i = 0; i < access.size(); ++i)
   42351             :             {
   42352             :                switch (std::tolower(access[i]))
   42353             :                {
   42354             :                   case 'r' : r_cnt++; break;
   42355             :                   case 'w' : w_cnt++; break;
   42356             :                   default  : return e_error;
   42357             :                }
   42358             :             }
   42359             : 
   42360             :             if ((0 == r_cnt) && (0 == w_cnt))
   42361             :                return e_error;
   42362             :             else if ((r_cnt > 1) || (w_cnt > 1))
   42363             :                return e_error;
   42364             :             else if ((1 == r_cnt) && (1 == w_cnt))
   42365             :                return e_rdwrt;
   42366             :             else if (1 == r_cnt)
   42367             :                return e_read;
   42368             :             else
   42369             :                return e_write;
   42370             :          }
   42371             :       };
   42372             : 
   42373             :       template <typename T>
   42374             :       file_descriptor* make_handle(T v)
   42375             :       {
   42376             :          const std::size_t fd_size    = sizeof(details::file_descriptor*);
   42377             :          details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
   42378             : 
   42379             :          std::memcpy(reinterpret_cast<char_ptr >(&fd),
   42380             :                      reinterpret_cast<char_cptr>(&v ),
   42381             :                      fd_size);
   42382             :          return fd;
   42383             :       }
   42384             : 
   42385             :       template <typename T>
   42386             :       void perform_check()
   42387             :       {
   42388             :          #ifdef _MSC_VER
   42389             :          #pragma warning(push)
   42390             :          #pragma warning(disable: 4127)
   42391             :          #endif
   42392             :          if (sizeof(T) < sizeof(void*))
   42393             :          {
   42394             :             throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
   42395             :          }
   42396             :          #ifdef _MSC_VER
   42397             :          #pragma warning(pop)
   42398             :          #endif
   42399             :          assert(sizeof(T) <= sizeof(void*));
   42400             :       }
   42401             : 
   42402             :    } // namespace exprtk::rtl::io::file::details
   42403             : 
   42404             :    template <typename T>
   42405             :    class open exprtk_final : public exprtk::igeneric_function<T>
   42406             :    {
   42407             :    public:
   42408             : 
   42409             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42410             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42411             :       typedef typename igfun_t::generic_type        generic_type;
   42412             :       typedef typename generic_type::string_view    string_t;
   42413             : 
   42414             :       using igfun_t::operator();
   42415             : 
   42416             :       open()
   42417             :       : exprtk::igeneric_function<T>("S|SS")
   42418             :       { details::perform_check<T>(); }
   42419             : 
   42420             :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42421             :       {
   42422             :          const std::string file_name = to_str(string_t(parameters[0]));
   42423             : 
   42424             :          if (file_name.empty())
   42425             :             return T(0);
   42426             : 
   42427             :          if ((1 == ps_index) && (0 == string_t(parameters[1]).size()))
   42428             :          {
   42429             :             return T(0);
   42430             :          }
   42431             : 
   42432             :          const std::string access =
   42433             :             (0 == ps_index) ? "r" : to_str(string_t(parameters[1]));
   42434             : 
   42435             :          details::file_descriptor* fd = new details::file_descriptor(file_name,access);
   42436             : 
   42437             :          if (fd->open())
   42438             :          {
   42439             :             T t = T(0);
   42440             : 
   42441             :             const std::size_t fd_size = sizeof(details::file_descriptor*);
   42442             : 
   42443             :             std::memcpy(reinterpret_cast<char*>(&t ),
   42444             :                         reinterpret_cast<char*>(&fd),
   42445             :                         fd_size);
   42446             :             return t;
   42447             :          }
   42448             :          else
   42449             :          {
   42450             :             delete fd;
   42451             :             return T(0);
   42452             :          }
   42453             :       }
   42454             :    };
   42455             : 
   42456             :    template <typename T>
   42457             :    struct close exprtk_final : public exprtk::ifunction<T>
   42458             :    {
   42459             :       using exprtk::ifunction<T>::operator();
   42460             : 
   42461             :       close()
   42462             :       : exprtk::ifunction<T>(1)
   42463             :       { details::perform_check<T>(); }
   42464             : 
   42465             :       inline T operator() (const T& v) exprtk_override
   42466             :       {
   42467             :          details::file_descriptor* fd = details::make_handle(v);
   42468             : 
   42469             :          if (!fd->close())
   42470             :             return T(0);
   42471             : 
   42472             :          delete fd;
   42473             : 
   42474             :          return T(1);
   42475             :       }
   42476             :    };
   42477             : 
   42478             :    template <typename T>
   42479             :    class write exprtk_final : public exprtk::igeneric_function<T>
   42480             :    {
   42481             :    public:
   42482             : 
   42483             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42484             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42485             :       typedef typename igfun_t::generic_type        generic_type;
   42486             :       typedef typename generic_type::string_view    string_t;
   42487             :       typedef typename generic_type::scalar_view    scalar_t;
   42488             :       typedef typename generic_type::vector_view    vector_t;
   42489             : 
   42490             :       using igfun_t::operator();
   42491             : 
   42492             :       write()
   42493             :       : igfun_t("TS|TST|TV|TVT")
   42494             :       { details::perform_check<T>(); }
   42495             : 
   42496             :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42497             :       {
   42498             :          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
   42499             : 
   42500             :          switch (ps_index)
   42501             :          {
   42502             :             case 0  : {
   42503             :                          const string_t buffer(parameters[1]);
   42504             :                          const std::size_t amount = buffer.size();
   42505             :                          return T(fd->write(buffer, amount) ? 1 : 0);
   42506             :                       }
   42507             : 
   42508             :             case 1  : {
   42509             :                          const string_t buffer(parameters[1]);
   42510             :                          const std::size_t amount =
   42511             :                                   std::min(buffer.size(),
   42512             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   42513             :                          return T(fd->write(buffer, amount) ? 1 : 0);
   42514             :                       }
   42515             : 
   42516             :             case 2  : {
   42517             :                          const vector_t vec(parameters[1]);
   42518             :                          const std::size_t amount = vec.size();
   42519             :                          return T(fd->write(vec, amount) ? 1 : 0);
   42520             :                       }
   42521             : 
   42522             :             case 3  : {
   42523             :                          const vector_t vec(parameters[1]);
   42524             :                          const std::size_t amount =
   42525             :                                   std::min(vec.size(),
   42526             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   42527             :                          return T(fd->write(vec, amount) ? 1 : 0);
   42528             :                       }
   42529             :          }
   42530             : 
   42531             :          return T(0);
   42532             :       }
   42533             :    };
   42534             : 
   42535             :    template <typename T>
   42536             :    class read exprtk_final : public exprtk::igeneric_function<T>
   42537             :    {
   42538             :    public:
   42539             : 
   42540             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42541             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42542             :       typedef typename igfun_t::generic_type        generic_type;
   42543             :       typedef typename generic_type::string_view    string_t;
   42544             :       typedef typename generic_type::scalar_view    scalar_t;
   42545             :       typedef typename generic_type::vector_view    vector_t;
   42546             : 
   42547             :       using igfun_t::operator();
   42548             : 
   42549             :       read()
   42550             :       : igfun_t("TS|TST|TV|TVT")
   42551             :       { details::perform_check<T>(); }
   42552             : 
   42553             :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42554             :       {
   42555             :          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
   42556             : 
   42557             :          switch (ps_index)
   42558             :          {
   42559             :             case 0  : {
   42560             :                          string_t buffer(parameters[1]);
   42561             :                          const std::size_t amount = buffer.size();
   42562             :                          return T(fd->read(buffer,amount) ? 1 : 0);
   42563             :                       }
   42564             : 
   42565             :             case 1  : {
   42566             :                          string_t buffer(parameters[1]);
   42567             :                          const std::size_t amount =
   42568             :                                   std::min(buffer.size(),
   42569             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   42570             :                          return T(fd->read(buffer,amount) ? 1 : 0);
   42571             :                       }
   42572             : 
   42573             :             case 2  : {
   42574             :                          vector_t vec(parameters[1]);
   42575             :                          const std::size_t amount = vec.size();
   42576             :                          return T(fd->read(vec,amount) ? 1 : 0);
   42577             :                       }
   42578             : 
   42579             :             case 3  : {
   42580             :                          vector_t vec(parameters[1]);
   42581             :                          const std::size_t amount =
   42582             :                                   std::min(vec.size(),
   42583             :                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
   42584             :                          return T(fd->read(vec,amount) ? 1 : 0);
   42585             :                       }
   42586             :          }
   42587             : 
   42588             :          return T(0);
   42589             :       }
   42590             :    };
   42591             : 
   42592             :    template <typename T>
   42593             :    class getline exprtk_final : public exprtk::igeneric_function<T>
   42594             :    {
   42595             :    public:
   42596             : 
   42597             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42598             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42599             :       typedef typename igfun_t::generic_type        generic_type;
   42600             :       typedef typename generic_type::string_view    string_t;
   42601             :       typedef typename generic_type::scalar_view    scalar_t;
   42602             : 
   42603             :       using igfun_t::operator();
   42604             : 
   42605             :       getline()
   42606             :       : igfun_t("T",igfun_t::e_rtrn_string)
   42607             :       { details::perform_check<T>(); }
   42608             : 
   42609             :       inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override
   42610             :       {
   42611             :          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
   42612             :          return T(fd->getline(result) ? 1 : 0);
   42613             :       }
   42614             :    };
   42615             : 
   42616             :    template <typename T>
   42617             :    struct eof exprtk_final : public exprtk::ifunction<T>
   42618             :    {
   42619             :       using exprtk::ifunction<T>::operator();
   42620             : 
   42621             :       eof()
   42622             :       : exprtk::ifunction<T>(1)
   42623             :       { details::perform_check<T>(); }
   42624             : 
   42625             :       inline T operator() (const T& v) exprtk_override
   42626             :       {
   42627             :          details::file_descriptor* fd = details::make_handle(v);
   42628             : 
   42629             :          return (fd->eof() ? T(1) : T(0));
   42630             :       }
   42631             :    };
   42632             : 
   42633             :    template <typename T>
   42634             :    struct package
   42635             :    {
   42636             :       open   <T> o;
   42637             :       close  <T> c;
   42638             :       write  <T> w;
   42639             :       read   <T> r;
   42640             :       getline<T> g;
   42641             :       eof    <T> e;
   42642             : 
   42643             :       bool register_package(exprtk::symbol_table<T>& symtab)
   42644             :       {
   42645             :          #define exprtk_register_function(FunctionName, FunctionType)                   \
   42646             :          if (!symtab.add_function(FunctionName,FunctionType))                           \
   42647             :          {                                                                              \
   42648             :             exprtk_debug((                                                              \
   42649             :               "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
   42650             :               FunctionName));                                                           \
   42651             :             return false;                                                               \
   42652             :          }                                                                              \
   42653             : 
   42654             :          exprtk_register_function("open"    , o)
   42655             :          exprtk_register_function("close"   , c)
   42656             :          exprtk_register_function("write"   , w)
   42657             :          exprtk_register_function("read"    , r)
   42658             :          exprtk_register_function("getline" , g)
   42659             :          exprtk_register_function("eof"     , e)
   42660             :          #undef exprtk_register_function
   42661             : 
   42662             :          return true;
   42663             :       }
   42664             :    };
   42665             : 
   42666             :    } // namespace exprtk::rtl::io::file
   42667             :    } // namespace exprtk::rtl::io
   42668             :    } // namespace exprtk::rtl
   42669             : }    // namespace exprtk
   42670             : #endif
   42671             : 
   42672             : #ifndef exprtk_disable_rtl_vecops
   42673             : namespace exprtk
   42674             : {
   42675             :    namespace rtl { namespace vecops {
   42676             : 
   42677             :    namespace helper
   42678             :    {
   42679             :       template <typename Vector>
   42680        2383 :       inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
   42681             :       {
   42682        2383 :          if (r0 > (v.size() - 1))
   42683           0 :             return true;
   42684        2383 :          else if (r1 > (v.size() - 1))
   42685           0 :             return true;
   42686        2383 :          else if (r1 < r0)
   42687           0 :             return true;
   42688             :          else
   42689        2383 :             return false;
   42690             :       }
   42691             : 
   42692             :       template <typename T>
   42693             :       struct load_vector_range
   42694             :       {
   42695             :          typedef typename exprtk::igeneric_function<T> igfun_t;
   42696             :          typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42697             :          typedef typename igfun_t::generic_type        generic_type;
   42698             :          typedef typename generic_type::scalar_view    scalar_t;
   42699             :          typedef typename generic_type::vector_view    vector_t;
   42700             : 
   42701         396 :          static inline bool process(parameter_list_t& parameters,
   42702             :                                     std::size_t& r0, std::size_t& r1,
   42703             :                                     const std::size_t& r0_prmidx,
   42704             :                                     const std::size_t& r1_prmidx,
   42705             :                                     const std::size_t vec_idx = 0)
   42706             :          {
   42707         396 :             if (r0_prmidx >= parameters.size())
   42708           0 :                return false;
   42709             : 
   42710         396 :             if (r1_prmidx >= parameters.size())
   42711           0 :                return false;
   42712             : 
   42713         396 :             if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
   42714           0 :                return false;
   42715             : 
   42716         396 :             if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
   42717           0 :                return false;
   42718             : 
   42719         396 :             return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
   42720             :          }
   42721             :       };
   42722             :    }
   42723             : 
   42724             :    namespace details
   42725             :    {
   42726             :       template <typename T>
   42727         160 :       inline void kahan_sum(T& sum, T& error, const T v)
   42728             :       {
   42729         160 :          const T x = v - error;
   42730         160 :          const T y = sum + x;
   42731         160 :          error = (y - sum) - x;
   42732         160 :          sum = y;
   42733         160 :       }
   42734             : 
   42735             :    } // namespace exprtk::rtl::details
   42736             : 
   42737             :    template <typename T>
   42738             :    class all_true exprtk_final : public exprtk::igeneric_function<T>
   42739             :    {
   42740             :    public:
   42741             : 
   42742             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42743             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42744             :       typedef typename igfun_t::generic_type        generic_type;
   42745             :       typedef typename generic_type::vector_view    vector_t;
   42746             : 
   42747             :       using igfun_t::operator();
   42748             : 
   42749          32 :       all_true()
   42750          64 :       : exprtk::igeneric_function<T>("V|VTT")
   42751             :         /*
   42752             :            Overloads:
   42753             :            0. V   - vector
   42754             :            1. VTT - vector, r0, r1
   42755             :         */
   42756          32 :       {}
   42757             : 
   42758         755 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42759             :       {
   42760         755 :          const vector_t vec(parameters[0]);
   42761             : 
   42762         755 :          std::size_t r0 = 0;
   42763         755 :          std::size_t r1 = vec.size() - 1;
   42764             : 
   42765         755 :          if (
   42766         755 :               (1 == ps_index) &&
   42767         755 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   42768             :             )
   42769             :          {
   42770           0 :             return std::numeric_limits<T>::quiet_NaN();
   42771             :          }
   42772             : 
   42773        5495 :          for (std::size_t i = r0; i <= r1; ++i)
   42774             :          {
   42775        4742 :             if (vec[i] == T(0))
   42776             :             {
   42777           2 :                return T(0);
   42778             :             }
   42779             :          }
   42780             : 
   42781         753 :          return T(1);
   42782             :       }
   42783             :    };
   42784             : 
   42785             :    template <typename T>
   42786             :    class all_false exprtk_final : public exprtk::igeneric_function<T>
   42787             :    {
   42788             :    public:
   42789             : 
   42790             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42791             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42792             :       typedef typename igfun_t::generic_type        generic_type;
   42793             :       typedef typename generic_type::vector_view    vector_t;
   42794             : 
   42795             :       using igfun_t::operator();
   42796             : 
   42797          32 :       all_false()
   42798          64 :       : exprtk::igeneric_function<T>("V|VTT")
   42799             :         /*
   42800             :            Overloads:
   42801             :            0. V   - vector
   42802             :            1. VTT - vector, r0, r1
   42803             :         */
   42804          32 :       {}
   42805             : 
   42806         123 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42807             :       {
   42808         123 :          const vector_t vec(parameters[0]);
   42809             : 
   42810         123 :          std::size_t r0 = 0;
   42811         123 :          std::size_t r1 = vec.size() - 1;
   42812             : 
   42813         123 :          if (
   42814         123 :               (1 == ps_index) &&
   42815         123 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   42816             :             )
   42817             :          {
   42818           0 :             return std::numeric_limits<T>::quiet_NaN();
   42819             :          }
   42820             : 
   42821         772 :          for (std::size_t i = r0; i <= r1; ++i)
   42822             :          {
   42823         651 :             if (vec[i] != T(0))
   42824             :             {
   42825           2 :                return T(0);
   42826             :             }
   42827             :          }
   42828             : 
   42829         121 :          return T(1);
   42830             :       }
   42831             :    };
   42832             : 
   42833             :    template <typename T>
   42834             :    class any_true exprtk_final : public exprtk::igeneric_function<T>
   42835             :    {
   42836             :    public:
   42837             : 
   42838             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42839             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42840             :       typedef typename igfun_t::generic_type        generic_type;
   42841             :       typedef typename generic_type::vector_view    vector_t;
   42842             : 
   42843             :       using igfun_t::operator();
   42844             : 
   42845          32 :       any_true()
   42846          64 :       : exprtk::igeneric_function<T>("V|VTT")
   42847             :         /*
   42848             :            Overloads:
   42849             :            0. V   - vector
   42850             :            1. VTT - vector, r0, r1
   42851             :         */
   42852          32 :       {}
   42853             : 
   42854           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42855             :       {
   42856           4 :          const vector_t vec(parameters[0]);
   42857             : 
   42858           4 :          std::size_t r0 = 0;
   42859           4 :          std::size_t r1 = vec.size() - 1;
   42860             : 
   42861           4 :          if (
   42862           4 :               (1 == ps_index) &&
   42863           4 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   42864             :             )
   42865             :          {
   42866           0 :             return std::numeric_limits<T>::quiet_NaN();
   42867             :          }
   42868             : 
   42869          25 :          for (std::size_t i = r0; i <= r1; ++i)
   42870             :          {
   42871          24 :             if (vec[i] != T(0))
   42872             :             {
   42873           3 :                return T(1);
   42874             :             }
   42875             :          }
   42876             : 
   42877           1 :          return T(0);
   42878             :       }
   42879             :    };
   42880             : 
   42881             :    template <typename T>
   42882             :    class any_false exprtk_final : public exprtk::igeneric_function<T>
   42883             :    {
   42884             :    public:
   42885             : 
   42886             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42887             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42888             :       typedef typename igfun_t::generic_type        generic_type;
   42889             :       typedef typename generic_type::vector_view    vector_t;
   42890             : 
   42891             :       using igfun_t::operator();
   42892             : 
   42893          32 :       any_false()
   42894          64 :       : exprtk::igeneric_function<T>("V|VTT")
   42895             :         /*
   42896             :            Overloads:
   42897             :            0. V   - vector
   42898             :            1. VTT - vector, r0, r1
   42899             :         */
   42900          32 :       {}
   42901             : 
   42902           5 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42903             :       {
   42904           5 :          const vector_t vec(parameters[0]);
   42905             : 
   42906           5 :          std::size_t r0 = 0;
   42907           5 :          std::size_t r1 = vec.size() - 1;
   42908             : 
   42909           5 :          if (
   42910           5 :               (1 == ps_index) &&
   42911           5 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   42912             :             )
   42913             :          {
   42914           0 :             return std::numeric_limits<T>::quiet_NaN();
   42915             :          }
   42916             : 
   42917          26 :          for (std::size_t i = r0; i <= r1; ++i)
   42918             :          {
   42919          25 :             if (vec[i] == T(0))
   42920             :             {
   42921           4 :                return T(1);
   42922             :             }
   42923             :          }
   42924             : 
   42925           1 :          return T(0);
   42926             :       }
   42927             :    };
   42928             : 
   42929             :    template <typename T>
   42930             :    class count exprtk_final : public exprtk::igeneric_function<T>
   42931             :    {
   42932             :    public:
   42933             : 
   42934             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42935             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42936             :       typedef typename igfun_t::generic_type        generic_type;
   42937             :       typedef typename generic_type::vector_view    vector_t;
   42938             : 
   42939             :       using igfun_t::operator();
   42940             : 
   42941          32 :       count()
   42942          64 :       : exprtk::igeneric_function<T>("V|VTT")
   42943             :         /*
   42944             :            Overloads:
   42945             :            0. V   - vector
   42946             :            1. VTT - vector, r0, r1
   42947             :         */
   42948          32 :       {}
   42949             : 
   42950           6 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42951             :       {
   42952           6 :          const vector_t vec(parameters[0]);
   42953             : 
   42954           6 :          std::size_t r0 = 0;
   42955           6 :          std::size_t r1 = vec.size() - 1;
   42956             : 
   42957           6 :          if (
   42958           6 :               (1 == ps_index) &&
   42959           6 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   42960             :             )
   42961             :          {
   42962           0 :             return std::numeric_limits<T>::quiet_NaN();
   42963             :          }
   42964             : 
   42965           6 :          std::size_t cnt = 0;
   42966             : 
   42967          60 :          for (std::size_t i = r0; i <= r1; ++i)
   42968             :          {
   42969          54 :             if (vec[i] != T(0)) ++cnt;
   42970             :          }
   42971             : 
   42972           6 :          return T(cnt);
   42973             :       }
   42974             :    };
   42975             : 
   42976             :    template <typename T>
   42977             :    class copy exprtk_final : public exprtk::igeneric_function<T>
   42978             :    {
   42979             :    public:
   42980             : 
   42981             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   42982             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   42983             :       typedef typename igfun_t::generic_type        generic_type;
   42984             :       typedef typename generic_type::scalar_view    scalar_t;
   42985             :       typedef typename generic_type::vector_view    vector_t;
   42986             : 
   42987             :       using igfun_t::operator();
   42988             : 
   42989          32 :       copy()
   42990          64 :       : exprtk::igeneric_function<T>("VV|VTTVTT")
   42991             :         /*
   42992             :            Overloads:
   42993             :            0. VV     - x(vector), y(vector)
   42994             :            1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
   42995             :         */
   42996          32 :       {}
   42997             : 
   42998           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   42999             :       {
   43000           4 :          const vector_t x(parameters[0]);
   43001           4 :                vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
   43002             : 
   43003           4 :          std::size_t xr0 = 0;
   43004           4 :          std::size_t xr1 = x.size() - 1;
   43005             : 
   43006           4 :          std::size_t yr0 = 0;
   43007           4 :          std::size_t yr1 = y.size() - 1;
   43008             : 
   43009           4 :          if (1 == ps_index)
   43010             :          {
   43011           3 :             if (
   43012           6 :                  !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
   43013           6 :                  !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
   43014             :                )
   43015           0 :                return T(0);
   43016             :          }
   43017             : 
   43018           4 :          const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
   43019             : 
   43020          12 :          std::copy(
   43021           4 :             x.begin() + xr0,
   43022           4 :             x.begin() + xr0 + n,
   43023           4 :             y.begin() + yr0);
   43024             : 
   43025           4 :          return T(n);
   43026             :       }
   43027             :    };
   43028             : 
   43029             :    template <typename T>
   43030             :    class rol exprtk_final : public exprtk::igeneric_function<T>
   43031             :    {
   43032             :    public:
   43033             : 
   43034             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43035             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43036             :       typedef typename igfun_t::generic_type        generic_type;
   43037             :       typedef typename generic_type::scalar_view    scalar_t;
   43038             :       typedef typename generic_type::vector_view    vector_t;
   43039             : 
   43040             :       using igfun_t::operator();
   43041             : 
   43042          32 :       rol()
   43043          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   43044             :         /*
   43045             :            Overloads:
   43046             :            0. VT   - vector, N
   43047             :            1. VTTT - vector, N, r0, r1
   43048             :         */
   43049          32 :       {}
   43050             : 
   43051           3 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43052             :       {
   43053           3 :          vector_t vec(parameters[0]);
   43054             : 
   43055           3 :          std::size_t n  = 0;
   43056           3 :          std::size_t r0 = 0;
   43057           3 :          std::size_t r1 = vec.size() - 1;
   43058             : 
   43059           3 :          if (!scalar_t(parameters[1]).to_uint(n))
   43060           0 :             return T(0);
   43061             : 
   43062           3 :          if (
   43063           4 :               (1 == ps_index) &&
   43064           4 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   43065             :             )
   43066           0 :             return T(0);
   43067             : 
   43068           3 :          const std::size_t dist  = r1 - r0 + 1;
   43069           3 :          const std::size_t shift = n % dist;
   43070             : 
   43071           9 :          std::rotate(
   43072           3 :             vec.begin() + r0,
   43073           3 :             vec.begin() + r0 + shift,
   43074           3 :             vec.begin() + r1 + 1);
   43075             : 
   43076           3 :          return T(1);
   43077             :       }
   43078             :    };
   43079             : 
   43080             :    template <typename T>
   43081             :    class ror exprtk_final : public exprtk::igeneric_function<T>
   43082             :    {
   43083             :    public:
   43084             : 
   43085             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43086             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43087             :       typedef typename igfun_t::generic_type        generic_type;
   43088             :       typedef typename generic_type::scalar_view    scalar_t;
   43089             :       typedef typename generic_type::vector_view    vector_t;
   43090             : 
   43091             :       using igfun_t::operator();
   43092             : 
   43093          32 :       ror()
   43094          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   43095             :         /*
   43096             :            Overloads:
   43097             :            0. VT   - vector, N
   43098             :            1. VTTT - vector, N, r0, r1
   43099             :         */
   43100          32 :       {}
   43101             : 
   43102           3 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43103             :       {
   43104           3 :          vector_t vec(parameters[0]);
   43105             : 
   43106           3 :          std::size_t n  = 0;
   43107           3 :          std::size_t r0 = 0;
   43108           3 :          std::size_t r1 = vec.size() - 1;
   43109             : 
   43110           3 :          if (!scalar_t(parameters[1]).to_uint(n))
   43111           0 :             return T(0);
   43112             : 
   43113           3 :          if (
   43114           4 :               (1 == ps_index) &&
   43115           4 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   43116             :             )
   43117           0 :             return T(0);
   43118             : 
   43119           3 :          const std::size_t dist  = r1 - r0 + 1;
   43120           3 :          const std::size_t shift = (dist - (n % dist)) % dist;
   43121             : 
   43122           9 :          std::rotate(
   43123           3 :             vec.begin() + r0,
   43124           3 :             vec.begin() + r0 + shift,
   43125           3 :             vec.begin() + r1 + 1);
   43126             : 
   43127           3 :          return T(1);
   43128             :       }
   43129             :    };
   43130             : 
   43131             :    template <typename T>
   43132             :    class shift_left exprtk_final : public exprtk::igeneric_function<T>
   43133             :    {
   43134             :    public:
   43135             : 
   43136             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43137             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43138             :       typedef typename igfun_t::generic_type        generic_type;
   43139             :       typedef typename generic_type::scalar_view    scalar_t;
   43140             :       typedef typename generic_type::vector_view    vector_t;
   43141             : 
   43142             :       using igfun_t::operator();
   43143             : 
   43144          32 :       shift_left()
   43145          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   43146             :         /*
   43147             :            Overloads:
   43148             :            0. VT   - vector, N
   43149             :            1. VTTT - vector, N, r0, r1
   43150             :         */
   43151          32 :       {}
   43152             : 
   43153           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43154             :       {
   43155           4 :          vector_t vec(parameters[0]);
   43156             : 
   43157           4 :          std::size_t n  = 0;
   43158           4 :          std::size_t r0 = 0;
   43159           4 :          std::size_t r1 = vec.size() - 1;
   43160             : 
   43161           4 :          if (!scalar_t(parameters[1]).to_uint(n))
   43162           0 :             return T(0);
   43163             : 
   43164           4 :          if (
   43165           5 :               (1 == ps_index) &&
   43166           5 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   43167             :             )
   43168           0 :             return T(0);
   43169             : 
   43170           4 :          const std::size_t dist = r1 - r0 + 1;
   43171             : 
   43172           4 :          if (n > dist)
   43173           0 :             return T(0);
   43174             : 
   43175          12 :          std::rotate(
   43176           4 :             vec.begin() + r0,
   43177           4 :             vec.begin() + r0 + n,
   43178           4 :             vec.begin() + r1 + 1);
   43179             : 
   43180          16 :          for (std::size_t i = r1 - n + 1; i <= r1; ++i)
   43181             :          {
   43182          12 :             vec[i] = T(0);
   43183             :          }
   43184             : 
   43185           4 :          return T(1);
   43186             :       }
   43187             :    };
   43188             : 
   43189             :    template <typename T>
   43190             :    class shift_right exprtk_final : public exprtk::igeneric_function<T>
   43191             :    {
   43192             :    public:
   43193             : 
   43194             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43195             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43196             :       typedef typename igfun_t::generic_type        generic_type;
   43197             :       typedef typename generic_type::scalar_view    scalar_t;
   43198             :       typedef typename generic_type::vector_view    vector_t;
   43199             : 
   43200             :       using igfun_t::operator();
   43201             : 
   43202          32 :       shift_right()
   43203          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   43204             :         /*
   43205             :            Overloads:
   43206             :            0. VT   - vector, N
   43207             :            1. VTTT - vector, N, r0, r1
   43208             :         */
   43209          32 :       {}
   43210             : 
   43211           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43212             :       {
   43213           4 :          vector_t vec(parameters[0]);
   43214             : 
   43215           4 :          std::size_t n  = 0;
   43216           4 :          std::size_t r0 = 0;
   43217           4 :          std::size_t r1 = vec.size() - 1;
   43218             : 
   43219           4 :          if (!scalar_t(parameters[1]).to_uint(n))
   43220           0 :             return T(0);
   43221             : 
   43222           4 :          if (
   43223           5 :               (1 == ps_index) &&
   43224           5 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   43225             :             )
   43226           0 :             return T(0);
   43227             : 
   43228           4 :          const std::size_t dist = r1 - r0 + 1;
   43229             : 
   43230           4 :          if (n > dist)
   43231           0 :             return T(0);
   43232             : 
   43233           4 :          const std::size_t shift = (dist - (n % dist)) % dist;
   43234             : 
   43235          12 :          std::rotate(
   43236           4 :             vec.begin() + r0,
   43237           4 :             vec.begin() + r0 + shift,
   43238           4 :             vec.begin() + r1 + 1);
   43239             : 
   43240          16 :          for (std::size_t i = r0; i < r0 + n; ++i)
   43241             :          {
   43242          12 :             vec[i] = T(0);
   43243             :          }
   43244             : 
   43245           4 :          return T(1);
   43246             :       }
   43247             :    };
   43248             : 
   43249             :    template <typename T>
   43250             :    class sort exprtk_final : public exprtk::igeneric_function<T>
   43251             :    {
   43252             :    public:
   43253             : 
   43254             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43255             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43256             :       typedef typename igfun_t::generic_type        generic_type;
   43257             :       typedef typename generic_type::string_view    string_t;
   43258             :       typedef typename generic_type::vector_view    vector_t;
   43259             : 
   43260             :       using igfun_t::operator();
   43261             : 
   43262          32 :       sort()
   43263          64 :       : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
   43264             :         /*
   43265             :            Overloads:
   43266             :            0. V    - vector
   43267             :            1. VTT  - vector, r0, r1
   43268             :            2. VS   - vector, string
   43269             :            3. VSTT - vector, string, r0, r1
   43270             :         */
   43271          32 :       {}
   43272             : 
   43273          20 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43274             :       {
   43275          20 :          vector_t vec(parameters[0]);
   43276             : 
   43277          20 :          std::size_t r0 = 0;
   43278          20 :          std::size_t r1 = vec.size() - 1;
   43279             : 
   43280          20 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
   43281           0 :             return T(0);
   43282          20 :          if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   43283           0 :             return T(0);
   43284             : 
   43285          20 :          bool ascending = true;
   43286             : 
   43287          20 :          if ((2 == ps_index) || (3 == ps_index))
   43288             :          {
   43289          24 :             if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
   43290           6 :                ascending = true;
   43291          12 :             else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
   43292           6 :                ascending = false;
   43293             :             else
   43294           0 :                return T(0);
   43295             :          }
   43296             : 
   43297          20 :          if (ascending)
   43298          28 :             std::sort(
   43299          14 :                vec.begin() + r0,
   43300          14 :                vec.begin() + r1 + 1,
   43301             :                std::less<T>());
   43302             :          else
   43303          12 :             std::sort(
   43304           6 :                vec.begin() + r0,
   43305           6 :                vec.begin() + r1 + 1,
   43306             :                std::greater<T>());
   43307             : 
   43308          20 :          return T(1);
   43309             :       }
   43310             :    };
   43311             : 
   43312             :    template <typename T>
   43313             :    class nthelement exprtk_final : public exprtk::igeneric_function<T>
   43314             :    {
   43315             :    public:
   43316             : 
   43317             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43318             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43319             :       typedef typename igfun_t::generic_type        generic_type;
   43320             :       typedef typename generic_type::scalar_view    scalar_t;
   43321             :       typedef typename generic_type::vector_view    vector_t;
   43322             : 
   43323             :       using igfun_t::operator();
   43324             : 
   43325          32 :       nthelement()
   43326          64 :       : exprtk::igeneric_function<T>("VT|VTTT")
   43327             :         /*
   43328             :            Overloads:
   43329             :            0. VT   - vector, nth-element
   43330             :            1. VTTT - vector, nth-element, r0, r1
   43331             :         */
   43332          32 :       {}
   43333             : 
   43334           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43335             :       {
   43336           4 :          vector_t vec(parameters[0]);
   43337             : 
   43338           4 :          std::size_t n  = 0;
   43339           4 :          std::size_t r0 = 0;
   43340           4 :          std::size_t r1 = vec.size() - 1;
   43341             : 
   43342           4 :          if (!scalar_t(parameters[1]).to_uint(n))
   43343           0 :             return T(0);
   43344             : 
   43345           4 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   43346             :          {
   43347           0 :             return std::numeric_limits<T>::quiet_NaN();
   43348             :          }
   43349             : 
   43350          12 :          std::nth_element(
   43351           4 :             vec.begin() + r0,
   43352           4 :             vec.begin() + r0 + n ,
   43353           4 :             vec.begin() + r1 + 1);
   43354             : 
   43355           4 :          return T(1);
   43356             :       }
   43357             :    };
   43358             : 
   43359             :    template <typename T>
   43360             :    class assign exprtk_final : public exprtk::igeneric_function<T>
   43361             :    {
   43362             :    public:
   43363             : 
   43364             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43365             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43366             :       typedef typename igfun_t::generic_type        generic_type;
   43367             :       typedef typename generic_type::scalar_view    scalar_t;
   43368             :       typedef typename generic_type::vector_view    vector_t;
   43369             : 
   43370             :       using igfun_t::operator();
   43371             : 
   43372          32 :       assign()
   43373          64 :       : exprtk::igeneric_function<T>("VT|VTTT|VTTTT")
   43374             :         /*
   43375             :            Overloads:
   43376             :            0. VT    - vector, V
   43377             :            1. VTTT  - vector, V, r0, r1
   43378             :            2. VTTTT - vector, V, r0, r1, SS
   43379             :         */
   43380          32 :       {}
   43381             : 
   43382         190 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43383             :       {
   43384         190 :          vector_t vec(parameters[0]);
   43385             : 
   43386         190 :          const T assign_value = scalar_t(parameters[1]);
   43387             : 
   43388         190 :          const std::size_t step_size = (2 != ps_index) ? 1 :
   43389         115 :                                        static_cast<std::size_t>(scalar_t(parameters.back())());
   43390             : 
   43391         190 :          std::size_t r0 = 0;
   43392         190 :          std::size_t r1 = vec.size() - 1;
   43393             : 
   43394         190 :          if (
   43395         380 :               ((ps_index == 1) || (ps_index == 2)) &&
   43396         380 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
   43397             :             )
   43398             :          {
   43399           0 :             return T(0);
   43400             :          }
   43401             : 
   43402        1040 :          for (std::size_t i = r0; i <= r1; i += step_size)
   43403             :          {
   43404         850 :             vec[i] = assign_value;
   43405             :          }
   43406             : 
   43407         190 :          return T(1);
   43408             :       }
   43409             :    };
   43410             : 
   43411             :    template <typename T>
   43412             :    class iota exprtk_final : public exprtk::igeneric_function<T>
   43413             :    {
   43414             :    public:
   43415             : 
   43416             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43417             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43418             :       typedef typename igfun_t::generic_type        generic_type;
   43419             :       typedef typename generic_type::scalar_view    scalar_t;
   43420             :       typedef typename generic_type::vector_view    vector_t;
   43421             : 
   43422             :       using igfun_t::operator();
   43423             : 
   43424          32 :       iota()
   43425          64 :       : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT")
   43426             :         /*
   43427             :            Overloads:
   43428             :            0. VTT  - vector, SV, SS
   43429             :            1. VT   - vector, SV, SS (+1)
   43430             :            2. VTTT - vector, r0, r1, SV, SS
   43431             :            3. VTT  - vector, r0, r1, SV, SS (+1)
   43432             : 
   43433             :            Where:
   43434             :            1. SV - Start value
   43435             :            2. SS - Step size
   43436             :         */
   43437          32 :       {}
   43438             : 
   43439         198 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43440             :       {
   43441         198 :          vector_t vec(parameters[0]);
   43442             : 
   43443         396 :          const T start_value = (ps_index <= 1) ?
   43444          40 :                                scalar_t(parameters[1]) :
   43445         158 :                                scalar_t(parameters[3]) ;
   43446             : 
   43447         376 :          const T step_size = ((0 == ps_index) || (2 == ps_index)) ?
   43448         178 :                              scalar_t(parameters.back())() :
   43449             :                              T(1) ;
   43450             : 
   43451         198 :          std::size_t r0 = 0;
   43452         198 :          std::size_t r1 = vec.size() - 1;
   43453             : 
   43454         198 :          if (
   43455         356 :               ((ps_index == 2) || (ps_index == 3)) &&
   43456         356 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   43457             :             )
   43458             :          {
   43459           0 :             return T(0);
   43460             :          }
   43461             : 
   43462        1120 :          for (std::size_t i = r0; i <= r1; ++i)
   43463             :          {
   43464         922 :             vec[i] = start_value + ((i - r0) * step_size);
   43465             :          }
   43466             : 
   43467         198 :          return T(1);
   43468             :       }
   43469             :    };
   43470             : 
   43471             :    template <typename T>
   43472             :    class sumk exprtk_final : public exprtk::igeneric_function<T>
   43473             :    {
   43474             :    public:
   43475             : 
   43476             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43477             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43478             :       typedef typename igfun_t::generic_type        generic_type;
   43479             :       typedef typename generic_type::scalar_view    scalar_t;
   43480             :       typedef typename generic_type::vector_view    vector_t;
   43481             : 
   43482             :       using igfun_t::operator();
   43483             : 
   43484          32 :       sumk()
   43485          64 :       : exprtk::igeneric_function<T>("V|VTT|VTTT")
   43486             :         /*
   43487             :            Overloads:
   43488             :            0. V    - vector
   43489             :            1. VTT  - vector, r0, r1
   43490             :            2. VTTT - vector, r0, r1, stride
   43491             :         */
   43492          32 :       {}
   43493             : 
   43494          25 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43495             :       {
   43496          25 :          const vector_t vec(parameters[0]);
   43497             : 
   43498          25 :          const std::size_t stride = (2 != ps_index) ? 1 :
   43499          15 :                                     static_cast<std::size_t>(scalar_t(parameters[3])());
   43500             : 
   43501          25 :          std::size_t r0 = 0;
   43502          25 :          std::size_t r1 = vec.size() - 1;
   43503             : 
   43504          25 :          if (
   43505          45 :               ((1 == ps_index) || (2 == ps_index)) &&
   43506          45 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   43507             :             )
   43508             :          {
   43509           0 :             return std::numeric_limits<T>::quiet_NaN();
   43510             :          }
   43511             : 
   43512          25 :          T result = T(0);
   43513          25 :          T error  = T(0);
   43514             : 
   43515         185 :          for (std::size_t i = r0; i <= r1;  i += stride)
   43516             :          {
   43517         160 :             details::kahan_sum(result, error, vec[i]);
   43518             :          }
   43519             : 
   43520          25 :          return result;
   43521             :       }
   43522             :    };
   43523             : 
   43524             :    template <typename T>
   43525             :    class axpy exprtk_final : public exprtk::igeneric_function<T>
   43526             :    {
   43527             :    public:
   43528             : 
   43529             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43530             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43531             :       typedef typename igfun_t::generic_type        generic_type;
   43532             :       typedef typename generic_type::scalar_view    scalar_t;
   43533             :       typedef typename generic_type::vector_view    vector_t;
   43534             : 
   43535             :       using igfun_t::operator();
   43536             : 
   43537          32 :       axpy()
   43538          64 :       : exprtk::igeneric_function<T>("TVV|TVVTT")
   43539             :         /*
   43540             :            y <- ax + y
   43541             :            Overloads:
   43542             :            0. TVV   - a, x(vector), y(vector)
   43543             :            1. TVVTT - a, x(vector), y(vector), r0, r1
   43544             :         */
   43545          32 :       {}
   43546             : 
   43547          26 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43548             :       {
   43549          26 :          const vector_t x(parameters[1]);
   43550          26 :                vector_t y(parameters[2]);
   43551             : 
   43552          26 :          std::size_t r0 = 0;
   43553          26 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43554             : 
   43555          26 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
   43556           0 :             return std::numeric_limits<T>::quiet_NaN();
   43557          26 :          else if (helper::invalid_range(y, r0, r1))
   43558           0 :             return std::numeric_limits<T>::quiet_NaN();
   43559             : 
   43560          26 :          const T a = scalar_t(parameters[0])();
   43561             : 
   43562         129 :          for (std::size_t i = r0; i <= r1; ++i)
   43563             :          {
   43564         103 :             y[i] = (a * x[i]) + y[i];
   43565             :          }
   43566             : 
   43567          26 :          return T(1);
   43568             :       }
   43569             :    };
   43570             : 
   43571             :    template <typename T>
   43572             :    class axpby exprtk_final : public exprtk::igeneric_function<T>
   43573             :    {
   43574             :    public:
   43575             : 
   43576             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43577             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43578             :       typedef typename igfun_t::generic_type        generic_type;
   43579             :       typedef typename generic_type::scalar_view    scalar_t;
   43580             :       typedef typename generic_type::vector_view    vector_t;
   43581             : 
   43582             :       using igfun_t::operator();
   43583             : 
   43584          32 :       axpby()
   43585          64 :       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
   43586             :         /*
   43587             :            y <- ax + by
   43588             :            Overloads:
   43589             :            0. TVTV   - a, x(vector), b, y(vector)
   43590             :            1. TVTVTT - a, x(vector), b, y(vector), r0, r1
   43591             :         */
   43592          32 :       {}
   43593             : 
   43594          21 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43595             :       {
   43596          21 :          const vector_t x(parameters[1]);
   43597          21 :                vector_t y(parameters[3]);
   43598             : 
   43599          21 :          std::size_t r0 = 0;
   43600          21 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43601             : 
   43602          21 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
   43603           0 :             return std::numeric_limits<T>::quiet_NaN();
   43604          21 :          else if (helper::invalid_range(y, r0, r1))
   43605           0 :             return std::numeric_limits<T>::quiet_NaN();
   43606             : 
   43607          21 :          const T a = scalar_t(parameters[0])();
   43608          21 :          const T b = scalar_t(parameters[2])();
   43609             : 
   43610         104 :          for (std::size_t i = r0; i <= r1; ++i)
   43611             :          {
   43612          83 :             y[i] = (a * x[i]) + (b * y[i]);
   43613             :          }
   43614             : 
   43615          21 :          return T(1);
   43616             :       }
   43617             :    };
   43618             : 
   43619             :    template <typename T>
   43620             :    class axpyz exprtk_final : public exprtk::igeneric_function<T>
   43621             :    {
   43622             :    public:
   43623             : 
   43624             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43625             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43626             :       typedef typename igfun_t::generic_type        generic_type;
   43627             :       typedef typename generic_type::scalar_view    scalar_t;
   43628             :       typedef typename generic_type::vector_view    vector_t;
   43629             : 
   43630             :       using igfun_t::operator();
   43631             : 
   43632          32 :       axpyz()
   43633          64 :       : exprtk::igeneric_function<T>("TVVV|TVVVTT")
   43634             :         /*
   43635             :            z <- ax + y
   43636             :            Overloads:
   43637             :            0. TVVV   - a, x(vector), y(vector), z(vector)
   43638             :            1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
   43639             :         */
   43640          32 :       {}
   43641             : 
   43642          21 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43643             :       {
   43644          21 :          const vector_t x(parameters[1]);
   43645          21 :          const vector_t y(parameters[2]);
   43646          21 :                vector_t z(parameters[3]);
   43647             : 
   43648          21 :          std::size_t r0 = 0;
   43649          21 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43650             : 
   43651          21 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
   43652           0 :             return std::numeric_limits<T>::quiet_NaN();
   43653          21 :          else if (helper::invalid_range(y, r0, r1))
   43654           0 :             return std::numeric_limits<T>::quiet_NaN();
   43655          21 :          else if (helper::invalid_range(z, r0, r1))
   43656           0 :             return std::numeric_limits<T>::quiet_NaN();
   43657             : 
   43658          21 :          const T a = scalar_t(parameters[0])();
   43659             : 
   43660         104 :          for (std::size_t i = r0; i <= r1; ++i)
   43661             :          {
   43662          83 :             z[i] = (a * x[i]) + y[i];
   43663             :          }
   43664             : 
   43665          21 :          return T(1);
   43666             :       }
   43667             :    };
   43668             : 
   43669             :    template <typename T>
   43670             :    class axpbyz exprtk_final : public exprtk::igeneric_function<T>
   43671             :    {
   43672             :    public:
   43673             : 
   43674             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43675             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43676             :       typedef typename igfun_t::generic_type        generic_type;
   43677             :       typedef typename generic_type::scalar_view    scalar_t;
   43678             :       typedef typename generic_type::vector_view    vector_t;
   43679             : 
   43680             :       using igfun_t::operator();
   43681             : 
   43682          32 :       axpbyz()
   43683          64 :       : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
   43684             :         /*
   43685             :            z <- ax + by
   43686             :            Overloads:
   43687             :            0. TVTVV   - a, x(vector), b, y(vector), z(vector)
   43688             :            1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
   43689             :         */
   43690          32 :       {}
   43691             : 
   43692          21 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43693             :       {
   43694          21 :          const vector_t x(parameters[1]);
   43695          21 :          const vector_t y(parameters[3]);
   43696          21 :                vector_t z(parameters[4]);
   43697             : 
   43698          21 :          std::size_t r0 = 0;
   43699          21 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43700             : 
   43701          21 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
   43702           0 :             return std::numeric_limits<T>::quiet_NaN();
   43703          21 :          else if (helper::invalid_range(y, r0, r1))
   43704           0 :             return std::numeric_limits<T>::quiet_NaN();
   43705          21 :          else if (helper::invalid_range(z, r0, r1))
   43706           0 :             return std::numeric_limits<T>::quiet_NaN();
   43707             : 
   43708          21 :          const T a = scalar_t(parameters[0])();
   43709          21 :          const T b = scalar_t(parameters[2])();
   43710             : 
   43711         104 :          for (std::size_t i = r0; i <= r1; ++i)
   43712             :          {
   43713          83 :             z[i] = (a * x[i]) + (b * y[i]);
   43714             :          }
   43715             : 
   43716          21 :          return T(1);
   43717             :       }
   43718             :    };
   43719             : 
   43720             :    template <typename T>
   43721             :    class axpbsy exprtk_final : public exprtk::igeneric_function<T>
   43722             :    {
   43723             :    public:
   43724             : 
   43725             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43726             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43727             :       typedef typename igfun_t::generic_type        generic_type;
   43728             :       typedef typename generic_type::scalar_view    scalar_t;
   43729             :       typedef typename generic_type::vector_view    vector_t;
   43730             : 
   43731             :       using igfun_t::operator();
   43732             : 
   43733          32 :       axpbsy()
   43734          64 :       : exprtk::igeneric_function<T>("TVTTV|TVTTVTT")
   43735             :         /*
   43736             :            y <- ax + by
   43737             :            Overloads:
   43738             :            0. TVTVV   - a, x(vector), b, shift, y(vector), z(vector)
   43739             :            1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
   43740             :         */
   43741          32 :       {}
   43742             : 
   43743           0 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43744             :       {
   43745           0 :          const vector_t x(parameters[1]);
   43746           0 :                vector_t y(parameters[4]);
   43747             : 
   43748           0 :          std::size_t r0 = 0;
   43749           0 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43750             : 
   43751           0 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
   43752           0 :             return std::numeric_limits<T>::quiet_NaN();
   43753           0 :          else if (helper::invalid_range(y, r0, r1))
   43754           0 :             return std::numeric_limits<T>::quiet_NaN();
   43755             : 
   43756           0 :          const T a = scalar_t(parameters[0])();
   43757           0 :          const T b = scalar_t(parameters[2])();
   43758             : 
   43759           0 :          const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
   43760             : 
   43761           0 :          for (std::size_t i = r0; i <= r1; ++i)
   43762             :          {
   43763           0 :             y[i] = (a * x[i]) + (b * y[i + s]);
   43764             :          }
   43765             : 
   43766           0 :          return T(1);
   43767             :       }
   43768             :    };
   43769             : 
   43770             :    template <typename T>
   43771             :    class axpbsyz exprtk_final : public exprtk::igeneric_function<T>
   43772             :    {
   43773             :    public:
   43774             : 
   43775             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43776             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43777             :       typedef typename igfun_t::generic_type        generic_type;
   43778             :       typedef typename generic_type::scalar_view    scalar_t;
   43779             :       typedef typename generic_type::vector_view    vector_t;
   43780             : 
   43781             :       using igfun_t::operator();
   43782             : 
   43783          32 :       axpbsyz()
   43784          64 :       : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT")
   43785             :         /*
   43786             :            z <- ax + by
   43787             :            Overloads:
   43788             :            0. TVTVV   - a, x(vector), b, shift, y(vector), z(vector)
   43789             :            1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
   43790             :         */
   43791          32 :       {}
   43792             : 
   43793           0 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43794             :       {
   43795           0 :          const vector_t x(parameters[1]);
   43796           0 :          const vector_t y(parameters[4]);
   43797           0 :                vector_t z(parameters[5]);
   43798             : 
   43799           0 :          std::size_t r0 = 0;
   43800           0 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43801             : 
   43802           0 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1))
   43803           0 :             return std::numeric_limits<T>::quiet_NaN();
   43804           0 :          else if (helper::invalid_range(y, r0, r1))
   43805           0 :             return std::numeric_limits<T>::quiet_NaN();
   43806           0 :          else if (helper::invalid_range(z, r0, r1))
   43807           0 :             return std::numeric_limits<T>::quiet_NaN();
   43808             : 
   43809           0 :          const T a = scalar_t(parameters[0])();
   43810           0 :          const T b = scalar_t(parameters[2])();
   43811             : 
   43812           0 :          const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
   43813             : 
   43814           0 :          for (std::size_t i = r0; i <= r1; ++i)
   43815             :          {
   43816           0 :             z[i] = (a * x[i]) + (b * y[i + s]);
   43817             :          }
   43818             : 
   43819           0 :          return T(1);
   43820             :       }
   43821             :    };
   43822             : 
   43823             :    template <typename T>
   43824             :    class axpbz exprtk_final : public exprtk::igeneric_function<T>
   43825             :    {
   43826             :    public:
   43827             : 
   43828             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43829             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43830             :       typedef typename igfun_t::generic_type        generic_type;
   43831             :       typedef typename generic_type::scalar_view    scalar_t;
   43832             :       typedef typename generic_type::vector_view    vector_t;
   43833             : 
   43834             :       using igfun_t::operator();
   43835             : 
   43836          32 :       axpbz()
   43837          64 :       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
   43838             :         /*
   43839             :            z <- ax + b
   43840             :            Overloads:
   43841             :            0. TVTV   - a, x(vector), b, z(vector)
   43842             :            1. TVTVTT - a, x(vector), b, z(vector), r0, r1
   43843             :         */
   43844          32 :       {}
   43845             : 
   43846          26 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43847             :       {
   43848          26 :          const vector_t x(parameters[1]);
   43849          26 :                vector_t z(parameters[3]);
   43850             : 
   43851          26 :          std::size_t r0 = 0;
   43852          26 :          std::size_t r1 = x.size() - 1;
   43853             : 
   43854          26 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
   43855           0 :             return std::numeric_limits<T>::quiet_NaN();
   43856          26 :          else if (helper::invalid_range(z, r0, r1))
   43857           0 :             return std::numeric_limits<T>::quiet_NaN();
   43858             : 
   43859          26 :          const T a = scalar_t(parameters[0])();
   43860          26 :          const T b = scalar_t(parameters[2])();
   43861             : 
   43862         129 :          for (std::size_t i = r0; i <= r1; ++i)
   43863             :          {
   43864         103 :             z[i] = (a * x[i]) + b;
   43865             :          }
   43866             : 
   43867          26 :          return T(1);
   43868             :       }
   43869             :    };
   43870             : 
   43871             :    template <typename T>
   43872             :    class diff exprtk_final : public exprtk::igeneric_function<T>
   43873             :    {
   43874             :    public:
   43875             : 
   43876             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43877             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43878             :       typedef typename igfun_t::generic_type        generic_type;
   43879             :       typedef typename generic_type::scalar_view    scalar_t;
   43880             :       typedef typename generic_type::vector_view    vector_t;
   43881             : 
   43882             :       using igfun_t::operator();
   43883             : 
   43884          32 :       diff()
   43885          64 :       : exprtk::igeneric_function<T>("VV|VVT")
   43886             :         /*
   43887             :            x_(i - stride) - x_i
   43888             :            Overloads:
   43889             :            0. VV  - x(vector), y(vector)
   43890             :            1. VVT - x(vector), y(vector), stride
   43891             :         */
   43892          32 :       {}
   43893             : 
   43894          10 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43895             :       {
   43896          10 :          const vector_t x(parameters[0]);
   43897          10 :                vector_t y(parameters[1]);
   43898             : 
   43899          10 :          const std::size_t r0 = 0;
   43900          10 :          const std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43901             : 
   43902          15 :          const std::size_t stride = (1 != ps_index) ? 1 :
   43903           5 :                                     std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])()));
   43904             : 
   43905          25 :          for (std::size_t i = 0; i < stride; ++i)
   43906             :          {
   43907          15 :             y[i] = std::numeric_limits<T>::quiet_NaN();
   43908             :          }
   43909             : 
   43910          75 :          for (std::size_t i = (r0 + stride); i <= r1; ++i)
   43911             :          {
   43912          65 :             y[i] = x[i] - x[i - stride];
   43913             :          }
   43914             : 
   43915          10 :          return T(1);
   43916             :       }
   43917             :    };
   43918             : 
   43919             :    template <typename T>
   43920             :    class dot exprtk_final : public exprtk::igeneric_function<T>
   43921             :    {
   43922             :    public:
   43923             : 
   43924             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43925             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43926             :       typedef typename igfun_t::generic_type        generic_type;
   43927             :       typedef typename generic_type::scalar_view    scalar_t;
   43928             :       typedef typename generic_type::vector_view    vector_t;
   43929             : 
   43930             :       using igfun_t::operator();
   43931             : 
   43932          32 :       dot()
   43933          64 :       : exprtk::igeneric_function<T>("VV|VVTT")
   43934             :         /*
   43935             :            Overloads:
   43936             :            0. VV   - x(vector), y(vector)
   43937             :            1. VVTT - x(vector), y(vector), r0, r1
   43938             :         */
   43939          32 :       {}
   43940             : 
   43941        1830 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43942             :       {
   43943        1830 :          const vector_t x(parameters[0]);
   43944        1830 :          const vector_t y(parameters[1]);
   43945             : 
   43946        1830 :          std::size_t r0 = 0;
   43947        1830 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43948             : 
   43949        1830 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   43950           0 :             return std::numeric_limits<T>::quiet_NaN();
   43951        1830 :          else if (helper::invalid_range(y, r0, r1))
   43952           0 :             return std::numeric_limits<T>::quiet_NaN();
   43953             : 
   43954        1830 :          T result = T(0);
   43955             : 
   43956       11030 :          for (std::size_t i = r0; i <= r1; ++i)
   43957             :          {
   43958        9200 :             result += (x[i] * y[i]);
   43959             :          }
   43960             : 
   43961        1830 :          return result;
   43962             :       }
   43963             :    };
   43964             : 
   43965             :    template <typename T>
   43966             :    class dotk exprtk_final : public exprtk::igeneric_function<T>
   43967             :    {
   43968             :    public:
   43969             : 
   43970             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   43971             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   43972             :       typedef typename igfun_t::generic_type        generic_type;
   43973             :       typedef typename generic_type::scalar_view    scalar_t;
   43974             :       typedef typename generic_type::vector_view    vector_t;
   43975             : 
   43976             :       using igfun_t::operator();
   43977             : 
   43978          32 :       dotk()
   43979          64 :       : exprtk::igeneric_function<T>("VV|VVTT")
   43980             :         /*
   43981             :            Overloads:
   43982             :            0. VV   - x(vector), y(vector)
   43983             :            1. VVTT - x(vector), y(vector), r0, r1
   43984             :         */
   43985          32 :       {}
   43986             : 
   43987           0 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   43988             :       {
   43989           0 :          const vector_t x(parameters[0]);
   43990           0 :          const vector_t y(parameters[1]);
   43991             : 
   43992           0 :          std::size_t r0 = 0;
   43993           0 :          std::size_t r1 = std::min(x.size(),y.size()) - 1;
   43994             : 
   43995           0 :          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
   43996           0 :             return std::numeric_limits<T>::quiet_NaN();
   43997           0 :          else if (helper::invalid_range(y, r0, r1))
   43998           0 :             return std::numeric_limits<T>::quiet_NaN();
   43999             : 
   44000           0 :          T result = T(0);
   44001           0 :          T error  = T(0);
   44002             : 
   44003           0 :          for (std::size_t i = r0; i <= r1; ++i)
   44004             :          {
   44005           0 :             details::kahan_sum(result, error, (x[i] * y[i]));
   44006             :          }
   44007             : 
   44008           0 :          return result;
   44009             :       }
   44010             :    };
   44011             : 
   44012             :    template <typename T>
   44013             :    class threshold_below exprtk_final : public exprtk::igeneric_function<T>
   44014             :    {
   44015             :    public:
   44016             : 
   44017             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44018             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44019             :       typedef typename igfun_t::generic_type        generic_type;
   44020             :       typedef typename generic_type::scalar_view    scalar_t;
   44021             :       typedef typename generic_type::vector_view    vector_t;
   44022             : 
   44023             :       using igfun_t::operator();
   44024             : 
   44025          32 :       threshold_below()
   44026          64 :       : exprtk::igeneric_function<T>("VTT|VTTTT")
   44027             :       /*
   44028             :          Overloads:
   44029             :          0. VTT   - vector, TV, SV
   44030             :          1. VTTTT - vector, r0, r1, TV, SV
   44031             : 
   44032             :          Where:
   44033             :          TV - Threshold value
   44034             :          SV - Snap-to value
   44035             :       */
   44036          32 :       {}
   44037             : 
   44038           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44039             :       {
   44040           4 :          vector_t vec(parameters[0]);
   44041             : 
   44042           8 :          const T threshold_value = (0 == ps_index) ?
   44043           1 :                                    scalar_t(parameters[1]) :
   44044           3 :                                    scalar_t(parameters[3]) ;
   44045             : 
   44046           4 :          const T snap_value = scalar_t(parameters.back());
   44047             : 
   44048           4 :          std::size_t r0 = 0;
   44049           4 :          std::size_t r1 = vec.size() - 1;
   44050             : 
   44051           4 :          if (
   44052           7 :               (1 == ps_index) &&
   44053           7 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44054             :             )
   44055             :          {
   44056           0 :             return T(0);
   44057             :          }
   44058             : 
   44059          22 :          for (std::size_t i = r0; i <= r1; ++i)
   44060             :          {
   44061          18 :             if (vec[i] < threshold_value)
   44062             :             {
   44063           6 :                vec[i] = snap_value;
   44064             :             }
   44065             :          }
   44066             : 
   44067           4 :          return T(1);
   44068             :       }
   44069             :    };
   44070             : 
   44071             :    template <typename T>
   44072             :    class threshold_above exprtk_final : public exprtk::igeneric_function<T>
   44073             :    {
   44074             :    public:
   44075             : 
   44076             :       typedef typename exprtk::igeneric_function<T> igfun_t;
   44077             :       typedef typename igfun_t::parameter_list_t    parameter_list_t;
   44078             :       typedef typename igfun_t::generic_type        generic_type;
   44079             :       typedef typename generic_type::scalar_view    scalar_t;
   44080             :       typedef typename generic_type::vector_view    vector_t;
   44081             : 
   44082             :       using igfun_t::operator();
   44083             : 
   44084          32 :       threshold_above()
   44085          64 :       : exprtk::igeneric_function<T>("VTT|VTTTT")
   44086             :       /*
   44087             :          Overloads:
   44088             :          0. VTT   - vector, TV, SV
   44089             :          1. VTTTT - vector, r0, r1, TV, SV
   44090             : 
   44091             :          Where:
   44092             :          TV - Threshold value
   44093             :          SV - Snap-to value
   44094             :       */
   44095          32 :       {}
   44096             : 
   44097           4 :       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
   44098             :       {
   44099           4 :          vector_t vec(parameters[0]);
   44100             : 
   44101           8 :          const T threshold_value = (0 == ps_index) ?
   44102           1 :                                    scalar_t(parameters[1]) :
   44103           3 :                                    scalar_t(parameters[3]) ;
   44104             : 
   44105           4 :          const T snap_value = scalar_t(parameters.back());
   44106             : 
   44107           4 :          std::size_t r0 = 0;
   44108           4 :          std::size_t r1 = vec.size() - 1;
   44109             : 
   44110           4 :          if (
   44111           7 :               (1 == ps_index) &&
   44112           7 :               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
   44113             :             )
   44114             :          {
   44115           0 :             return T(0);
   44116             :          }
   44117             : 
   44118          22 :          for (std::size_t i = r0; i <= r1; ++i)
   44119             :          {
   44120          18 :             if (vec[i] > threshold_value)
   44121             :             {
   44122           8 :                vec[i] = snap_value;
   44123             :             }
   44124             :          }
   44125             : 
   44126           4 :          return T(1);
   44127             :       }
   44128             :    };
   44129             : 
   44130             :    template <typename T>
   44131             :    struct package
   44132             :    {
   44133             :       all_true       <T> at;
   44134             :       all_false      <T> af;
   44135             :       any_true       <T> nt;
   44136             :       any_false      <T> nf;
   44137             :       count          <T>  c;
   44138             :       copy           <T> cp;
   44139             :       rol            <T> rl;
   44140             :       ror            <T> rr;
   44141             :       shift_left     <T> sl;
   44142             :       shift_right    <T> sr;
   44143             :       sort           <T> st;
   44144             :       nthelement     <T> ne;
   44145             :       assign         <T> an;
   44146             :       iota           <T> ia;
   44147             :       sumk           <T> sk;
   44148             :       axpy           <T> b1_axpy;
   44149             :       axpby          <T> b1_axpby;
   44150             :       axpyz          <T> b1_axpyz;
   44151             :       axpbyz         <T> b1_axpbyz;
   44152             :       axpbsy         <T> b1_axpbsy;
   44153             :       axpbsyz        <T> b1_axpbsyz;
   44154             :       axpbz          <T> b1_axpbz;
   44155             :       diff           <T> df;
   44156             :       dot            <T> dt;
   44157             :       dotk           <T> dtk;
   44158             :       threshold_above<T> ta;
   44159             :       threshold_below<T> tb;
   44160             : 
   44161          32 :       bool register_package(exprtk::symbol_table<T>& symtab)
   44162             :       {
   44163             :          #define exprtk_register_function(FunctionName, FunctionType)                 \
   44164             :          if (!symtab.add_function(FunctionName,FunctionType))                         \
   44165             :          {                                                                            \
   44166             :             exprtk_debug((                                                            \
   44167             :               "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
   44168             :               FunctionName));                                                         \
   44169             :             return false;                                                             \
   44170             :          }                                                                            \
   44171             : 
   44172          96 :          exprtk_register_function("all_true"        , at        )
   44173          96 :          exprtk_register_function("all_false"       , af        )
   44174          96 :          exprtk_register_function("any_true"        , nt        )
   44175          96 :          exprtk_register_function("any_false"       , nf        )
   44176          96 :          exprtk_register_function("count"           , c         )
   44177          96 :          exprtk_register_function("copy"            , cp        )
   44178          96 :          exprtk_register_function("rotate_left"     , rl        )
   44179          96 :          exprtk_register_function("rol"             , rl        )
   44180          96 :          exprtk_register_function("rotate_right"    , rr        )
   44181          96 :          exprtk_register_function("ror"             , rr        )
   44182          96 :          exprtk_register_function("shftl"           , sl        )
   44183          96 :          exprtk_register_function("shftr"           , sr        )
   44184          96 :          exprtk_register_function("sort"            , st        )
   44185          96 :          exprtk_register_function("nth_element"     , ne        )
   44186          96 :          exprtk_register_function("assign"          , an        )
   44187          96 :          exprtk_register_function("iota"            , ia        )
   44188          96 :          exprtk_register_function("sumk"            , sk        )
   44189          96 :          exprtk_register_function("axpy"            , b1_axpy   )
   44190          96 :          exprtk_register_function("axpby"           , b1_axpby  )
   44191          96 :          exprtk_register_function("axpyz"           , b1_axpyz  )
   44192          96 :          exprtk_register_function("axpbyz"          , b1_axpbyz )
   44193          96 :          exprtk_register_function("axpbsy"          , b1_axpbsy )
   44194          96 :          exprtk_register_function("axpbsyz"         , b1_axpbsyz)
   44195          96 :          exprtk_register_function("axpbz"           , b1_axpbz  )
   44196          96 :          exprtk_register_function("diff"            , df        )
   44197          96 :          exprtk_register_function("dot"             , dt        )
   44198          96 :          exprtk_register_function("dotk"            , dtk       )
   44199          96 :          exprtk_register_function("threshold_above" , ta        )
   44200          96 :          exprtk_register_function("threshold_below" , tb        )
   44201             :          #undef exprtk_register_function
   44202             : 
   44203          32 :          return true;
   44204             :       }
   44205             :    };
   44206             : 
   44207             :    } // namespace exprtk::rtl::vecops
   44208             :    } // namespace exprtk::rtl
   44209             : }    // namespace exprtk
   44210             : #endif
   44211             : 
   44212             : namespace exprtk
   44213             : {
   44214             :    namespace information
   44215             :    {
   44216             :       using ::exprtk::details::char_cptr;
   44217             : 
   44218             :       static char_cptr library = "Mathematical Expression Toolkit";
   44219             :       static char_cptr version = "2.718281828459045235360287471352662"
   44220             :                                  "49775724709369995957496696762772407"
   44221             :                                  "66303535475945713821785251664274274"
   44222             :                                  "66391932003059921817413596629043572";
   44223             :       static char_cptr date    = "20240101";
   44224             :       static char_cptr min_cpp = "199711L";
   44225             : 
   44226             :       static inline std::string data()
   44227             :       {
   44228             :          static const std::string info_str = std::string(library) +
   44229             :                                              std::string(" v") + std::string(version) +
   44230             :                                              std::string(" (") + date + std::string(")") +
   44231             :                                              std::string(" (") + min_cpp + std::string(")");
   44232             :          return info_str;
   44233             :       }
   44234             : 
   44235             :    } // namespace information
   44236             : 
   44237             :    #ifdef exprtk_debug
   44238             :    #undef exprtk_debug
   44239             :    #endif
   44240             : 
   44241             :    #ifdef exprtk_error_location
   44242             :    #undef exprtk_error_location
   44243             :    #endif
   44244             : 
   44245             :    #ifdef exprtk_fallthrough
   44246             :    #undef exprtk_fallthrough
   44247             :    #endif
   44248             : 
   44249             :    #ifdef exprtk_override
   44250             :    #undef exprtk_override
   44251             :    #endif
   44252             : 
   44253             :    #ifdef exprtk_final
   44254             :    #undef exprtk_final
   44255             :    #endif
   44256             : 
   44257             :    #ifdef exprtk_delete
   44258             :    #undef exprtk_delete
   44259             :    #endif
   44260             : 
   44261             : } // namespace exprtk
   44262             : 
   44263             : #endif

Generated by: LCOV version 1.14