diff --git a/src/core/math/extern/.clang-tidy b/src/core/math/extern/.clang-tidy
new file mode 100644
index 0000000000000000000000000000000000000000..8f3d2744dd68901ffa8d4a7d993c8c5a93bc506b
--- /dev/null
+++ b/src/core/math/extern/.clang-tidy
@@ -0,0 +1,3 @@
+# Disable all checks in this folder.
+Checks: '-*'
+
diff --git a/src/core/math/extern/exprtk.h b/src/core/math/extern/exprtk.h
index afa862bf11b3a28de2c44bd6145cd09842137f50..da493c5917a08bbd01ad8369895421f9ef77db3b 100644
--- a/src/core/math/extern/exprtk.h
+++ b/src/core/math/extern/exprtk.h
@@ -2,14 +2,15 @@
  ******************************************************************
  *           C++ Mathematical Expression Toolkit Library          *
  *                                                                *
- * Author: Arash Partow (1999-2021)                               *
- * URL: http://www.partow.net/programming/exprtk/index.html       *
+ * Author: Arash Partow (1999-2024)                               *
+ * URL: https://www.partow.net/programming/exprtk/index.html      *
  *                                                                *
  * Copyright notice:                                              *
  * Free use of the C++ Mathematical Expression Toolkit Library is *
  * permitted under the guidelines and in accordance with the most *
  * current version of the MIT License.                            *
- * http://www.opensource.org/licenses/MIT                         *
+ * https://www.opensource.org/licenses/MIT                        *
+ * SPDX-License-Identifier: MIT                                   *
  *                                                                *
  * Example expressions:                                           *
  * (00) (y + x / y) * (x - y / x)                                 *
@@ -17,12 +18,12 @@
  * (02) sqrt(1 - (x^2))                                           *
  * (03) 1 - sin(2 * x) + cos(pi / y)                              *
  * (04) a * exp(2 * t) + c                                        *
- * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)        *
+ * (05) if(((x + 2) == 3) and ((y + 5) <= 9), 1 + w, 2 / z)       *
  * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x          *
  * (07) z := x + sin(2 * pi / y)                                  *
  * (08) u := 2 * (pi * z) / (w := x + cos(y / pi))                *
- * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1)            *
- * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)     *
+ * (09) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)          *
+ * (10) inrange(-2, m, +2) == if(({-2 <= m} and [m <= +2]), 1, 0) *
  * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1)  *
  * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *
  *                                                                *
@@ -38,12 +39,10 @@
 #include <cassert>
 #include <cctype>
 #include <cmath>
-#include <complex>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
 #include <deque>
-#include <exception>
 #include <functional>
 #include <iterator>
 #include <limits>
@@ -68,30 +67,38 @@ namespace exprtk
    #define exprtk_error_location             \
    "exprtk.hpp:" + details::to_str(__LINE__) \
 
-   #if defined(__GNUC__) && (__GNUC__  >= 7)
-
-      #define exprtk_disable_fallthrough_begin                      \
-      _Pragma ("GCC diagnostic push")                               \
-      _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
-
-      #define exprtk_disable_fallthrough_end                        \
-      _Pragma ("GCC diagnostic pop")                                \
+   #if __cplusplus >= 201103L
+      #define exprtk_override override
+      #define exprtk_final    final
+      #define exprtk_delete   = delete
+   #else
+      #define exprtk_override
+      #define exprtk_final
+      #define exprtk_delete
+   #endif
 
+   #if __cplusplus >= 201603L
+      #define exprtk_fallthrough [[fallthrough]];
+   #elif __cplusplus >= 201103L
+      #define exprtk_fallthrough [[gnu::fallthrough]];
    #else
-      #define exprtk_disable_fallthrough_begin (void)0;
-      #define exprtk_disable_fallthrough_end   (void)0;
+      #ifndef _MSC_VER
+      #define exprtk_fallthrough __attribute__ ((fallthrough));
+      #else
+      #define exprtk_fallthrough
+      #endif
    #endif
 
    namespace details
    {
-      typedef unsigned char            uchar_t;
-      typedef char                      char_t;
-      typedef uchar_t*               uchar_ptr;
-      typedef char_t*                 char_ptr;
-      typedef uchar_t const*        uchar_cptr;
+      typedef char                   char_t;
+      typedef char_t*                char_ptr;
       typedef char_t const*          char_cptr;
+      typedef unsigned char          uchar_t;
+      typedef uchar_t*               uchar_ptr;
+      typedef uchar_t const*         uchar_cptr;
       typedef unsigned long long int _uint64_t;
-      typedef long long int           _int64_t;
+      typedef long long int          _int64_t;
 
       inline bool is_whitespace(const char_t c)
       {
@@ -167,7 +174,7 @@ namespace exprtk
 
       inline bool is_valid_string_char(const char_t c)
       {
-         return std::isprint(static_cast<unsigned char>(c)) ||
+         return std::isprint(static_cast<uchar_t>(c)) ||
                 is_whitespace(c);
       }
 
@@ -209,15 +216,15 @@ namespace exprtk
          {
             const std::size_t length = std::min(s1.size(),s2.size());
 
-            for (std::size_t i = 0; i < length;  ++i)
+            for (std::size_t i = 0; i < length; ++i)
             {
-               const char_t c1 = static_cast<char>(std::tolower(s1[i]));
-               const char_t c2 = static_cast<char>(std::tolower(s2[i]));
+               const char_t c1 = static_cast<char_t>(std::tolower(s1[i]));
+               const char_t c2 = static_cast<char_t>(std::tolower(s2[i]));
 
-               if (c1 > c2)
-                  return false;
-               else if (c1 < c2)
+               if (c1 < c2)
                   return true;
+               else if (c2 < c1)
+                  return false;
             }
 
             return s1.size() < s2.size();
@@ -274,21 +281,16 @@ namespace exprtk
 
          std::string result;
 
-         if (i < 0)
-         {
-            for ( ; i; i /= 10)
-            {
-               result += '0' + char(-(i % 10));
-            }
+         const int sign = (i < 0) ? -1 : 1;
 
-            result += '-';
+         for ( ; i; i /= 10)
+         {
+            result += '0' + static_cast<char_t>(sign * (i % 10));
          }
-         else
+
+         if (sign < 0)
          {
-            for ( ; i; i /= 10)
-            {
-               result += '0' + char(i % 10);
-            }
+            result += '-';
          }
 
          std::reverse(result.begin(), result.end());
@@ -301,7 +303,7 @@ namespace exprtk
          return to_str(static_cast<int>(i));
       }
 
-      inline bool is_hex_digit(const std::string::value_type digit)
+      inline bool is_hex_digit(const uchar_t digit)
       {
          return (('0' <= digit) && (digit <= '9')) ||
                 (('A' <= digit) && (digit <= 'F')) ||
@@ -313,12 +315,12 @@ namespace exprtk
          if (('0' <= h) && (h <= '9'))
             return (h - '0');
          else
-            return static_cast<unsigned char>(std::toupper(h) - 'A');
+            return static_cast<uchar_t>(std::toupper(h) - 'A');
       }
 
       template <typename Iterator>
       inline bool parse_hex(Iterator& itr, Iterator end,
-                            std::string::value_type& result)
+                            char_t& result)
       {
          if (
               (end ==  (itr    ))               ||
@@ -360,9 +362,9 @@ namespace exprtk
                }
                else if (parse_hex(itr1, end, *itr2))
                {
-                  itr1+= 4;
-                  itr2+= 1;
-                  removal_count +=4;
+                  itr1 += 4;
+                  itr2 += 1;
+                  removal_count += 4;
                }
                else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; }
                else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; }
@@ -377,6 +379,7 @@ namespace exprtk
                   (*itr2++) = (*itr1++);
                   ++removal_count;
                }
+
                continue;
             }
             else
@@ -395,7 +398,7 @@ namespace exprtk
       {
       public:
 
-         build_string(const std::size_t& initial_size = 64)
+         explicit build_string(const std::size_t& initial_size = 64)
          {
             data_.reserve(initial_size);
          }
@@ -428,85 +431,85 @@ namespace exprtk
       };
 
       static const std::string reserved_words[] =
-                                  {
-                                    "break",  "case",  "continue",  "default",  "false",  "for",
-                                    "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
-                                    "not",  "null",  "or",   "repeat", "return",  "shl",  "shr",
-                                    "swap", "switch", "true",  "until", "var",  "while", "xnor",
-                                    "xor", "&", "|"
-                                  };
+      {
+         "assert",  "break", "case", "continue", "const",  "default",
+         "false", "for", "if", "else", "ilike", "in", "like",  "and",
+         "nand",  "nor",  "not",  "null",  "or",  "repeat", "return",
+         "shl",  "shr",  "swap",  "switch",  "true",  "until", "var",
+         "while", "xnor", "xor", "&", "|"
+      };
 
       static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
 
       static const std::string reserved_symbols[] =
-                                  {
-                                    "abs",  "acos",  "acosh",  "and",  "asin",  "asinh", "atan",
-                                    "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
-                                    "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
-                                    "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
-                                    "expm1",  "false",   "floor",  "for",   "frac",  "grad2deg",
-                                    "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
-                                    "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
-                                    "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
-                                    "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
-                                    "repeat", "return", "root", "round", "roundn", "sec", "sgn",
-                                    "shl", "shr", "sin", "sinc", "sinh", "sqrt",  "sum", "swap",
-                                    "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
-                                    "while", "xnor", "xor", "&", "|"
-                                  };
+      {
+         "abs", "acos",  "acosh", "and",  "asin", "asinh",  "assert",
+         "atan", "atanh",  "atan2", "avg",  "break", "case",  "ceil",
+         "clamp", "continue", "const",  "cos", "cosh", "cot",  "csc",
+         "default",  "deg2grad", "deg2rad",  "equal", "erf",  "erfc",
+         "exp", "expm1", "false", "floor", "for", "frac", "grad2deg",
+         "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
+         "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
+         "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
+         "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
+         "repeat", "return", "root", "round", "roundn", "sec", "sgn",
+         "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum",  "swap",
+         "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
+         "while", "xnor", "xor", "&", "|"
+      };
 
       static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
 
       static const std::string base_function_list[] =
-                                  {
-                                    "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
-                                    "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
-                                    "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
-                                    "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
-                                    "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
-                                    "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
-                                    "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
-                                    "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
-                                    "rad2deg", "grad2deg"
-                                  };
+      {
+         "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
+         "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
+         "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
+         "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
+         "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
+         "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
+         "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
+         "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
+         "rad2deg", "grad2deg"
+      };
 
       static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
 
       static const std::string logic_ops_list[] =
-                                  {
-                                    "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
-                                  };
+      {
+         "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
+      };
 
       static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
 
       static const std::string cntrl_struct_list[] =
-                                  {
-                                     "if", "switch", "for", "while", "repeat", "return"
-                                  };
+      {
+         "if", "switch", "for", "while", "repeat", "return"
+      };
 
       static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
 
       static const std::string arithmetic_ops_list[] =
-                                  {
-                                    "+", "-", "*", "/", "%", "^"
-                                  };
+      {
+         "+", "-", "*", "/", "%", "^"
+      };
 
       static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
 
       static const std::string assignment_ops_list[] =
-                                  {
-                                    ":=", "+=", "-=",
-                                    "*=", "/=", "%="
-                                  };
+      {
+         ":=", "+=", "-=",
+         "*=", "/=", "%="
+      };
 
       static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
 
       static const std::string inequality_ops_list[] =
-                                  {
-                                     "<",  "<=", "==",
-                                     "=",  "!=", "<>",
-                                    ">=",  ">"
-                                  };
+      {
+         "<",  "<=", "==",
+         "=",  "!=", "<>",
+         ">=",  ">"
+      };
 
       static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
 
@@ -597,78 +600,87 @@ namespace exprtk
                              const Iterator data_begin   ,
                              const Iterator data_end     ,
                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
-                             const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
+                             const typename std::iterator_traits<Iterator>::value_type& exactly_one )
       {
+         typedef typename std::iterator_traits<Iterator>::value_type type;
+
          const Iterator null_itr(0);
 
-         Iterator d_itr    = data_begin;
-         Iterator p_itr    = pattern_begin;
-         Iterator tb_p_itr = null_itr;
-         Iterator tb_d_itr = null_itr;
+         Iterator p_itr  = pattern_begin;
+         Iterator d_itr  = data_begin;
+         Iterator np_itr = null_itr;
+         Iterator nd_itr = null_itr;
 
-         while (d_itr != data_end)
+         for ( ; ; )
          {
-            if (zero_or_more == *p_itr)
+            if (p_itr != pattern_end)
             {
-               while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
-               {
-                  ++p_itr;
-               }
-
-               if (pattern_end == p_itr)
-                  return true;
+               const type c = *(p_itr);
 
-               const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
-
-               while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
+               if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c)))
                {
                   ++d_itr;
+                  ++p_itr;
+                  continue;
                }
+               else if (zero_or_more == c)
+               {
+                  while ((pattern_end != p_itr) && (zero_or_more == *(p_itr)))
+                  {
+                     ++p_itr;
+                  }
 
-               tb_p_itr = p_itr;
-               tb_d_itr = d_itr;
+                  const type d = *(p_itr);
 
-               continue;
-            }
-            else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
-            {
-               if (null_itr == tb_d_itr)
-                  return false;
+                  while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d)))
+                  {
+                     ++d_itr;
+                  }
 
-               d_itr = tb_d_itr++;
-               p_itr = tb_p_itr;
+                  // set backtrack iterators
+                  np_itr = p_itr - 1;
+                  nd_itr = d_itr + 1;
 
-               continue;
+                  continue;
+               }
             }
+            else if (data_end == d_itr)
+               break;
 
-            ++p_itr;
-            ++d_itr;
-         }
+            if ((data_end == d_itr) || (null_itr == nd_itr))
+                return false;
 
-         while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
-         {
-            ++p_itr;
+            p_itr = np_itr;
+            d_itr = nd_itr;
          }
 
-         return (pattern_end == p_itr);
+         return true;
       }
 
       inline bool wc_match(const std::string& wild_card,
                            const std::string& str)
       {
-         return match_impl<char_cptr,cs_match>(
-                   wild_card.data(), wild_card.data() + wild_card.size(),
-                   str.data(), str.data() + str.size(),
-                   '*', '?');
+         return match_impl<char_cptr,cs_match>
+                (
+                   wild_card.data(),
+                   wild_card.data() + wild_card.size(),
+                   str.data(),
+                   str.data() + str.size(),
+                   '*', '?'
+                );
       }
 
       inline bool wc_imatch(const std::string& wild_card,
                             const std::string& str)
       {
-         return match_impl<char_cptr,cis_match>(
-                   wild_card.data(), wild_card.data() + wild_card.size(),
-                   str.data(), str.data() + str.size(),
-                   '*', '?');
+         return match_impl<char_cptr,cis_match>
+                (
+                   wild_card.data(),
+                   wild_card.data() + wild_card.size(),
+                   str.data(),
+                   str.data() + str.size(),
+                   '*', '?'
+                );
       }
 
       inline bool sequence_match(const std::string& pattern,
@@ -688,19 +700,19 @@ namespace exprtk
          itr_t p_itr = pattern.begin();
          itr_t s_itr = str    .begin();
 
-         itr_t p_end = pattern.end();
-         itr_t s_end = str    .end();
+         const itr_t p_end = pattern.end();
+         const itr_t s_end = str    .end();
 
          while ((s_end != s_itr) && (p_end != p_itr))
          {
             if ('*' == (*p_itr))
             {
-               const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
+               const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1)));
 
                if ('*' == target)
                {
                   diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
-                  diff_value = static_cast<char>(std::toupper(*p_itr));
+                  diff_value = static_cast<char_t>(std::toupper(*p_itr));
 
                   return false;
                }
@@ -723,7 +735,7 @@ namespace exprtk
                     )
             {
                diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
-               diff_value = static_cast<char>(std::toupper(*p_itr));
+               diff_value = static_cast<char_t>(std::toupper(*p_itr));
 
                return false;
             }
@@ -741,13 +753,55 @@ namespace exprtk
                 );
       }
 
-      static const double pow10[] = {
-                                      1.0,
-                                      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, 1.0E+011, 1.0E+012,
-                                      1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
-                                    };
+      template<typename T>
+      struct set_zero_value_impl
+      {
+         static inline void process(T* base_ptr, const std::size_t size)
+         {
+            const T zero = T(0);
+            for (std::size_t i = 0; i < size; ++i)
+            {
+               base_ptr[i] = zero;
+            }
+         }
+      };
+
+      #define pod_set_zero_value(T)                                      \
+      template <>                                                        \
+      struct set_zero_value_impl<T>                                      \
+      {                                                                  \
+         static inline void process(T* base_ptr, const std::size_t size) \
+         { std::memset(base_ptr, 0x00, size * sizeof(T)); }              \
+      };                                                                 \
+
+      pod_set_zero_value(float      )
+      pod_set_zero_value(double     )
+      pod_set_zero_value(long double)
+
+      #ifdef pod_set_zero_value
+      #undef pod_set_zero_value
+      #endif
+
+      template<typename T>
+      inline void set_zero_value(T* data, const std::size_t size)
+      {
+         set_zero_value_impl<T>::process(data,size);
+      }
+
+      template<typename T>
+      inline void set_zero_value(std::vector<T>& v)
+      {
+         set_zero_value(v.data(),v.size());
+      }
+
+      static const double pow10[] =
+      {
+         1.0,
+         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, 1.0E+011, 1.0E+012,
+         1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
+      };
 
       static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
 
@@ -771,7 +825,6 @@ namespace exprtk
          {
             struct unknown_type_tag { unknown_type_tag() {} };
             struct real_type_tag    { real_type_tag   () {} };
-            struct complex_type_tag { complex_type_tag() {} };
             struct int_type_tag     { int_type_tag    () {} };
 
             template <typename T>
@@ -781,25 +834,17 @@ namespace exprtk
                number_type() {}
             };
 
-            #define exprtk_register_real_type_tag(T)             \
-            template <> struct number_type<T>                    \
-            { typedef real_type_tag type; number_type() {} };    \
+            #define exprtk_register_real_type_tag(T)          \
+            template <> struct number_type<T>                 \
+            { typedef real_type_tag type; number_type() {} }; \
 
-            #define exprtk_register_complex_type_tag(T)          \
-            template <> struct number_type<std::complex<T> >     \
-            { typedef complex_type_tag type; number_type() {} }; \
-
-            #define exprtk_register_int_type_tag(T)              \
-            template <> struct number_type<T>                    \
-            { typedef int_type_tag type; number_type() {} };     \
+            #define exprtk_register_int_type_tag(T)           \
+            template <> struct number_type<T>                 \
+            { typedef int_type_tag type; number_type() {} };  \
 
+            exprtk_register_real_type_tag(float      )
             exprtk_register_real_type_tag(double     )
             exprtk_register_real_type_tag(long double)
-            exprtk_register_real_type_tag(float      )
-
-            exprtk_register_complex_type_tag(double     )
-            exprtk_register_complex_type_tag(long double)
-            exprtk_register_complex_type_tag(float      )
 
             exprtk_register_int_type_tag(short         )
             exprtk_register_int_type_tag(int           )
@@ -812,34 +857,23 @@ namespace exprtk
             #undef exprtk_register_int_type_tag
 
             template <typename T>
-            struct epsilon_type
-            {
-               static inline T value()
-               {
-                  const T epsilon = T(0.0000000001);
-                  return epsilon;
-               }
-            };
+            struct epsilon_type {};
 
-            template <>
-            struct epsilon_type <float>
-            {
-               static inline float value()
-               {
-                  const float epsilon = float(0.000001f);
-                  return epsilon;
-               }
-            };
+            #define exprtk_define_epsilon_type(Type, Epsilon)      \
+            template <> struct epsilon_type<Type>                  \
+            {                                                      \
+               static inline Type value()                          \
+               {                                                   \
+                  const Type epsilon = static_cast<Type>(Epsilon); \
+                  return epsilon;                                  \
+               }                                                   \
+            };                                                     \
 
-            template <>
-            struct epsilon_type <long double>
-            {
-               static inline long double value()
-               {
-                  const long double epsilon = static_cast<long double>(0.000000000001);
-                  return epsilon;
-               }
-            };
+            exprtk_define_epsilon_type(float      , 0.00000100000f)
+            exprtk_define_epsilon_type(double     , 0.000000000100)
+            exprtk_define_epsilon_type(long double, 0.000000000001)
+
+            #undef exprtk_define_epsilon_type
 
             template <typename T>
             inline bool is_nan_impl(const T v, real_type_tag)
@@ -859,6 +893,12 @@ namespace exprtk
                return static_cast<_int64_t>(v);
             }
 
+            template <typename T>
+            inline _uint64_t to_uint64_impl(const T v, real_type_tag)
+            {
+               return static_cast<_uint64_t>(v);
+            }
+
             template <typename T>
             inline bool is_true_impl(const T v)
             {
@@ -993,8 +1033,8 @@ namespace exprtk
                   else
                      return (T(-0.5) * v + T(1)) * v;
                }
-               else
-                  return std::numeric_limits<T>::quiet_NaN();
+
+               return std::numeric_limits<T>::quiet_NaN();
             }
 
             template <typename T>
@@ -1004,8 +1044,8 @@ namespace exprtk
                {
                   return std::log(T(1) + v);
                }
-               else
-                  return std::numeric_limits<T>::quiet_NaN();
+
+               return std::numeric_limits<T>::quiet_NaN();
             }
 
             template <typename T>
@@ -1103,7 +1143,7 @@ namespace exprtk
             template <typename T>
             inline T sgn_impl(const T v, real_type_tag)
             {
-                    if (v > T(0)) return T(+1);
+               if      (v > T(0)) return T(+1);
                else if (v < T(0)) return T(-1);
                else               return T( 0);
             }
@@ -1111,7 +1151,7 @@ namespace exprtk
             template <typename T>
             inline T sgn_impl(const T v, int_type_tag)
             {
-                    if (v > T(0)) return T(+1);
+               if      (v > T(0)) return T(+1);
                else if (v < T(0)) return T(-1);
                else               return T( 0);
             }
@@ -1201,36 +1241,37 @@ namespace exprtk
             }
 
             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
-            #define exprtk_define_erf(TT,impl)           \
-            inline TT erf_impl(TT v) { return impl(v); } \
+            #define exprtk_define_erf(TT, impl)                \
+            inline TT erf_impl(const TT v) { return impl(v); } \
 
-            exprtk_define_erf(      float,::erff)
-            exprtk_define_erf(     double,::erf )
-            exprtk_define_erf(long double,::erfl)
+            exprtk_define_erf(float      , ::erff)
+            exprtk_define_erf(double     , ::erf )
+            exprtk_define_erf(long double, ::erfl)
             #undef exprtk_define_erf
             #endif
 
             template <typename T>
-            inline T erf_impl(T v, real_type_tag)
+            inline T erf_impl(const T v, real_type_tag)
             {
                #if defined(_MSC_VER) && (_MSC_VER < 1900)
                // Credits: Abramowitz & Stegun Equations 7.1.25-28
-               static const T c[] = {
-                                      T( 1.26551223), T(1.00002368),
-                                      T( 0.37409196), T(0.09678418),
-                                      T(-0.18628806), T(0.27886807),
-                                      T(-1.13520398), T(1.48851587),
-                                      T(-0.82215223), T(0.17087277)
-                                    };
+               static const T c[] =
+               {
+                  T( 1.26551223), T(1.00002368),
+                  T( 0.37409196), T(0.09678418),
+                  T(-0.18628806), T(0.27886807),
+                  T(-1.13520398), T(1.48851587),
+                  T(-0.82215223), T(0.17087277)
+               };
 
                const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
 
-               T result = T(1) - t * std::exp((-v * v) -
-                                      c[0] + t * (c[1] + t *
-                                     (c[2] + t * (c[3] + t *
-                                     (c[4] + t * (c[5] + t *
-                                     (c[6] + t * (c[7] + t *
-                                     (c[8] + t * (c[9]))))))))));
+               const T result = T(1) - t * std::exp((-v * v) -
+                                            c[0] + t * (c[1] + t *
+                                           (c[2] + t * (c[3] + t *
+                                           (c[4] + t * (c[5] + t *
+                                           (c[6] + t * (c[7] + t *
+                                           (c[8] + t * (c[9]))))))))));
 
                return (v >= T(0)) ? result : -result;
                #else
@@ -1239,23 +1280,23 @@ namespace exprtk
             }
 
             template <typename T>
-            inline T erf_impl(T v, int_type_tag)
+            inline T erf_impl(const T v, int_type_tag)
             {
                return erf_impl(static_cast<double>(v),real_type_tag());
             }
 
             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
-            #define exprtk_define_erfc(TT,impl)           \
-            inline TT erfc_impl(TT v) { return impl(v); } \
+            #define exprtk_define_erfc(TT, impl)                \
+            inline TT erfc_impl(const TT v) { return impl(v); } \
 
-            exprtk_define_erfc(      float,::erfcf)
-            exprtk_define_erfc(     double,::erfc )
+            exprtk_define_erfc(float      ,::erfcf)
+            exprtk_define_erfc(double     ,::erfc )
             exprtk_define_erfc(long double,::erfcl)
             #undef exprtk_define_erfc
             #endif
 
             template <typename T>
-            inline T erfc_impl(T v, real_type_tag)
+            inline T erfc_impl(const T v, real_type_tag)
             {
                #if defined(_MSC_VER) && (_MSC_VER < 1900)
                return T(1) - erf_impl(v,real_type_tag());
@@ -1265,28 +1306,25 @@ namespace exprtk
             }
 
             template <typename T>
-            inline T erfc_impl(T v, int_type_tag)
+            inline T erfc_impl(const T v, int_type_tag)
             {
                return erfc_impl(static_cast<double>(v),real_type_tag());
             }
 
             template <typename T>
-            inline T ncdf_impl(T v, real_type_tag)
+            inline T ncdf_impl(const T v, real_type_tag)
             {
-               T cnd = T(0.5) * (T(1) + erf_impl(
-                                           abs_impl(v,real_type_tag()) /
-                                           T(numeric::constant::sqrt2),real_type_tag()));
-               return  (v < T(0)) ? (T(1) - cnd) : cnd;
+               return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag());
             }
 
             template <typename T>
-            inline T ncdf_impl(T v, int_type_tag)
+            inline T ncdf_impl(const T v, int_type_tag)
             {
                return ncdf_impl(static_cast<double>(v),real_type_tag());
             }
 
             template <typename T>
-            inline T sinc_impl(T v, real_type_tag)
+            inline T sinc_impl(const T v, real_type_tag)
             {
                if (std::abs(v) >= std::numeric_limits<T>::epsilon())
                    return(std::sin(v) / v);
@@ -1295,17 +1333,52 @@ namespace exprtk
             }
 
             template <typename T>
-            inline T sinc_impl(T v, int_type_tag)
+            inline T sinc_impl(const T v, int_type_tag)
             {
                return sinc_impl(static_cast<double>(v),real_type_tag());
             }
 
+            #if __cplusplus >= 201103L
+            template <typename T>
+            inline T acosh_impl(const T v, real_type_tag)
+            {
+               return std::acosh(v);
+            }
+
+            template <typename T>
+            inline T asinh_impl(const T v, real_type_tag)
+            {
+               return std::asinh(v);
+            }
+
+            template <typename T>
+            inline T atanh_impl(const T v, real_type_tag)
+            {
+               return std::atanh(v);
+            }
+            #else
+            template <typename T>
+            inline T acosh_impl(const T v, real_type_tag)
+            {
+               return std::log(v + std::sqrt((v * v) - T(1)));
+            }
+
+            template <typename T>
+            inline T asinh_impl(const T v, real_type_tag)
+            {
+               return std::log(v + std::sqrt((v * v) + T(1)));
+            }
+
+            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);
+            }
+            #endif
+
             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
-            template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
-            template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
-            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); }
             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
@@ -1326,14 +1399,15 @@ namespace exprtk
             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
-            template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
-            template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
+            template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); }
+            template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); }
             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)); }
             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
 
-            template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
-            template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e);  }
+            template <typename T> inline T   const_pi_impl(real_type_tag) { return T(numeric::constant::pi);            }
+            template <typename T> inline T    const_e_impl(real_type_tag) { return T(numeric::constant::e);             }
+            template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
 
             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
@@ -1381,10 +1455,10 @@ namespace exprtk
          template <typename Type>
          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
 
-         template <> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length = 9}; };
-         template <> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
-         template <> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
-         template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
+         template <> struct numeric_info<int        > { enum { length = 10, size = 16, bound_length = 9 }; };
+         template <> struct numeric_info<float      > { enum { min_exp =  -38, max_exp =  +38 }; };
+         template <> struct numeric_info<double     > { enum { min_exp = -308, max_exp = +308 }; };
+         template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; };
 
          template <typename T>
          inline int to_int32(const T v)
@@ -1400,6 +1474,13 @@ namespace exprtk
             return to_int64_impl(v, num_type);
          }
 
+         template <typename T>
+         inline _uint64_t to_uint64(const T v)
+         {
+            const typename details::number_type<T>::type num_type;
+            return to_uint64_impl(v, num_type);
+         }
+
          template <typename T>
          inline bool is_nan(const T v)
          {
@@ -1557,31 +1638,31 @@ namespace exprtk
 
                while (k)
                {
-                  if (k & 1)
+                  if (1 == (k % 2))
                   {
                      l *= v;
                      --k;
                   }
 
                   v *= v;
-                  k >>= 1;
+                  k /= 2;
                }
 
                return l;
             }
          };
 
-         template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
-         template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
-         template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
-         template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
-         template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
-         template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
-         template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
-         template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
-         template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
-         template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
-         template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
+         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; } };
+         template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } };
+         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; } };
+         template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } };
+         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; } };
+         template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } };
+         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; } };
+         template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } };
+         template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v;     } };
+         template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v;         } };
+         template <typename T> struct fast_exp<T, 0> { static inline T result(const T  ) { return T(1);      } };
 
          #define exprtk_define_unary_function(FunctionName)        \
          template <typename T>                                     \
@@ -1639,38 +1720,38 @@ namespace exprtk
       {
          static const double fract10[] =
          {
-           0.0,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           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,
-           1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
+            0.0,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            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,
+            1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
          };
 
          static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
@@ -1716,11 +1797,10 @@ namespace exprtk
 
          bool return_result = true;
          unsigned int digit = 0;
-         const std::size_t length  = static_cast<std::size_t>(std::distance(itr,end));
+         const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
 
          if (length <= 4)
          {
-            exprtk_disable_fallthrough_begin
             switch (length)
             {
                #ifdef exprtk_use_lut
@@ -1733,28 +1813,33 @@ namespace exprtk
                   return_result = false;                             \
                   break;                                             \
                }                                                     \
+               exprtk_fallthrough                                    \
 
                #else
 
-               #define exprtk_process_digit         \
-               if ((digit = (*itr++ - zero)) < 10)  \
-                  result = result * T(10) + digit;  \
-               else                                 \
-               {                                    \
-                  return_result = false;            \
-                  break;                            \
-               }                                    \
+               #define exprtk_process_digit        \
+               if ((digit = (*itr++ - zero)) < 10) \
+                  result = result * T(10) + digit; \
+               else                                \
+               {                                   \
+                  return_result = false;           \
+                  break;                           \
+               }                                   \
+               exprtk_fallthrough                  \
 
                #endif
 
-               case  4 : exprtk_process_digit
-               case  3 : exprtk_process_digit
-               case  2 : exprtk_process_digit
-               case  1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
+               case 4 : exprtk_process_digit
+               case 3 : exprtk_process_digit
+               case 2 : exprtk_process_digit
+               case 1 : if ((digit = (*itr - zero))>= 10)
+                        {
+                           digit = 0;
+                           return_result = false;
+                        }
 
                #undef exprtk_process_digit
             }
-            exprtk_disable_fallthrough_end
          }
          else
             return_result = false;
@@ -1803,7 +1888,7 @@ namespace exprtk
       }
 
       template <typename Iterator, typename T>
-      static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
+      static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative)
       {
          static const char_t inf_uc[] = "INFINITY";
          static const char_t inf_lc[] = "infinity";
@@ -1818,7 +1903,7 @@ namespace exprtk
 
          while (end != itr)
          {
-            if (*inf_itr == static_cast<char>(*itr))
+            if (*inf_itr == static_cast<char_t>(*itr))
             {
                ++itr;
                ++inf_itr;
@@ -1839,8 +1924,8 @@ namespace exprtk
       template <typename T>
       inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
       {
-         return (std::numeric_limits<T>::min_exponent10 <= exponent) &&
-                (exponent <= std::numeric_limits<T>::max_exponent10) ;
+         using namespace details::numeric;
+         return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp);
       }
 
       template <typename Iterator, typename T>
@@ -1874,7 +1959,8 @@ namespace exprtk
          #define parse_digit_2(d)          \
          if ((digit = (*itr - zero)) < 10) \
             { d = d * T(10) + digit; }     \
-         else { break; }                   \
+         else                              \
+            { break; }                     \
             ++itr;                         \
 
          if ('.' != (*itr))
@@ -1885,14 +1971,7 @@ namespace exprtk
 
             while (end != itr)
             {
-               // Note: For 'physical' superscalar architectures it
-               // is advised that the following loop be: 4xPD1 and 1xPD2
                unsigned int digit;
-
-               #ifdef exprtk_enable_superscalar
-               parse_digit_1(d)
-               parse_digit_1(d)
-               #endif
                parse_digit_1(d)
                parse_digit_1(d)
                parse_digit_2(d)
@@ -1913,12 +1992,6 @@ namespace exprtk
                while (end != itr)
                {
                   unsigned int digit;
-
-                  #ifdef exprtk_enable_superscalar
-                  parse_digit_1(tmp_d)
-                  parse_digit_1(tmp_d)
-                  parse_digit_1(tmp_d)
-                  #endif
                   parse_digit_1(tmp_d)
                   parse_digit_1(tmp_d)
                   parse_digit_2(tmp_d)
@@ -1928,12 +2001,12 @@ namespace exprtk
                {
                   instate = true;
 
-                  const int exponent = static_cast<int>(-std::distance(curr, itr));
+                  const int frac_exponent = static_cast<int>(-std::distance(curr, itr));
 
-                  if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
+                  if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag()))
                      return false;
 
-                  d += compute_pow10(tmp_d, exponent);
+                  d += compute_pow10(tmp_d, frac_exponent);
                }
 
                #undef parse_digit_1
@@ -2065,8 +2138,8 @@ namespace exprtk
       loop_types loop_set;
 
       loop_runtime_check()
-      : loop_set(e_invalid),
-        max_loop_iterations(0)
+      : loop_set(e_invalid)
+      , max_loop_iterations(0)
       {}
 
       details::_uint64_t max_loop_iterations;
@@ -2078,16 +2151,81 @@ namespace exprtk
          details::_uint64_t iteration_count;
       };
 
+      virtual bool check()
+      {
+         return true;
+      }
+
       virtual void handle_runtime_violation(const violation_context&)
       {
-         throw std::runtime_error("ExprTk Loop run-time violation.");
+         throw std::runtime_error("ExprTk Loop runtime violation.");
       }
 
-      virtual ~loop_runtime_check() {}
+      virtual ~loop_runtime_check()
+      {}
    };
 
    typedef loop_runtime_check* loop_runtime_check_ptr;
 
+   struct vector_access_runtime_check
+   {
+      struct violation_context
+      {
+         void* base_ptr;
+         void* end_ptr;
+         void* access_ptr;
+         std::size_t type_size;
+      };
+
+      virtual ~vector_access_runtime_check()
+      {}
+
+      virtual bool handle_runtime_violation(violation_context& /*context*/)
+      {
+         throw std::runtime_error("ExprTk runtime vector access violation.");
+         #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
+         return false;
+         #endif
+      }
+   };
+
+   typedef vector_access_runtime_check* vector_access_runtime_check_ptr;
+
+   struct assert_check
+   {
+      struct assert_context
+      {
+         std::string condition;
+         std::string message;
+         std::string id;
+         std::size_t offet;
+      };
+
+      virtual ~assert_check()
+      {}
+
+      virtual void handle_assert(const assert_context& /*context*/)
+      {
+      }
+   };
+
+   typedef assert_check* assert_check_ptr;
+
+   struct compilation_check
+   {
+      struct compilation_context
+      {
+         std::string error_message;
+      };
+
+      virtual bool continue_compilation(compilation_context& /*context*/) = 0;
+
+      virtual ~compilation_check()
+      {}
+   };
+
+   typedef compilation_check* compilation_check_ptr;
+
    namespace lexer
    {
       struct token
@@ -2111,9 +2249,9 @@ namespace exprtk
          };
 
          token()
-         : type(e_none),
-           value(""),
-           position(std::numeric_limits<std::size_t>::max())
+         : type(e_none)
+         , value("")
+         , position(std::numeric_limits<std::size_t>::max())
          {}
 
          void clear()
@@ -2246,6 +2384,19 @@ namespace exprtk
             }
          }
 
+         static inline std::string seperator_to_str(const token_type t)
+         {
+            switch (t)
+            {
+               case e_comma : return ",";
+               case e_colon : return ":";
+               case e_eof   : return ";";
+               default      : return "UNKNOWN";
+            }
+
+            return "UNKNOWN";
+         }
+
          inline bool is_error() const
          {
             return (
@@ -2272,9 +2423,9 @@ namespace exprtk
          typedef details::char_t char_t;
 
          generator()
-         : base_itr_(0),
-           s_itr_   (0),
-           s_end_   (0)
+         : base_itr_(0)
+         , s_itr_   (0)
+         , s_end_   (0)
          {
             clear();
          }
@@ -2295,7 +2446,7 @@ namespace exprtk
             s_itr_    = str.data();
             s_end_    = str.data() + str.size();
 
-            eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
+            eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_);
             token_list_.clear();
 
             while (!is_end(s_itr_))
@@ -2358,7 +2509,9 @@ namespace exprtk
          inline token_t& operator[](const std::size_t& index)
          {
             if (index < token_list_.size())
+            {
                return token_list_[index];
+            }
             else
                return eof_token_;
          }
@@ -2366,7 +2519,9 @@ namespace exprtk
          inline token_t operator[](const std::size_t& index) const
          {
             if (index < token_list_.size())
+            {
                return token_list_[index];
+            }
             else
                return eof_token_;
          }
@@ -2390,10 +2545,10 @@ namespace exprtk
             }
          }
 
-         inline std::string substr(const std::size_t& begin, const std::size_t& end)
+         inline std::string substr(const std::size_t& begin, const std::size_t& end) const
          {
             const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
-            const details::char_cptr end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
+            const details::char_cptr end_itr   = ((base_itr_ + end  ) < s_end_) ? (base_itr_ + end  ) : s_end_;
 
             return std::string(begin_itr,end_itr);
          }
@@ -2410,13 +2565,13 @@ namespace exprtk
 
       private:
 
-         inline bool is_end(details::char_cptr itr)
+         inline bool is_end(details::char_cptr itr) const
          {
             return (s_end_ == itr);
          }
 
          #ifndef exprtk_disable_comments
-         inline bool is_comment_start(details::char_cptr itr)
+         inline bool is_comment_start(details::char_cptr itr) const
          {
             const char_t c0 = *(itr + 0);
             const char_t c1 = *(itr + 1);
@@ -2431,7 +2586,7 @@ namespace exprtk
             return false;
          }
          #else
-         inline bool is_comment_start(details::char_cptr)
+         inline bool is_comment_start(details::char_cptr) const
          {
             return false;
          }
@@ -2457,10 +2612,10 @@ namespace exprtk
                static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
                {
                   mode = 0;
-                       if ('#' == c0)    { mode = 1; incr = 1; }
+                  if      ('#' == c0)    { mode = 1; incr = 1; }
                   else if ('/' == c0)
                   {
-                          if ('/' == c1) { mode = 1; incr = 2; }
+                     if      ('/' == c1) { mode = 1; incr = 2; }
                      else if ('*' == c1) { mode = 2; incr = 2; }
                   }
                   return (0 != mode);
@@ -2510,7 +2665,7 @@ namespace exprtk
                   }
                }
 
-                ++s_itr_;
+               ++s_itr_;
             }
 
             if (2 == mode)
@@ -2522,9 +2677,17 @@ namespace exprtk
             #endif
          }
 
+         inline bool next_is_digit(const details::char_cptr itr) const
+         {
+            return ((itr + 1) != s_end_) &&
+                   details::is_digit(*(itr + 1));
+         }
+
          inline void scan_token()
          {
-            if (details::is_whitespace(*s_itr_))
+            const char_t c = *s_itr_;
+
+            if (details::is_whitespace(c))
             {
                skip_whitespace();
                return;
@@ -2534,34 +2697,39 @@ namespace exprtk
                skip_comments();
                return;
             }
-            else if (details::is_operator_char(*s_itr_))
+            else if (details::is_operator_char(c))
             {
                scan_operator();
                return;
             }
-            else if (details::is_letter(*s_itr_))
+            else if (details::is_letter(c))
             {
                scan_symbol();
                return;
             }
-            else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
+            else if (('.' == c) && !next_is_digit(s_itr_))
+            {
+               scan_operator();
+               return;
+            }
+            else if (details::is_digit(c) || ('.' == c))
             {
                scan_number();
                return;
             }
-            else if ('$' == (*s_itr_))
+            else if ('$' == c)
             {
                scan_special_function();
                return;
             }
             #ifndef exprtk_disable_string_capabilities
-            else if ('\'' == (*s_itr_))
+            else if ('\'' == c)
             {
                scan_string();
                return;
             }
             #endif
-            else if ('~' == (*s_itr_))
+            else if ('~' == c)
             {
                token_t t;
                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
@@ -2603,7 +2771,7 @@ namespace exprtk
 
                token_t::token_type ttype = token_t::e_none;
 
-                    if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
+               if      ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
@@ -2671,7 +2839,7 @@ namespace exprtk
             }
 
             token_t t;
-            t.set_symbol(initial_itr,s_itr_,base_itr_);
+            t.set_symbol(initial_itr, s_itr_, base_itr_);
             token_list_.push_back(t);
          }
 
@@ -2871,12 +3039,12 @@ namespace exprtk
                        ((s_itr_ + 4) <= s_end_)
                      )
                   {
-                     const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1)));
+                     const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1)));
 
                      const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
                                               details::is_hex_digit(*(s_itr_ + 3)) ;
 
-                     if (!(x_seperator && both_digits))
+                     if (!(x_separator && both_digits))
                      {
                         t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
                         token_list_.push_back(t);
@@ -2916,8 +3084,8 @@ namespace exprtk
                }
 
                t.set_string(
-                    parsed_string,
-                    static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
+                  parsed_string,
+                  static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
             }
 
             token_list_.push_back(t);
@@ -2941,7 +3109,7 @@ namespace exprtk
          friend class token_modifier;
          friend class token_inserter;
          friend class token_joiner;
-      };
+      }; // class generator
 
       class helper_interface
       {
@@ -2970,7 +3138,7 @@ namespace exprtk
             }
          }
 
-         inline std::size_t process(generator& g)
+         inline std::size_t process(generator& g) exprtk_override
          {
             if (g.token_list_.size() >= stride_)
             {
@@ -2986,7 +3154,7 @@ namespace exprtk
 
                                  if (!operator()(t0))
                                  {
-                                    return i;
+                                    return 0;
                                  }
                               }
                               break;
@@ -2998,7 +3166,7 @@ namespace exprtk
 
                                  if (!operator()(t0, t1))
                                  {
-                                    return i;
+                                    return 0;
                                  }
                               }
                               break;
@@ -3011,7 +3179,7 @@ namespace exprtk
 
                                  if (!operator()(t0, t1, t2))
                                  {
-                                    return i;
+                                    return 0;
                                  }
                               }
                               break;
@@ -3025,7 +3193,7 @@ namespace exprtk
 
                                  if (!operator()(t0, t1, t2, t3))
                                  {
-                                    return i;
+                                    return 0;
                                  }
                               }
                               break;
@@ -3033,7 +3201,7 @@ namespace exprtk
                }
             }
 
-            return (g.token_list_.size() - stride_ + 1);
+            return 0;
          }
 
          virtual bool operator() (const token&)
@@ -3059,13 +3227,13 @@ namespace exprtk
       private:
 
          const std::size_t stride_;
-      };
+      }; // class token_scanner
 
       class token_modifier : public helper_interface
       {
       public:
 
-         inline std::size_t process(generator& g)
+         inline std::size_t process(generator& g) exprtk_override
          {
             std::size_t changes = 0;
 
@@ -3093,7 +3261,7 @@ namespace exprtk
             }
          }
 
-         inline std::size_t process(generator& g)
+         inline std::size_t process(generator& g) exprtk_override
          {
             if (g.token_list_.empty())
                return 0;
@@ -3197,7 +3365,7 @@ namespace exprtk
          : stride_(stride)
          {}
 
-         inline std::size_t process(generator& g)
+         inline std::size_t process(generator& g) exprtk_override
          {
             if (g.token_list_.empty())
                return 0;
@@ -3225,7 +3393,7 @@ namespace exprtk
             generator::token_list_t token_list;
             token_list.reserve(10000);
 
-            for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 1); ++i)
+            for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
             {
                token t;
 
@@ -3241,15 +3409,17 @@ namespace exprtk
 
                   ++changes;
 
-                  i+=2;
+                  i += 2;
 
-                  if (static_cast<std::size_t>(i) >= g.token_list_.size())
+                  if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1))
                      break;
                }
             }
 
             token_list.push_back(g.token_list_.back());
 
+            assert(token_list.size() <= g.token_list_.size());
+
             std::swap(token_list, g.token_list_);
 
             return changes;
@@ -3265,7 +3435,7 @@ namespace exprtk
             generator::token_list_t token_list;
             token_list.reserve(10000);
 
-            for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 2); ++i)
+            for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
             {
                token t;
 
@@ -3281,9 +3451,9 @@ namespace exprtk
 
                   ++changes;
 
-                  i+=3;
+                  i += 3;
 
-                  if (static_cast<std::size_t>(i) >= g.token_list_.size())
+                  if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2))
                      break;
                }
             }
@@ -3291,6 +3461,8 @@ namespace exprtk
             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
 
+            assert(token_list.size() <= g.token_list_.size());
+
             std::swap(token_list, g.token_list_);
 
             return changes;
@@ -3330,7 +3502,7 @@ namespace exprtk
                ignore_set_.insert(symbol);
             }
 
-            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
+            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override
             {
                bool match         = false;
                new_token.type     = lexer::token::e_mul;
@@ -3356,7 +3528,7 @@ namespace exprtk
                      return -1;
                   }
                }
-                    if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
+               if      ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
@@ -3377,7 +3549,7 @@ namespace exprtk
             std::set<std::string,details::ilesscompare> ignore_set_;
          };
 
-         class operator_joiner : public token_joiner
+         class operator_joiner exprtk_final : public token_joiner
          {
          public:
 
@@ -3385,7 +3557,7 @@ namespace exprtk
             : token_joiner(stride)
             {}
 
-            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
+            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override
             {
                // ': =' --> ':='
                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
@@ -3469,7 +3641,7 @@ namespace exprtk
                   return true;
                }
                // '! =' --> '!='
-               else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
+               else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
                {
                   t.type     = lexer::token::e_ne;
                   t.value    = "!=";
@@ -3530,7 +3702,10 @@ namespace exprtk
                   return false;
             }
 
-            inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
+            inline bool join(const lexer::token& t0,
+                             const lexer::token& t1,
+                             const lexer::token& t2,
+                             lexer::token& t) exprtk_override
             {
                // '[ * ]' --> '[*]'
                if (
@@ -3550,18 +3725,18 @@ namespace exprtk
             }
          };
 
-         class bracket_checker : public lexer::token_scanner
+         class bracket_checker exprtk_final : public lexer::token_scanner
          {
          public:
 
             using lexer::token_scanner::operator();
 
             bracket_checker()
-            : token_scanner(1),
-              state_(true)
+            : token_scanner(1)
+            , state_(true)
             {}
 
-            bool result()
+            bool result() exprtk_override
             {
                if (!stack_.empty())
                {
@@ -3582,7 +3757,7 @@ namespace exprtk
                return error_token_;
             }
 
-            void reset()
+            void reset() exprtk_override
             {
                // Why? because msvc doesn't support swap properly.
                stack_ = std::stack<std::pair<char,std::size_t> >();
@@ -3590,7 +3765,7 @@ namespace exprtk
                error_token_.clear();
             }
 
-            bool operator() (const lexer::token& t)
+            bool operator() (const lexer::token& t) exprtk_override
             {
                if (
                     !t.value.empty()                       &&
@@ -3601,7 +3776,7 @@ namespace exprtk
                {
                   details::char_t c = t.value[0];
 
-                       if (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));
+                  if      (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));
                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
                   else if (exprtk::details::is_right_bracket(c))
@@ -3635,33 +3810,34 @@ namespace exprtk
             lexer::token error_token_;
          };
 
-         class numeric_checker : public lexer::token_scanner
+         template <typename T>
+         class numeric_checker exprtk_final : public lexer::token_scanner
          {
          public:
 
             using lexer::token_scanner::operator();
 
             numeric_checker()
-            : token_scanner (1),
-              current_index_(0)
+            : token_scanner (1)
+            , current_index_(0)
             {}
 
-            bool result()
+            bool result() exprtk_override
             {
                return error_list_.empty();
             }
 
-            void reset()
+            void reset() exprtk_override
             {
                error_list_.clear();
                current_index_ = 0;
             }
 
-            bool operator() (const lexer::token& t)
+            bool operator() (const lexer::token& t) exprtk_override
             {
                if (token::e_number == t.type)
                {
-                  double v;
+                  T v;
 
                   if (!exprtk::details::string_to_real(t.value,v))
                   {
@@ -3698,7 +3874,7 @@ namespace exprtk
             std::vector<std::size_t> error_list_;
          };
 
-         class symbol_replacer : public lexer::token_modifier
+         class symbol_replacer exprtk_final : public lexer::token_modifier
          {
          private:
 
@@ -3741,7 +3917,7 @@ namespace exprtk
 
          private:
 
-            bool modify(lexer::token& t)
+            bool modify(lexer::token& t) exprtk_override
             {
                if (lexer::token::e_symbol == t.type)
                {
@@ -3765,7 +3941,7 @@ namespace exprtk
             replace_map_t replace_map_;
          };
 
-         class sequence_validator : public lexer::token_scanner
+         class sequence_validator exprtk_final : public lexer::token_scanner
          {
          private:
 
@@ -3804,12 +3980,12 @@ namespace exprtk
                add_invalid_set1(lexer::token::e_ternary);
             }
 
-            bool result()
+            bool result() exprtk_override
             {
                return error_list_.empty();
             }
 
-            bool operator() (const lexer::token& t0, const lexer::token& t1)
+            bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override
             {
                const set_t::value_type p = std::make_pair(t0.type,t1.type);
 
@@ -3850,12 +4026,12 @@ namespace exprtk
 
          private:
 
-            void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
+            void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t)
             {
                invalid_comb_.insert(std::make_pair(base,t));
             }
 
-            void add_invalid_set1(lexer::token::token_type t)
+            void add_invalid_set1(const lexer::token::token_type t)
             {
                add_invalid(t, lexer::token::e_assign);
                add_invalid(t, lexer::token::e_shr   );
@@ -3874,9 +4050,9 @@ namespace exprtk
                add_invalid(t, lexer::token::e_colon );
             }
 
-            bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
+            bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t)
             {
-               if (details::is_right_bracket(static_cast<char>(base)))
+               if (details::is_right_bracket(static_cast<details::char_t>(base)))
                {
                   switch (t)
                   {
@@ -3885,11 +4061,11 @@ namespace exprtk
                      default                     : return false;
                   }
                }
-               else if (details::is_left_bracket(static_cast<char>(base)))
+               else if (details::is_left_bracket(static_cast<details::char_t>(base)))
                {
-                  if (details::is_right_bracket(static_cast<char>(t)))
+                  if (details::is_right_bracket(static_cast<details::char_t>(t)))
                      return false;
-                  else if (details::is_left_bracket(static_cast<char>(t)))
+                  else if (details::is_left_bracket(static_cast<details::char_t>(t)))
                      return false;
                   else
                   {
@@ -3906,7 +4082,7 @@ namespace exprtk
                      }
                   }
                }
-               else if (details::is_right_bracket(static_cast<char>(t)))
+               else if (details::is_right_bracket(static_cast<details::char_t>(t)))
                {
                   switch (base)
                   {
@@ -3919,7 +4095,7 @@ namespace exprtk
                      default                      : return true ;
                   }
                }
-               else if (details::is_left_bracket(static_cast<char>(t)))
+               else if (details::is_left_bracket(static_cast<details::char_t>(t)))
                {
                   switch (base)
                   {
@@ -3937,7 +4113,7 @@ namespace exprtk
             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
          };
 
-         class sequence_validator_3tokens : public lexer::token_scanner
+         class sequence_validator_3tokens exprtk_final : public lexer::token_scanner
          {
          private:
 
@@ -3952,31 +4128,31 @@ namespace exprtk
             sequence_validator_3tokens()
             : lexer::token_scanner(3)
             {
-               add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
-               add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
-               add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
+               add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number);
+               add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string);
+               add_invalid(lexer::token::e_comma  , lexer::token::e_comma  , lexer::token::e_comma );
 
-               add_invalid(lexer::token::e_add   , lexer::token::e_add   , lexer::token::e_add   );
-               add_invalid(lexer::token::e_sub   , lexer::token::e_sub   , lexer::token::e_sub   );
-               add_invalid(lexer::token::e_div   , lexer::token::e_div   , lexer::token::e_div   );
-               add_invalid(lexer::token::e_mul   , lexer::token::e_mul   , lexer::token::e_mul   );
-               add_invalid(lexer::token::e_mod   , lexer::token::e_mod   , lexer::token::e_mod   );
-               add_invalid(lexer::token::e_pow   , lexer::token::e_pow   , lexer::token::e_pow   );
+               add_invalid(lexer::token::e_add    , lexer::token::e_add    , lexer::token::e_add   );
+               add_invalid(lexer::token::e_sub    , lexer::token::e_sub    , lexer::token::e_sub   );
+               add_invalid(lexer::token::e_div    , lexer::token::e_div    , lexer::token::e_div   );
+               add_invalid(lexer::token::e_mul    , lexer::token::e_mul    , lexer::token::e_mul   );
+               add_invalid(lexer::token::e_mod    , lexer::token::e_mod    , lexer::token::e_mod   );
+               add_invalid(lexer::token::e_pow    , lexer::token::e_pow    , lexer::token::e_pow   );
 
-               add_invalid(lexer::token::e_add   , lexer::token::e_sub   , lexer::token::e_add   );
-               add_invalid(lexer::token::e_sub   , lexer::token::e_add   , lexer::token::e_sub   );
-               add_invalid(lexer::token::e_div   , lexer::token::e_mul   , lexer::token::e_div   );
-               add_invalid(lexer::token::e_mul   , lexer::token::e_div   , lexer::token::e_mul   );
-               add_invalid(lexer::token::e_mod   , lexer::token::e_pow   , lexer::token::e_mod   );
-               add_invalid(lexer::token::e_pow   , lexer::token::e_mod   , lexer::token::e_pow   );
+               add_invalid(lexer::token::e_add    , lexer::token::e_sub    , lexer::token::e_add   );
+               add_invalid(lexer::token::e_sub    , lexer::token::e_add    , lexer::token::e_sub   );
+               add_invalid(lexer::token::e_div    , lexer::token::e_mul    , lexer::token::e_div   );
+               add_invalid(lexer::token::e_mul    , lexer::token::e_div    , lexer::token::e_mul   );
+               add_invalid(lexer::token::e_mod    , lexer::token::e_pow    , lexer::token::e_mod   );
+               add_invalid(lexer::token::e_pow    , lexer::token::e_mod    , lexer::token::e_pow   );
             }
 
-            bool result()
+            bool result() exprtk_override
             {
                return error_list_.empty();
             }
 
-            bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
+            bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override
             {
                const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
 
@@ -4013,7 +4189,7 @@ namespace exprtk
 
          private:
 
-            void add_invalid(token_t t0, token_t t1, token_t t2)
+            void add_invalid(const token_t t0, const token_t t1, const token_t t2)
             {
                invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
             }
@@ -4184,7 +4360,7 @@ namespace exprtk
       {
       public:
 
-         typedef token         token_t;
+         typedef token     token_t;
          typedef generator generator_t;
 
          inline bool init(const std::string& str)
@@ -4233,6 +4409,11 @@ namespace exprtk
             return current_token_;
          }
 
+         inline const token_t& peek_next_token()
+         {
+            return lexer_.peek_next_token();
+         }
+
          enum token_advance_mode
          {
             e_hold    = 0,
@@ -4276,6 +4457,110 @@ namespace exprtk
             return true;
          }
 
+         inline bool token_is(const std::string& value,
+                              const token_advance_mode mode = e_advance)
+         {
+            if (!exprtk::details::imatch(value,current_token().value))
+            {
+               return false;
+            }
+
+            advance_token(mode);
+
+            return true;
+         }
+
+         inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance)
+         {
+            switch (current_token().type)
+            {
+               case token_t::e_add :
+               case token_t::e_sub :
+               case token_t::e_div :
+               case token_t::e_mul :
+               case token_t::e_mod :
+               case token_t::e_pow : break;
+               default             : return false;
+            }
+
+            advance_token(mode);
+
+            return true;
+         }
+
+         inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance)
+         {
+            switch (current_token().type)
+            {
+               case token_t::e_eq  :
+               case token_t::e_lte :
+               case token_t::e_ne  :
+               case token_t::e_gte :
+               case token_t::e_lt  :
+               case token_t::e_gt  : break;
+               default             : return false;
+            }
+
+            advance_token(mode);
+
+            return true;
+         }
+
+         inline bool token_is_left_bracket(const token_advance_mode mode = e_advance)
+         {
+            switch (current_token().type)
+            {
+               case token_t::e_lbracket    :
+               case token_t::e_lcrlbracket :
+               case token_t::e_lsqrbracket : break;
+               default                     : return false;
+            }
+
+            advance_token(mode);
+
+            return true;
+         }
+
+         inline bool token_is_right_bracket(const token_advance_mode mode = e_advance)
+         {
+            switch (current_token().type)
+            {
+               case token_t::e_rbracket    :
+               case token_t::e_rcrlbracket :
+               case token_t::e_rsqrbracket : break;
+               default                     : return false;
+            }
+
+            advance_token(mode);
+
+            return true;
+         }
+
+         inline bool token_is_bracket(const token_advance_mode mode = e_advance)
+         {
+            switch (current_token().type)
+            {
+               case token_t::e_rbracket    :
+               case token_t::e_rcrlbracket :
+               case token_t::e_rsqrbracket :
+               case token_t::e_lbracket    :
+               case token_t::e_lcrlbracket :
+               case token_t::e_lsqrbracket : break;
+               default                     : return false;
+            }
+
+            advance_token(mode);
+
+            return true;
+         }
+
+         inline bool token_is_loop(const token_advance_mode mode = e_advance)
+         {
+            return token_is("for"   , mode) ||
+                   token_is("while" , mode) ||
+                   token_is("repeat", mode) ;
+         }
+
          inline bool peek_token_is(const token_t::token_type& ttype)
          {
             return (lexer_.peek_next_token().type == ttype);
@@ -4302,16 +4587,22 @@ namespace exprtk
       typedef T* data_ptr_t;
 
       vector_view(data_ptr_t data, const std::size_t& size)
-      : size_(size),
-        data_(data),
-        data_ref_(0)
-      {}
+      : base_size_(size)
+      , size_(size)
+      , data_(data)
+      , data_ref_(0)
+      {
+         assert(size_ > 0);
+      }
 
       vector_view(const vector_view<T>& vv)
-      : size_(vv.size_),
-        data_(vv.data_),
-        data_ref_(0)
-      {}
+      : base_size_(vv.base_size_)
+      , size_(vv.size_)
+      , data_(vv.data_)
+      , data_ref_(0)
+      {
+         assert(size_ > 0);
+      }
 
       inline void rebase(data_ptr_t data)
       {
@@ -4331,6 +4622,11 @@ namespace exprtk
          return data_;
       }
 
+      inline std::size_t base_size() const
+      {
+         return base_size_;
+      }
+
       inline std::size_t size() const
       {
          return size_;
@@ -4338,22 +4634,55 @@ namespace exprtk
 
       inline const T& operator[](const std::size_t index) const
       {
+         assert(index < size_);
          return data_[index];
       }
 
       inline T& operator[](const std::size_t index)
       {
+         assert(index < size_);
          return data_[index];
       }
 
       void set_ref(data_ptr_t* data_ref)
       {
          data_ref_.push_back(data_ref);
+         exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n",
+                       reinterpret_cast<void*>(data_ref),
+                       static_cast<int>(data_ref_.size())));
+      }
+
+      void remove_ref(data_ptr_t* data_ref)
+      {
+         data_ref_.erase(
+            std::remove(data_ref_.begin(), data_ref_.end(), data_ref),
+            data_ref_.end());
+         exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n",
+                       reinterpret_cast<void*>(data_ref),
+                       static_cast<int>(data_ref_.size())));
+      }
+
+      bool set_size(const std::size_t new_size)
+      {
+         if ((new_size > 0) && (new_size <= base_size_))
+         {
+            size_ = new_size;
+            exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n",
+                          reinterpret_cast<void*>(data_),
+                          size_));
+            return true;
+         }
+
+         exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu  base_size: %lu\n",
+                       new_size,
+                       base_size_));
+         return false;
       }
 
    private:
 
-      const std::size_t size_;
+      const std::size_t base_size_;
+      std::size_t size_;
       data_ptr_t  data_;
       std::vector<data_ptr_t*> data_ref_;
    };
@@ -4386,15 +4715,15 @@ namespace exprtk
       };
 
       type_store()
-      : data(0),
-        size(0),
-        type(e_unknown)
+      : data(0)
+      , size(0)
+      , type(e_unknown)
       {}
 
       union
       {
-          void*  data;
-          T*     vec_data;
+         void* data;
+         T*    vec_data;
       };
 
       std::size_t size;
@@ -4462,13 +4791,13 @@ namespace exprtk
          typedef ViewType      value_t;
 
          explicit type_view(type_store_t& ts)
-         : ts_(ts),
-           data_(reinterpret_cast<value_t*>(ts_.data))
+         : ts_(ts)
+         , data_(reinterpret_cast<value_t*>(ts_.data))
          {}
 
          explicit type_view(const type_store_t& ts)
-         : ts_(const_cast<type_store_t&>(ts)),
-           data_(reinterpret_cast<value_t*>(ts_.data))
+         : ts_(const_cast<type_store_t&>(ts))
+         , data_(reinterpret_cast<value_t*>(ts_.data))
          {}
 
          inline std::size_t size() const
@@ -4529,6 +4858,16 @@ namespace exprtk
             return v_;
          }
 
+         inline operator value_t() const
+         {
+            return v_;
+         }
+
+         inline operator value_t()
+         {
+            return v_;
+         }
+
          template <typename IntType>
          inline bool to_int(IntType& i) const
          {
@@ -4577,6 +4916,9 @@ namespace exprtk
    public:
 
       typedef type_store<T> type_store_t;
+      typedef typename type_store_t::scalar_view scalar_t;
+      typedef typename type_store_t::vector_view vector_t;
+      typedef typename type_store_t::string_view string_t;
 
       results_context()
       : results_available_(false)
@@ -4600,6 +4942,61 @@ namespace exprtk
          return parameter_list_[index];
       }
 
+      inline bool get_scalar(const std::size_t& index, T& out) const
+      {
+         if (
+              (index < parameter_list_.size()) &&
+              (parameter_list_[index].type == type_store_t::e_scalar)
+            )
+         {
+            const scalar_t scalar(parameter_list_[index]);
+            out = scalar();
+            return true;
+         }
+
+         return false;
+      }
+
+      template <typename OutputIterator>
+      inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const
+      {
+         if (
+              (index < parameter_list_.size()) &&
+              (parameter_list_[index].type == type_store_t::e_vector)
+            )
+         {
+            const vector_t vector(parameter_list_[index]);
+            for (std::size_t i = 0; i < vector.size(); ++i)
+            {
+               *(out_itr++) = vector[i];
+            }
+
+            return true;
+         }
+
+         return false;
+      }
+
+      inline bool get_vector(const std::size_t& index, std::vector<T>& out) const
+      {
+         return get_vector(index,std::back_inserter(out));
+      }
+
+      inline bool get_string(const std::size_t& index, std::string& out) const
+      {
+         if (
+              (index < parameter_list_.size()) &&
+              (parameter_list_[index].type == type_store_t::e_string)
+            )
+         {
+            const string_t str(parameter_list_[index]);
+            out.assign(str.begin(),str.size());
+            return true;
+         }
+
+         return false;
+      }
+
    private:
 
       inline void clear()
@@ -4736,8 +5133,8 @@ namespace exprtk
       struct base_operation_t
       {
          base_operation_t(const operator_type t, const unsigned int& np)
-         : type(t),
-           num_params(np)
+         : type(t)
+         , num_params(np)
          {}
 
          operator_type type;
@@ -4746,23 +5143,24 @@ namespace exprtk
 
       namespace loop_unroll
       {
+         const unsigned int global_loop_batch_size =
          #ifndef exprtk_disable_superscalar_unroll
-         const unsigned int global_loop_batch_size = 16;
+         16;
          #else
-         const unsigned int global_loop_batch_size = 4;
+          4;
          #endif
 
          struct details
          {
             explicit details(const std::size_t& vsize,
                              const unsigned int loop_batch_size = global_loop_batch_size)
-            : batch_size(loop_batch_size   ),
-              remainder (vsize % batch_size),
-              upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
+            : batch_size(loop_batch_size   )
+            , remainder (vsize % batch_size)
+            , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
             {}
 
             unsigned int batch_size;
-            int   remainder;
+            int remainder;
             int upper_bound;
          };
       }
@@ -4771,16 +5169,33 @@ namespace exprtk
       inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
       {
          if (size)
-            exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
-         else
             exprtk_debug(("%s - addr: %p size: %d\n",
                           s.c_str(),
                           ptr,
                           static_cast<unsigned int>(size)));
+         else
+            exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr));
+      }
+
+      template <typename T>
+      inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size)
+      {
+         printf("----- %s (%p) -----\n",
+                vec_name.c_str(),
+                static_cast<const void*>(data));
+         printf("[ ");
+         for (std::size_t i = 0; i <  size; ++i)
+         {
+            printf("%8.3f\t", data[i]);
+         }
+         printf(" ]\n");
+         printf("---------------------\n");
       }
       #else
       inline void dump_ptr(const std::string&, const void*) {}
       inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
+      template <typename T>
+      inline void dump_vector(const std::string&, const T*, const std::size_t) {}
       #endif
 
       template <typename T>
@@ -4796,31 +5211,31 @@ namespace exprtk
          struct control_block
          {
             control_block()
-            : ref_count(1),
-              size     (0),
-              data     (0),
-              destruct (true)
+            : ref_count(1)
+            , size     (0)
+            , data     (0)
+            , destruct (true)
             {}
 
             explicit control_block(const std::size_t& dsize)
-            : ref_count(1    ),
-              size     (dsize),
-              data     (0    ),
-              destruct (true )
+            : ref_count(1    )
+            , size     (dsize)
+            , data     (0    )
+            , destruct (true )
             { create_data(); }
 
             control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
-            : ref_count(1     ),
-              size     (dsize ),
-              data     (dptr  ),
-              destruct (dstrct)
+            : ref_count(1     )
+            , size     (dsize )
+            , data     (dptr  )
+            , destruct (dstrct)
             {}
 
            ~control_block()
             {
                if (data && destruct && (0 == ref_count))
                {
-                  dump_ptr("~control_block() data",data);
+                  dump_ptr("~vec_data_store::control_block() data",data);
                   delete[] data;
                   data = reinterpret_cast<data_t>(0);
                }
@@ -4862,15 +5277,15 @@ namespace exprtk
 
          private:
 
-            control_block(const control_block&);
-            control_block& operator=(const control_block&);
+            control_block(const control_block&) exprtk_delete;
+            control_block& operator=(const control_block&) exprtk_delete;
 
             inline void create_data()
             {
                destruct = true;
                data     = new T[size];
                std::fill_n(data, size, T(0));
-               dump_ptr("control_block::create_data() - data",data,size);
+               dump_ptr("control_block::create_data() - data", data, size);
             }
          };
 
@@ -4903,7 +5318,7 @@ namespace exprtk
          {
             if (this != &vds)
             {
-               std::size_t final_size = min_size(control_block_, vds.control_block_);
+               const std::size_t final_size = min_size(control_block_, vds.control_block_);
 
                vds.control_block_->size = final_size;
                    control_block_->size = final_size;
@@ -4930,11 +5345,6 @@ namespace exprtk
             return control_block_->data;
          }
 
-         inline std::size_t size()
-         {
-            return control_block_->size;
-         }
-
          inline std::size_t size() const
          {
             return control_block_->size;
@@ -4958,7 +5368,7 @@ namespace exprtk
                if (5 == i)
                   exprtk_debug(("\n"));
 
-               exprtk_debug(("%15.10f ",data()[i]));
+               exprtk_debug(("%15.10f ", data()[i]));
             }
             exprtk_debug(("\n"));
             #endif
@@ -4973,7 +5383,7 @@ namespace exprtk
 
       private:
 
-         static inline std::size_t min_size(control_block* cb0, control_block* cb1)
+         static inline std::size_t min_size(const control_block* cb0, const control_block* cb1)
          {
             const std::size_t size0 = cb0->size;
             const std::size_t size1 = cb1->size;
@@ -5071,8 +5481,8 @@ namespace exprtk
                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
                   case e_root   : return root    <T>(arg0,arg1);
                   case e_roundn : return roundn  <T>(arg0,arg1);
-                  case e_equal  : return equal      (arg0,arg1);
-                  case e_nequal : return nequal     (arg0,arg1);
+                  case e_equal  : return equal   <T>(arg0,arg1);
+                  case e_nequal : return nequal  <T>(arg0,arg1);
                   case e_hypot  : return hypot   <T>(arg0,arg1);
                   case e_shr    : return shr     <T>(arg0,arg1);
                   case e_shl    : return shl     <T>(arg0,arg1);
@@ -5141,17 +5551,19 @@ namespace exprtk
          typedef Node** node_pp_t;
          typedef std::vector<node_pp_t> noderef_list_t;
 
-         virtual ~node_collector_interface() {}
+         virtual ~node_collector_interface()
+         {}
 
-         virtual void collect_nodes(noderef_list_t&) {}
+         virtual void collect_nodes(noderef_list_t&)
+         {}
       };
 
       template <typename Node>
       struct node_depth_base;
 
       template <typename T>
-      class expression_node : public node_collector_interface<expression_node<T> >,
-                              public node_depth_base<expression_node<T> >
+      class expression_node : public node_collector_interface<expression_node<T> >
+                            , public node_depth_base<expression_node<T> >
       {
       public:
 
@@ -5188,12 +5600,14 @@ namespace exprtk
             e_vovovoc       , e_vovocov       , e_vocovov     , e_covovov      ,
             e_covocov       , e_vocovoc       , e_covovoc     , e_vococov      ,
             e_sf3ext        , e_sf4ext        , e_nulleq      , e_strass       ,
-            e_vector        , e_vecelem       , e_rbvecelem   , e_rbveccelem   ,
-            e_vecdefass     , e_vecvalass     , e_vecvecass   , e_vecopvalass  ,
-            e_vecopvecass   , e_vecfunc       , e_vecvecswap  , e_vecvecineq   ,
-            e_vecvalineq    , e_valvecineq    , e_vecvecarith , e_vecvalarith  ,
-            e_valvecarith   , e_vecunaryop    , e_break       , e_continue     ,
-            e_swap
+            e_vector        , e_vecsize       , e_vecelem     , e_veccelem     ,
+            e_vecelemrtc    , e_veccelemrtc   , e_rbvecelem   , e_rbvecelemrtc ,
+            e_rbveccelem    , e_rbveccelemrtc , e_vecinit     , e_vecvalass    ,
+            e_vecvecass     , e_vecopvalass   , e_vecopvecass , e_vecfunc      ,
+            e_vecvecswap    , e_vecvecineq    , e_vecvalineq  , e_valvecineq   ,
+            e_vecvecarith   , e_vecvalarith   , e_valvecarith , e_vecunaryop   ,
+            e_vecondition   , e_break         , e_continue    , e_swap         ,
+            e_assert
          };
 
          typedef T value_type;
@@ -5219,7 +5633,12 @@ namespace exprtk
          {
             return e_none;
          }
-      };
+
+         inline virtual bool valid() const
+         {
+            return true;
+         }
+      }; // class expression_node
 
       template <typename T>
       inline bool is_generally_string_node(const expression_node<T>* node);
@@ -5239,12 +5658,6 @@ namespace exprtk
          return std::not_equal_to<float>()(0.0f,v);
       }
 
-      template <typename T>
-      inline bool is_true(const std::complex<T>& v)
-      {
-         return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
-      }
-
       template <typename T>
       inline bool is_true(const expression_node<T>* node)
       {
@@ -5269,6 +5682,12 @@ namespace exprtk
          return std::equal_to<T>()(T(0),node.first->value());
       }
 
+      template <typename T>
+      inline bool is_literal_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_constant == node->type());
+      }
+
       template <typename T>
       inline bool is_unary_node(const expression_node<T>* node)
       {
@@ -5298,10 +5717,15 @@ namespace exprtk
       {
          return node &&
                 (
-                  details::expression_node<T>::e_variable   == node->type() ||
-                  details::expression_node<T>::e_vecelem    == node->type() ||
-                  details::expression_node<T>::e_rbvecelem  == node->type() ||
-                  details::expression_node<T>::e_rbveccelem == node->type()
+                  details::expression_node<T>::e_variable      == node->type() ||
+                  details::expression_node<T>::e_vecelem       == node->type() ||
+                  details::expression_node<T>::e_veccelem      == node->type() ||
+                  details::expression_node<T>::e_vecelemrtc    == node->type() ||
+                  details::expression_node<T>::e_veccelemrtc   == node->type() ||
+                  details::expression_node<T>::e_rbvecelem     == node->type() ||
+                  details::expression_node<T>::e_rbveccelem    == node->type() ||
+                  details::expression_node<T>::e_rbvecelemrtc  == node->type() ||
+                  details::expression_node<T>::e_rbveccelemrtc == node->type()
                 );
       }
 
@@ -5311,12 +5735,42 @@ namespace exprtk
          return node && (details::expression_node<T>::e_vecelem == node->type());
       }
 
+      template <typename T>
+      inline bool is_vector_celem_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_veccelem == node->type());
+      }
+
+      template <typename T>
+      inline bool is_vector_elem_rtc_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_vecelemrtc == node->type());
+      }
+
+      template <typename T>
+      inline bool is_vector_celem_rtc_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_veccelemrtc == node->type());
+      }
+
       template <typename T>
       inline bool is_rebasevector_elem_node(const expression_node<T>* node)
       {
          return node && (details::expression_node<T>::e_rbvecelem == node->type());
       }
 
+      template <typename T>
+      inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_rbvecelemrtc == node->type());
+      }
+
+      template <typename T>
+      inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_rbveccelemrtc == node->type());
+      }
+
       template <typename T>
       inline bool is_rebasevector_celem_node(const expression_node<T>* node)
       {
@@ -5345,7 +5799,8 @@ namespace exprtk
                case details::expression_node<T>::e_vecvecarith :
                case details::expression_node<T>::e_vecvalarith :
                case details::expression_node<T>::e_valvecarith :
-               case details::expression_node<T>::e_vecunaryop  : return true;
+               case details::expression_node<T>::e_vecunaryop  :
+               case details::expression_node<T>::e_vecondition : return true;
                default                                         : return false;
             }
          }
@@ -5356,7 +5811,11 @@ namespace exprtk
       template <typename T>
       inline bool is_constant_node(const expression_node<T>* node)
       {
-         return node && (details::expression_node<T>::e_constant == node->type());
+         return node &&
+         (
+           details::expression_node<T>::e_constant    == node->type() ||
+           details::expression_node<T>::e_stringconst == node->type()
+         );
       }
 
       template <typename T>
@@ -5389,6 +5848,12 @@ namespace exprtk
          return node && (details::expression_node<T>::e_function == node->type());
       }
 
+      template <typename T>
+      inline bool is_vararg_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_vararg == node->type());
+      }
+
       template <typename T>
       inline bool is_return_node(const expression_node<T>* node)
       {
@@ -5409,7 +5874,13 @@ namespace exprtk
       }
 
       template <typename T>
-      inline bool branch_deletable(expression_node<T>* node)
+      inline bool is_assert_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_assert == node->type());
+      }
+
+      template <typename T>
+      inline bool branch_deletable(const expression_node<T>* node)
       {
          return (0 != node)             &&
                 !is_variable_node(node) &&
@@ -5417,7 +5888,7 @@ namespace exprtk
       }
 
       template <std::size_t N, typename T>
-      inline bool all_nodes_valid(expression_node<T>* (&b)[N])
+      inline bool all_nodes_valid(expression_node<T>* const (&b)[N])
       {
          for (std::size_t i = 0; i < N; ++i)
          {
@@ -5441,7 +5912,7 @@ namespace exprtk
       }
 
       template <std::size_t N, typename T>
-      inline bool all_nodes_variables(expression_node<T>* (&b)[N])
+      inline bool all_nodes_variables(expression_node<T>* const (&b)[N])
       {
          for (std::size_t i = 0; i < N; ++i)
          {
@@ -5457,7 +5928,7 @@ namespace exprtk
       template <typename T,
                 typename Allocator,
                 template <typename, typename> class Sequence>
-      inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
+      inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b)
       {
          for (std::size_t i = 0; i < b.size(); ++i)
          {
@@ -5491,7 +5962,7 @@ namespace exprtk
             for (std::size_t i = 0; i < node_delete_list.size(); ++i)
             {
                node_ptr_t& node = *node_delete_list[i];
-               exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast<void*>(node)));
+               exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node)));
                delete node;
                node = reinterpret_cast<node_ptr_t>(0);
             }
@@ -5588,12 +6059,16 @@ namespace exprtk
       template <typename Node>
       struct node_depth_base
       {
+         typedef Node* node_ptr_t;
+         typedef std::pair<node_ptr_t,bool> nb_pair_t;
+
          node_depth_base()
-         : depth_set(false),
-           depth(0)
+         : depth_set(false)
+         , depth(0)
          {}
 
-         virtual ~node_depth_base() {}
+         virtual ~node_depth_base()
+         {}
 
          virtual std::size_t node_depth() const { return 1; }
 
@@ -5608,7 +6083,7 @@ namespace exprtk
             return depth;
          }
 
-         std::size_t compute_node_depth(const std::pair<Node*,bool>& branch) const
+         std::size_t compute_node_depth(const nb_pair_t& branch) const
          {
             if (!depth_set)
             {
@@ -5620,11 +6095,12 @@ namespace exprtk
          }
 
          template <std::size_t N>
-         std::size_t compute_node_depth(const std::pair<Node*,bool> (&branch)[N]) const
+         std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const
          {
             if (!depth_set)
             {
                depth = 0;
+
                for (std::size_t i = 0; i < N; ++i)
                {
                   if (branch[i].first)
@@ -5632,6 +6108,7 @@ namespace exprtk
                      depth = std::max(depth,branch[i].first->node_depth());
                   }
                }
+
                depth += 1;
                depth_set = true;
             }
@@ -5639,12 +6116,34 @@ namespace exprtk
             return depth;
          }
 
+         template <typename BranchType>
+         std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const
+         {
+            return std::max(compute_node_depth(n0), compute_node_depth(n1));
+         }
+
+         template <typename BranchType>
+         std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const
+         {
+            return std::max(compute_node_depth(n0),
+                   std::max(compute_node_depth(n1), compute_node_depth(n2)));
+         }
+
+         template <typename BranchType>
+         std::size_t max_node_depth(const BranchType& n0, const BranchType& n1,
+                                    const BranchType& n2, const BranchType& n3) const
+         {
+            return std::max(
+                     std::max(compute_node_depth(n0), compute_node_depth(n1)),
+                     std::max(compute_node_depth(n2), compute_node_depth(n3)));
+         }
+
          template <typename BranchType>
          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
          {
             if (!depth_set)
             {
-               depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1));
+               depth = 1 + max_node_depth(n0, n1);
                depth_set = true;
             }
 
@@ -5657,9 +6156,7 @@ namespace exprtk
          {
             if (!depth_set)
             {
-               depth = 1 + std::max(
-                              std::max(compute_node_depth(n0), compute_node_depth(n1)),
-                              compute_node_depth(n2));
+               depth = 1 + max_node_depth(n0, n1, n2);
                depth_set = true;
             }
 
@@ -5672,9 +6169,7 @@ namespace exprtk
          {
             if (!depth_set)
             {
-               depth = 1 + std::max(
-                           std::max(compute_node_depth(n0), compute_node_depth(n1)),
-                           std::max(compute_node_depth(n2), compute_node_depth(n3)));
+               depth = 1 + max_node_depth(n0, n1, n2, n3);
                depth_set = true;
             }
 
@@ -5683,7 +6178,7 @@ namespace exprtk
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
-         std::size_t compute_node_depth(const Sequence<Node*, Allocator>& branch_list) const
+         std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const
          {
             if (!depth_set)
             {
@@ -5694,6 +6189,7 @@ namespace exprtk
                      depth = std::max(depth, compute_node_depth(branch_list[i]));
                   }
                }
+
                depth_set = true;
             }
 
@@ -5702,7 +6198,7 @@ namespace exprtk
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
-         std::size_t compute_node_depth(const Sequence<std::pair<Node*,bool>,Allocator>& branch_list) const
+         std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const
          {
             if (!depth_set)
             {
@@ -5713,6 +6209,7 @@ namespace exprtk
                      depth = std::max(depth, compute_node_depth(branch_list[i].first));
                   }
                }
+
                depth_set = true;
             }
 
@@ -5723,18 +6220,18 @@ namespace exprtk
          mutable std::size_t depth;
 
          template <typename NodeSequence>
-         void collect(Node*const& node,
+         void collect(node_ptr_t const& node,
                       const bool deletable,
                       NodeSequence& delete_node_list) const
          {
             if ((0 != node) && deletable)
             {
-               delete_node_list.push_back(const_cast<Node**>(&node));
+               delete_node_list.push_back(const_cast<node_ptr_t*>(&node));
             }
          }
 
          template <typename NodeSequence>
-         void collect(const std::pair<Node*, bool>& branch,
+         void collect(const nb_pair_t& branch,
                       NodeSequence& delete_node_list) const
          {
             collect(branch.first, branch.second, delete_node_list);
@@ -5748,7 +6245,7 @@ namespace exprtk
          }
 
          template <std::size_t N, typename NodeSequence>
-         void collect(const std::pair<Node*, bool>(&branch)[N],
+         void collect(const nb_pair_t(&branch)[N],
                       NodeSequence& delete_node_list) const
          {
             for (std::size_t i = 0; i < N; ++i)
@@ -5760,7 +6257,7 @@ namespace exprtk
          template <typename Allocator,
                    template <typename, typename> class Sequence,
                    typename NodeSequence>
-         void collect(const Sequence<std::pair<Node*, bool>, Allocator>& branch,
+         void collect(const Sequence<nb_pair_t, Allocator>& branch,
                       NodeSequence& delete_node_list) const
          {
             for (std::size_t i = 0; i < branch.size(); ++i)
@@ -5772,7 +6269,7 @@ namespace exprtk
          template <typename Allocator,
                    template <typename, typename> class Sequence,
                    typename NodeSequence>
-         void collect(const Sequence<Node*, Allocator>& branch_list,
+         void collect(const Sequence<node_ptr_t, Allocator>& branch_list,
                       NodeSequence& delete_node_list) const
          {
             for (std::size_t i = 0; i < branch_list.size(); ++i)
@@ -5786,7 +6283,7 @@ namespace exprtk
                    typename AllocatorB,
                    template <typename, typename> class Sequence,
                    typename NodeSequence>
-         void collect(const Sequence<Node*, AllocatorT>& branch_list,
+         void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list,
                       const Sequence<Boolean, AllocatorB>& branch_deletable_list,
                       NodeSequence& delete_node_list) const
          {
@@ -5805,12 +6302,14 @@ namespace exprtk
          typedef Type value_type;
          typedef value_type* value_ptr;
          typedef const value_ptr const_value_ptr;
+         typedef vector_holder<Type> vector_holder_t;
 
          class vector_holder_base
          {
          public:
 
-            virtual ~vector_holder_base() {}
+            virtual ~vector_holder_base()
+            {}
 
             inline value_ptr operator[](const std::size_t& index) const
             {
@@ -5822,6 +6321,11 @@ namespace exprtk
                return vector_size();
             }
 
+            inline std::size_t base_size() const
+            {
+               return vector_base_size();
+            }
+
             inline value_ptr data() const
             {
                return value_at(0);
@@ -5832,41 +6336,55 @@ namespace exprtk
                return false;
             }
 
-            virtual void set_ref(value_ptr*) {}
+            virtual void set_ref(value_ptr*)
+            {}
+
+            virtual void remove_ref(value_ptr*)
+            {}
+
+            virtual vector_view<Type>* rebaseable_instance()
+            {
+               return reinterpret_cast<vector_view<Type>*>(0);
+            }
 
          protected:
 
             virtual value_ptr value_at(const std::size_t&) const = 0;
             virtual std::size_t vector_size()              const = 0;
+            virtual std::size_t vector_base_size()         const = 0;
          };
 
-         class array_vector_impl : public vector_holder_base
+         class array_vector_impl exprtk_final : public vector_holder_base
          {
          public:
 
             array_vector_impl(const Type* vec, const std::size_t& vec_size)
-            : vec_(vec),
-              size_(vec_size)
+            : vec_(vec)
+            , size_(vec_size)
             {}
 
          protected:
 
-            value_ptr value_at(const std::size_t& index) const
+            value_ptr value_at(const std::size_t& index) const exprtk_override
             {
-               if (index < size_)
-                  return const_cast<const_value_ptr>(vec_ + index);
-               else
-                  return const_value_ptr(0);
+               assert(index < size_);
+               return const_cast<const_value_ptr>(vec_ + index);
             }
 
-            std::size_t vector_size() const
+            std::size_t vector_size() const exprtk_override
             {
                return size_;
             }
 
+            std::size_t vector_base_size() const exprtk_override
+            {
+               return vector_size();
+            }
+
          private:
 
-            array_vector_impl operator=(const array_vector_impl&);
+            array_vector_impl(const array_vector_impl&) exprtk_delete;
+            array_vector_impl& operator=(const array_vector_impl&) exprtk_delete;
 
             const Type* vec_;
             const std::size_t size_;
@@ -5874,36 +6392,43 @@ namespace exprtk
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
-         class sequence_vector_impl : public vector_holder_base
+         class sequence_vector_impl exprtk_final : public vector_holder_base
          {
          public:
 
             typedef Sequence<Type,Allocator> sequence_t;
 
-            sequence_vector_impl(sequence_t& seq)
+            explicit sequence_vector_impl(sequence_t& seq)
             : sequence_(seq)
             {}
 
          protected:
 
-            value_ptr value_at(const std::size_t& index) const
+            value_ptr value_at(const std::size_t& index) const exprtk_override
             {
-               return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
+               assert(index < sequence_.size());
+               return (&sequence_[index]);
             }
 
-            std::size_t vector_size() const
+            std::size_t vector_size() const exprtk_override
             {
                return sequence_.size();
             }
 
+            std::size_t vector_base_size() const exprtk_override
+            {
+               return vector_size();
+            }
+
          private:
 
-            sequence_vector_impl operator=(const sequence_vector_impl&);
+            sequence_vector_impl(const sequence_vector_impl&) exprtk_delete;
+            sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete;
 
             sequence_t& sequence_;
          };
 
-         class vector_view_impl : public vector_holder_base
+         class vector_view_impl exprtk_final : public vector_holder_base
          {
          public:
 
@@ -5911,37 +6436,112 @@ namespace exprtk
 
             vector_view_impl(vector_view_t& vec_view)
             : vec_view_(vec_view)
-            {}
+            {
+               assert(vec_view_.size() > 0);
+            }
 
-            void set_ref(value_ptr* ref)
+            void set_ref(value_ptr* ref) exprtk_override
             {
                vec_view_.set_ref(ref);
             }
 
-            virtual inline bool rebaseable() const
+            void remove_ref(value_ptr* ref) exprtk_override
+            {
+               vec_view_.remove_ref(ref);
+            }
+
+            bool rebaseable() const exprtk_override
             {
                return true;
             }
 
+            vector_view<Type>* rebaseable_instance() exprtk_override
+            {
+               return &vec_view_;
+            }
+
          protected:
 
-            value_ptr value_at(const std::size_t& index) const
+            value_ptr value_at(const std::size_t& index) const exprtk_override
             {
-               return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
+               assert(index < vec_view_.size());
+               return (&vec_view_[index]);
             }
 
-            std::size_t vector_size() const
+            std::size_t vector_size() const exprtk_override
             {
                return vec_view_.size();
             }
 
+            std::size_t vector_base_size() const exprtk_override
+            {
+               return vec_view_.base_size();
+            }
+
          private:
 
-            vector_view_impl operator=(const vector_view_impl&);
+            vector_view_impl(const vector_view_impl&) exprtk_delete;
+            vector_view_impl& operator=(const vector_view_impl&) exprtk_delete;
 
             vector_view_t& vec_view_;
          };
 
+         class resizable_vector_impl exprtk_final : public vector_holder_base
+         {
+         public:
+
+            resizable_vector_impl(vector_holder& vec_view_holder,
+                                  const Type* vec,
+                                  const std::size_t& vec_size)
+            : vec_(vec)
+            , size_(vec_size)
+            , vec_view_holder_(*vec_view_holder.rebaseable_instance())
+            {
+               assert(vec_view_holder.rebaseable_instance());
+               assert(size_ <= vector_base_size());
+            }
+
+            virtual ~resizable_vector_impl()
+            {}
+
+         protected:
+
+            value_ptr value_at(const std::size_t& index) const exprtk_override
+            {
+               assert(index < vector_size());
+               return const_cast<const_value_ptr>(vec_ + index);
+            }
+
+            std::size_t vector_size() const exprtk_override
+            {
+               return vec_view_holder_.size();
+            }
+
+            std::size_t vector_base_size() const exprtk_override
+            {
+               return vec_view_holder_.base_size();
+            }
+
+            bool rebaseable() const exprtk_override
+            {
+               return true;
+            }
+
+            virtual vector_view<Type>* rebaseable_instance() exprtk_override
+            {
+               return &vec_view_holder_;
+            }
+
+         private:
+
+            resizable_vector_impl(const resizable_vector_impl&) exprtk_delete;
+            resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete;
+
+            const Type* vec_;
+            const std::size_t size_;
+            vector_view<Type>& vec_view_holder_;
+         };
+
       public:
 
          typedef typename details::vec_data_store<Type> vds_t;
@@ -5950,19 +6550,23 @@ namespace exprtk
          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
          {}
 
-         vector_holder(const vds_t& vds)
+         explicit vector_holder(const vds_t& vds)
          : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
          {}
 
          template <typename Allocator>
-         vector_holder(std::vector<Type,Allocator>& vec)
+         explicit vector_holder(std::vector<Type,Allocator>& vec)
          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
          {}
 
-         vector_holder(exprtk::vector_view<Type>& vec)
+         explicit vector_holder(exprtk::vector_view<Type>& vec)
          : vector_holder_base_(new(buffer)vector_view_impl(vec))
          {}
 
+         explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds)
+         : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size()))
+         {}
+
          inline value_ptr operator[](const std::size_t& index) const
          {
             return (*vector_holder_base_)[index];
@@ -5973,6 +6577,11 @@ namespace exprtk
             return vector_holder_base_->size();
          }
 
+         inline std::size_t base_size() const
+         {
+            return vector_holder_base_->base_size();
+         }
+
          inline value_ptr data() const
          {
             return vector_holder_base_->data();
@@ -5980,7 +6589,18 @@ namespace exprtk
 
          void set_ref(value_ptr* ref)
          {
-            vector_holder_base_->set_ref(ref);
+            if (rebaseable())
+            {
+               vector_holder_base_->set_ref(ref);
+            }
+         }
+
+         void remove_ref(value_ptr* ref)
+         {
+            if (rebaseable())
+            {
+               vector_holder_base_->remove_ref(ref);
+            }
          }
 
          bool rebaseable() const
@@ -5988,23 +6608,31 @@ namespace exprtk
             return vector_holder_base_->rebaseable();
          }
 
+         vector_view<Type>* rebaseable_instance()
+         {
+            return vector_holder_base_->rebaseable_instance();
+         }
+
       private:
 
+         vector_holder(const vector_holder<Type>&) exprtk_delete;
+         vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete;
+
          mutable vector_holder_base* vector_holder_base_;
          uchar_t buffer[64];
       };
 
       template <typename T>
-      class null_node : public expression_node<T>
+      class null_node exprtk_final : public expression_node<T>
       {
       public:
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_null;
          }
@@ -6056,7 +6684,7 @@ namespace exprtk
       }
 
       template <typename T>
-      class null_eq_node : public expression_node<T>
+      class null_eq_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -6067,42 +6695,41 @@ namespace exprtk
          : equality_(equality)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
-
             const T v = branch_.first->value();
             const bool result = details::numeric::is_nan(v);
 
             if (result)
-               return (equality_) ? T(1) : T(0);
+               return equality_ ? T(1) : T(0);
             else
-               return (equality_) ? T(0) : T(1);
+               return equality_ ? T(0) : T(1);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_nulleq;
          }
 
-         inline operator_type operation() const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
-            return details::e_eq;
+            return branch_.first;
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline bool valid() const exprtk_override
          {
             return branch_.first;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::collect(branch_,node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
@@ -6114,7 +6741,7 @@ namespace exprtk
       };
 
       template <typename T>
-      class literal_node : public expression_node<T>
+      class literal_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -6122,25 +6749,25 @@ namespace exprtk
          : value_(v)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return value_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_constant;
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return reinterpret_cast<expression_node<T>*>(0);
          }
 
       private:
 
-         literal_node(literal_node<T>&) {}
-         literal_node<T>& operator=(literal_node<T>&) { return (*this); }
+         literal_node(const literal_node<T>&) exprtk_delete;
+         literal_node<T>& operator=(const literal_node<T>&) exprtk_delete;
 
          const T value_;
       };
@@ -6185,9 +6812,10 @@ namespace exprtk
       };
 
       template <typename T>
-      class string_literal_node : public expression_node <T>,
-                                  public string_base_node<T>,
-                                  public range_interface <T>
+      class string_literal_node exprtk_final
+                                : public expression_node <T>
+                                , public string_base_node<T>
+                                , public range_interface <T>
       {
       public:
 
@@ -6196,56 +6824,56 @@ namespace exprtk
          explicit string_literal_node(const std::string& v)
          : value_(v)
          {
-            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
+            rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0);
+            rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size());
             rp_.cache.first  = rp_.n0_c.second;
             rp_.cache.second = rp_.n1_c.second;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_stringconst;
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return reinterpret_cast<expression_node<T>*>(0);
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return value_;
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
             return value_.data();
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return value_.size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return rp_;
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return rp_;
          }
 
       private:
 
-         string_literal_node(const string_literal_node<T>&);
-         string_literal_node<T>& operator=(const string_literal_node<T>&);
+         string_literal_node(const string_literal_node<T>&) exprtk_delete;
+         string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete;
 
          const std::string value_;
          range_t rp_;
@@ -6264,48 +6892,51 @@ namespace exprtk
          : operation_(opr)
          {
             construct_branch_pair(branch_,branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
-
-            const T arg = branch_.first->value();
-
-            return numeric::process<T>(operation_,arg);
+            return numeric::process<T>
+                     (operation_,branch_.first->value());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_unary;
          }
 
-         inline operator_type operation() const
+         inline operator_type operation()
          {
             return operation_;
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return branch_.first;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return branch_.first && branch_.first->valid();
+         }
+
          inline void release()
          {
             branch_.second = false;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_final
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
-      protected:
+      private:
 
          operator_type operation_;
          branch_t branch_;
@@ -6325,20 +6956,20 @@ namespace exprtk
          : operation_(opr)
          {
             init_branches<2>(branch_, branch0, branch1);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_[0].first);
-            assert(branch_[1].first);
-
-            const T arg0 = branch_[0].first->value();
-            const T arg1 = branch_[1].first->value();
-
-            return numeric::process<T>(operation_,arg0,arg1);
+            return numeric::process<T>
+                   (
+                      operation_,
+                      branch_[0].first->value(),
+                      branch_[1].first->value()
+                   );
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_binary;
          }
@@ -6348,34 +6979,37 @@ namespace exprtk
             return operation_;
          }
 
-         inline expression_node<T>* branch(const std::size_t& index = 0) const
+         inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
          {
-            if (0 == index)
-               return branch_[0].first;
-            else if (1 == index)
-               return branch_[1].first;
-            else
-               return reinterpret_cast<expression_ptr>(0);
+            assert(index < 2);
+            return branch_[index].first;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return
+               branch_[0].first && branch_[0].first->valid() &&
+               branch_[1].first && branch_[1].first->valid() ;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_final
          {
             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
          }
 
-      protected:
+      private:
 
          operator_type operation_;
          branch_t branch_[2];
       };
 
       template <typename T, typename Operation>
-      class binary_ext_node : public expression_node<T>
+      class binary_ext_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -6385,20 +7019,17 @@ namespace exprtk
          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
          {
             init_branches<2>(branch_, branch0, branch1);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_[0].first);
-            assert(branch_[1].first);
-
             const T arg0 = branch_[0].first->value();
             const T arg1 = branch_[1].first->value();
-
             return Operation::process(arg0,arg1);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_binary_ext;
          }
@@ -6408,22 +7039,25 @@ namespace exprtk
             return Operation::operation();
          }
 
-         inline expression_node<T>* branch(const std::size_t& index = 0) const
+         inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
          {
-            if (0 == index)
-               return branch_[0].first;
-            else if (1 == index)
-               return branch_[1].first;
-            else
-               return reinterpret_cast<expression_ptr>(0);
+            assert(index < 2);
+            return branch_[index].first;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            return
+               branch_[0].first && branch_[0].first->valid() &&
+               branch_[1].first && branch_[1].first->valid() ;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
          }
@@ -6448,14 +7082,11 @@ namespace exprtk
          : operation_(opr)
          {
             init_branches<3>(branch_, branch0, branch1, branch2);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_[0].first);
-            assert(branch_[1].first);
-            assert(branch_[2].first);
-
             const T arg0 = branch_[0].first->value();
             const T arg1 = branch_[1].first->value();
             const T arg2 = branch_[2].first->value();
@@ -6476,17 +7107,25 @@ namespace exprtk
             }
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_trinary;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            return
+               branch_[0].first && branch_[0].first->valid() &&
+               branch_[1].first && branch_[1].first->valid() &&
+               branch_[2].first && branch_[2].first->valid() ;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override exprtk_final
          {
             return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
          }
@@ -6515,26 +7154,35 @@ namespace exprtk
             init_branches<4>(branch_, branch0, branch1, branch2, branch3);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_quaternary;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override exprtk_final
          {
             return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return
+               branch_[0].first && branch_[0].first->valid() &&
+               branch_[1].first && branch_[1].first->valid() &&
+               branch_[2].first && branch_[2].first->valid() &&
+               branch_[3].first && branch_[3].first->valid() ;
+         }
+
       protected:
 
          operator_type operation_;
@@ -6542,7 +7190,7 @@ namespace exprtk
       };
 
       template <typename T>
-      class conditional_node : public expression_node<T>
+      class conditional_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -6556,33 +7204,38 @@ namespace exprtk
             construct_branch_pair(condition_  , condition  );
             construct_branch_pair(consequent_ , consequent );
             construct_branch_pair(alternative_, alternative);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_  .first);
-            assert(consequent_ .first);
-            assert(alternative_.first);
-
             if (is_true(condition_))
                return consequent_.first->value();
             else
                return alternative_.first->value();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_conditional;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
-            expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
-            expression_node<T>::ndb_t::collect(alternative_, node_delete_list);
+            return
+               condition_  .first && condition_  .first->valid() &&
+               consequent_ .first && consequent_ .first->valid() &&
+               alternative_.first && alternative_.first->valid() ;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
+            expression_node<T>::ndb_t::collect(consequent_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth
                (condition_, consequent_, alternative_);
@@ -6596,7 +7249,7 @@ namespace exprtk
       };
 
       template <typename T>
-      class cons_conditional_node : public expression_node<T>
+      class cons_conditional_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -6609,31 +7262,36 @@ namespace exprtk
          {
             construct_branch_pair(condition_ , condition );
             construct_branch_pair(consequent_, consequent);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_ .first);
-            assert(consequent_.first);
-
             if (is_true(condition_))
                return consequent_.first->value();
             else
                return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_conditional;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
-            expression_node<T>::ndb_t::collect(consequent_, node_delete_list);
+            return
+               condition_ .first && condition_ .first->valid() &&
+               consequent_.first && consequent_.first->valid() ;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::
                compute_node_depth(condition_, consequent_);
@@ -6658,41 +7316,45 @@ namespace exprtk
          T value;
       };
 
-      class continue_exception
-      {};
+      class continue_exception {};
 
       template <typename T>
-      class break_node : public expression_node<T>
+      class break_node exprtk_final : public expression_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
          typedef std::pair<expression_ptr,bool> branch_t;
 
-         break_node(expression_ptr ret = expression_ptr(0))
+         explicit break_node(expression_ptr ret = expression_ptr(0))
          {
             construct_branch_pair(return_, ret);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            throw break_exception<T>(return_.first ? return_.first->value() : std::numeric_limits<T>::quiet_NaN());
-            #ifndef _MSC_VER
+            const T result = return_.first ?
+                             return_.first->value() :
+                             std::numeric_limits<T>::quiet_NaN();
+
+            throw break_exception<T>(result);
+
+            #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
             return std::numeric_limits<T>::quiet_NaN();
             #endif
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_break;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(return_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(return_);
          }
@@ -6703,34 +7365,36 @@ namespace exprtk
       };
 
       template <typename T>
-      class continue_node : public expression_node<T>
+      class continue_node exprtk_final : public expression_node<T>
       {
       public:
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             throw continue_exception();
-            #ifndef _MSC_VER
+            #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
             return std::numeric_limits<T>::quiet_NaN();
             #endif
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_break;
          }
       };
       #endif
 
-      #ifdef exprtk_enable_runtime_checks
       struct loop_runtime_checker
       {
-         loop_runtime_checker(loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0),
+         loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check,
                               loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid)
-         : iteration_count_(0),
-           loop_runtime_check_(loop_rt_chk),
-           loop_type(lp_typ)
-         {}
+         : iteration_count_(0)
+         , loop_runtime_check_(loop_runtime_check)
+         , max_loop_iterations_(loop_runtime_check_->max_loop_iterations)
+         , loop_type_(lp_typ)
+         {
+            assert(loop_runtime_check_);
+         }
 
          inline void reset(const _uint64_t initial_value = 0) const
          {
@@ -6739,16 +7403,18 @@ namespace exprtk
 
          inline bool check() const
          {
+            assert(loop_runtime_check_);
+
             if (
-                 (0 == loop_runtime_check_) ||
-                 (++iteration_count_ <= loop_runtime_check_->max_loop_iterations)
+                 (++iteration_count_ <= max_loop_iterations_) &&
+                 loop_runtime_check_->check()
                )
             {
                return true;
             }
 
             loop_runtime_check::violation_context ctxt;
-            ctxt.loop      = loop_type;
+            ctxt.loop      = loop_type_;
             ctxt.violation = loop_runtime_check::e_iteration_count;
 
             loop_runtime_check_->handle_runtime_violation(ctxt);
@@ -6756,29 +7422,19 @@ namespace exprtk
             return false;
          }
 
-         mutable _uint64_t iteration_count_;
-         mutable loop_runtime_check_ptr loop_runtime_check_;
-         loop_runtime_check::loop_types loop_type;
-      };
-      #else
-      struct loop_runtime_checker
-      {
-         loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types)
-         {}
-
-         inline void reset(const _uint64_t = 0) const
-         {}
-
-         inline bool check() const
+         bool valid() const
          {
-            return true;
+            return 0 != loop_runtime_check_;
          }
+
+         mutable _uint64_t iteration_count_;
+         mutable loop_runtime_check_ptr loop_runtime_check_;
+         const details::_uint64_t& max_loop_iterations_;
+         loop_runtime_check::loop_types loop_type_;
       };
-      #endif
 
       template <typename T>
-      class while_loop_node : public expression_node<T>,
-                              public loop_runtime_checker
+      class while_loop_node : public expression_node<T>
       {
       public:
 
@@ -6786,24 +7442,18 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
 
          while_loop_node(expression_ptr condition,
-                         expression_ptr loop_body,
-                         loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
-         : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop)
+                         expression_ptr loop_body)
          {
             construct_branch_pair(condition_, condition);
             construct_branch_pair(loop_body_, loop_body);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_.first);
-            assert(loop_body_.first);
-
             T result = T(0);
 
-            loop_runtime_checker::reset();
-
-            while (is_true(condition_) && loop_runtime_checker::check())
+            while (is_true(condition_))
             {
                result = loop_body_.first->value();
             }
@@ -6811,31 +7461,80 @@ namespace exprtk
             return result;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_while;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
-            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+            return
+               condition_.first && condition_.first->valid() &&
+               loop_body_.first && loop_body_.first->valid() ;
          }
 
-         std::size_t node_depth() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
          }
 
-      private:
+      protected:
 
          branch_t condition_;
          branch_t loop_body_;
       };
 
       template <typename T>
-      class repeat_until_loop_node : public expression_node<T>,
-                                     public loop_runtime_checker
+      class while_loop_rtc_node exprtk_final
+                                : public while_loop_node<T>
+                                , public loop_runtime_checker
+      {
+      public:
+
+         typedef while_loop_node<T>  parent_t;
+         typedef expression_node<T>* expression_ptr;
+
+         while_loop_rtc_node(expression_ptr condition,
+                             expression_ptr loop_body,
+                             loop_runtime_check_ptr loop_rt_chk)
+         : parent_t(condition, loop_body)
+         , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
+         {
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+
+            T result = T(0);
+
+            loop_runtime_checker::reset();
+
+            while (is_true(parent_t::condition_) && loop_runtime_checker::check())
+            {
+               result = parent_t::loop_body_.first->value();
+            }
+
+            return result;
+         }
+
+         using parent_t::valid;
+
+         bool valid() const exprtk_override exprtk_final
+         {
+            return parent_t::valid() &&
+                   loop_runtime_checker::valid();
+         }
+      };
+
+      template <typename T>
+      class repeat_until_loop_node : public expression_node<T>
       {
       public:
 
@@ -6843,57 +7542,100 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
 
          repeat_until_loop_node(expression_ptr condition,
-                                expression_ptr loop_body,
-                                loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
-         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
+                                expression_ptr loop_body)
          {
             construct_branch_pair(condition_, condition);
             construct_branch_pair(loop_body_, loop_body);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_.first);
-            assert(loop_body_.first);
-
             T result = T(0);
 
-            loop_runtime_checker::reset(1);
-
             do
             {
                result = loop_body_.first->value();
             }
-            while (is_false(condition_.first) && loop_runtime_checker::check());
+            while (is_false(condition_.first));
 
             return result;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_repeat;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
-            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+            return
+               condition_.first && condition_.first->valid() &&
+               loop_body_.first && loop_body_.first->valid() ;
          }
 
-         std::size_t node_depth() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
          }
 
-      private:
+      protected:
 
          branch_t condition_;
          branch_t loop_body_;
       };
 
       template <typename T>
-      class for_loop_node : public expression_node<T>,
-                            public loop_runtime_checker
+      class repeat_until_loop_rtc_node exprtk_final
+                                       : public repeat_until_loop_node<T>
+                                       , public loop_runtime_checker
+      {
+      public:
+
+         typedef repeat_until_loop_node<T> parent_t;
+         typedef expression_node<T>*       expression_ptr;
+
+         repeat_until_loop_rtc_node(expression_ptr condition,
+                                    expression_ptr loop_body,
+                                    loop_runtime_check_ptr loop_rt_chk)
+         : parent_t(condition, loop_body)
+         , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
+         {
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T result = T(0);
+
+            loop_runtime_checker::reset(1);
+
+            do
+            {
+               result = parent_t::loop_body_.first->value();
+            }
+            while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
+
+            return result;
+         }
+
+         using parent_t::valid;
+
+         inline bool valid() const exprtk_override exprtk_final
+         {
+            return parent_t::valid() &&
+                   loop_runtime_checker::valid();
+         }
+      };
+
+      template <typename T>
+      class for_loop_node : public expression_node<T>
       {
       public:
 
@@ -6903,31 +7645,25 @@ namespace exprtk
          for_loop_node(expression_ptr initialiser,
                        expression_ptr condition,
                        expression_ptr incrementor,
-                       expression_ptr loop_body,
-                       loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
-         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
+                       expression_ptr loop_body)
          {
             construct_branch_pair(initialiser_, initialiser);
             construct_branch_pair(condition_  , condition  );
             construct_branch_pair(incrementor_, incrementor);
             construct_branch_pair(loop_body_  , loop_body  );
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_.first);
-            assert(loop_body_.first);
-
             T result = T(0);
 
-            loop_runtime_checker::reset();
-
             if (initialiser_.first)
                initialiser_.first->value();
 
             if (incrementor_.first)
             {
-               while (is_true(condition_) && loop_runtime_checker::check())
+               while (is_true(condition_))
                {
                   result = loop_body_.first->value();
                   incrementor_.first->value();
@@ -6935,7 +7671,7 @@ namespace exprtk
             }
             else
             {
-               while (is_true(condition_) && loop_runtime_checker::check())
+               while (is_true(condition_))
                {
                   result = loop_body_.first->value();
                }
@@ -6944,26 +7680,31 @@ namespace exprtk
             return result;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_for;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
-            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
-            expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
-            expression_node<T>::ndb_t::collect(loop_body_  , node_delete_list);
+            return condition_.first && loop_body_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
+            expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(loop_body_   , node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth
                (initialiser_, condition_, incrementor_, loop_body_);
          }
 
-      private:
+      protected:
 
          branch_t initialiser_;
          branch_t condition_  ;
@@ -6971,39 +7712,89 @@ namespace exprtk
          branch_t loop_body_  ;
       };
 
-      #ifndef exprtk_disable_break_continue
       template <typename T>
-      class while_loop_bc_node : public expression_node<T>,
-                                 public loop_runtime_checker
+      class for_loop_rtc_node exprtk_final
+                              : public for_loop_node<T>
+                              , public loop_runtime_checker
       {
       public:
 
+         typedef for_loop_node<T>    parent_t;
          typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
 
-         while_loop_bc_node(expression_ptr condition,
-                            expression_ptr loop_body,
-                            loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
-         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
+         for_loop_rtc_node(expression_ptr initialiser,
+                           expression_ptr condition,
+                           expression_ptr incrementor,
+                           expression_ptr loop_body,
+                           loop_runtime_check_ptr loop_rt_chk)
+         : parent_t(initialiser, condition, incrementor, loop_body)
+         , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
          {
-            construct_branch_pair(condition_, condition);
-            construct_branch_pair(loop_body_, loop_body);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_.first);
-            assert(loop_body_.first);
-
             T result = T(0);
 
             loop_runtime_checker::reset();
 
-            while (is_true(condition_) && loop_runtime_checker::check())
+            if (parent_t::initialiser_.first)
+               parent_t::initialiser_.first->value();
+
+            if (parent_t::incrementor_.first)
+            {
+               while (is_true(parent_t::condition_) && loop_runtime_checker::check())
+               {
+                  result = parent_t::loop_body_.first->value();
+                  parent_t::incrementor_.first->value();
+               }
+            }
+            else
+            {
+               while (is_true(parent_t::condition_) && loop_runtime_checker::check())
+               {
+                  result = parent_t::loop_body_.first->value();
+               }
+            }
+
+            return result;
+         }
+
+         using parent_t::valid;
+
+         inline bool valid() const exprtk_override exprtk_final
+         {
+            return parent_t::valid() &&
+                   loop_runtime_checker::valid();
+         }
+      };
+
+      #ifndef exprtk_disable_break_continue
+      template <typename T>
+      class while_loop_bc_node : public while_loop_node<T>
+      {
+      public:
+
+         typedef while_loop_node<T>  parent_t;
+         typedef expression_node<T>* expression_ptr;
+
+         while_loop_bc_node(expression_ptr condition,
+                            expression_ptr loop_body)
+         : parent_t(condition, loop_body)
+         {
+            assert(parent_t::valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T result = T(0);
+
+            while (is_true(parent_t::condition_))
             {
                try
                {
-                  result = loop_body_.first->value();
+                  result = parent_t::loop_body_.first->value();
                }
                catch(const break_exception<T>& e)
                {
@@ -7015,61 +7806,83 @@ namespace exprtk
 
             return result;
          }
+      };
 
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_while;
-         }
+      template <typename T>
+      class while_loop_bc_rtc_node exprtk_final
+                                   : public while_loop_bc_node<T>
+                                   , public loop_runtime_checker
+      {
+      public:
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         typedef while_loop_bc_node<T> parent_t;
+         typedef expression_node<T>*   expression_ptr;
+
+         while_loop_bc_rtc_node(expression_ptr condition,
+                                expression_ptr loop_body,
+                                loop_runtime_check_ptr loop_rt_chk)
+         : parent_t(condition, loop_body)
+         , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
          {
-            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
-            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+            assert(valid());
          }
 
-         std::size_t node_depth() const
+         inline T value() const exprtk_override
          {
-            return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
+            T result = T(0);
+
+            loop_runtime_checker::reset();
+
+            while (is_true(parent_t::condition_) && loop_runtime_checker::check())
+            {
+               try
+               {
+                  result = parent_t::loop_body_.first->value();
+               }
+               catch(const break_exception<T>& e)
+               {
+                  return e.value;
+               }
+               catch(const continue_exception&)
+               {}
+            }
+
+            return result;
          }
 
-      private:
+         using parent_t::valid;
 
-         branch_t condition_;
-         branch_t loop_body_;
+         inline bool valid() const exprtk_override exprtk_final
+         {
+            return parent_t::valid() &&
+                   loop_runtime_checker::valid();
+         }
       };
 
       template <typename T>
-      class repeat_until_loop_bc_node : public expression_node<T>,
-                                        public loop_runtime_checker
+      class repeat_until_loop_bc_node : public repeat_until_loop_node<T>
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef repeat_until_loop_node<T> parent_t;
+         typedef expression_node<T>*       expression_ptr;
 
          repeat_until_loop_bc_node(expression_ptr condition,
-                                   expression_ptr loop_body,
-                                   loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
-         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
+                                   expression_ptr loop_body)
+         : parent_t(condition, loop_body)
          {
-            construct_branch_pair(condition_, condition);
-            construct_branch_pair(loop_body_, loop_body);
+            assert(parent_t::valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_.first);
-            assert(loop_body_.first);
-
             T result = T(0);
 
-            loop_runtime_checker::reset();
-
             do
             {
                try
                {
-                  result = loop_body_.first->value();
+                  result = parent_t::loop_body_.first->value();
                }
                catch(const break_exception<T>& e)
                {
@@ -7078,74 +7891,95 @@ namespace exprtk
                catch(const continue_exception&)
                {}
             }
-            while (is_false(condition_.first) && loop_runtime_checker::check());
+            while (is_false(parent_t::condition_.first));
 
             return result;
          }
+      };
 
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_repeat;
-         }
+      template <typename T>
+      class repeat_until_loop_bc_rtc_node exprtk_final
+                                          : public repeat_until_loop_bc_node<T>
+                                          , public loop_runtime_checker
+      {
+      public:
+
+         typedef repeat_until_loop_bc_node<T> parent_t;
+         typedef expression_node<T>*          expression_ptr;
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         repeat_until_loop_bc_rtc_node(expression_ptr condition,
+                                       expression_ptr loop_body,
+                                       loop_runtime_check_ptr loop_rt_chk)
+         : parent_t(condition, loop_body)
+         , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
          {
-            expression_node<T>::ndb_t::collect(condition_, node_delete_list);
-            expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
+            assert(valid());
          }
 
-         std::size_t node_depth() const
+         inline T value() const exprtk_override
          {
-            return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
+            T result = T(0);
+
+            loop_runtime_checker::reset();
+
+            do
+            {
+               try
+               {
+                  result = parent_t::loop_body_.first->value();
+               }
+               catch(const break_exception<T>& e)
+               {
+                  return e.value;
+               }
+               catch(const continue_exception&)
+               {}
+            }
+            while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
+
+            return result;
          }
 
-      private:
+         using parent_t::valid;
 
-         branch_t condition_;
-         branch_t loop_body_;
+         inline bool valid() const exprtk_override exprtk_final
+         {
+            return parent_t::valid() &&
+                   loop_runtime_checker::valid();
+         }
       };
 
       template <typename T>
-      class for_loop_bc_node : public expression_node<T>,
-                               public loop_runtime_checker
+      class for_loop_bc_node : public for_loop_node<T>
       {
       public:
 
+         typedef for_loop_node<T>    parent_t;
          typedef expression_node<T>* expression_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
 
          for_loop_bc_node(expression_ptr initialiser,
                           expression_ptr condition,
                           expression_ptr incrementor,
-                          expression_ptr loop_body,
-                          loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
-         : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
+                          expression_ptr loop_body)
+         : parent_t(initialiser, condition, incrementor, loop_body)
          {
-            construct_branch_pair(initialiser_, initialiser);
-            construct_branch_pair(condition_  , condition  );
-            construct_branch_pair(incrementor_, incrementor);
-            construct_branch_pair(loop_body_  , loop_body  );
+            assert(parent_t::valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(condition_.first);
-            assert(loop_body_.first);
-
             T result = T(0);
 
-            loop_runtime_checker::reset();
-
-            if (initialiser_.first)
-               initialiser_.first->value();
+            if (parent_t::initialiser_.first)
+               parent_t::initialiser_.first->value();
 
-            if (incrementor_.first)
+            if (parent_t::incrementor_.first)
             {
-               while (is_true(condition_) && loop_runtime_checker::check())
+               while (is_true(parent_t::condition_))
                {
                   try
                   {
-                     result = loop_body_.first->value();
+                     result = parent_t::loop_body_.first->value();
                   }
                   catch(const break_exception<T>& e)
                   {
@@ -7154,16 +7988,16 @@ namespace exprtk
                   catch(const continue_exception&)
                   {}
 
-                  incrementor_.first->value();
+                  parent_t::incrementor_.first->value();
                }
             }
             else
             {
-               while (is_true(condition_) && loop_runtime_checker::check())
+               while (is_true(parent_t::condition_))
                {
                   try
                   {
-                     result = loop_body_.first->value();
+                     result = parent_t::loop_body_.first->value();
                   }
                   catch(const break_exception<T>& e)
                   {
@@ -7176,32 +8010,83 @@ namespace exprtk
 
             return result;
          }
+      };
 
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_for;
-         }
+      template <typename T>
+      class for_loop_bc_rtc_node exprtk_final
+                                 : public for_loop_bc_node<T>
+                                 , public loop_runtime_checker
+      {
+      public:
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         typedef for_loop_bc_node<T> parent_t;
+         typedef expression_node<T>* expression_ptr;
+
+         for_loop_bc_rtc_node(expression_ptr initialiser,
+                              expression_ptr condition,
+                              expression_ptr incrementor,
+                              expression_ptr loop_body,
+                              loop_runtime_check_ptr loop_rt_chk)
+         : parent_t(initialiser, condition, incrementor, loop_body)
+         , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
          {
-            expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
-            expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
-            expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
-            expression_node<T>::ndb_t::collect(loop_body_  , node_delete_list);
+            assert(valid());
          }
 
-         std::size_t node_depth() const
+         inline T value() const exprtk_override
          {
-            return expression_node<T>::ndb_t::compute_node_depth
-               (initialiser_, condition_, incrementor_, loop_body_);
+            T result = T(0);
+
+            loop_runtime_checker::reset();
+
+            if (parent_t::initialiser_.first)
+               parent_t::initialiser_.first->value();
+
+            if (parent_t::incrementor_.first)
+            {
+               while (is_true(parent_t::condition_) && loop_runtime_checker::check())
+               {
+                  try
+                  {
+                     result = parent_t::loop_body_.first->value();
+                  }
+                  catch(const break_exception<T>& e)
+                  {
+                     return e.value;
+                  }
+                  catch(const continue_exception&)
+                  {}
+
+                  parent_t::incrementor_.first->value();
+               }
+            }
+            else
+            {
+               while (is_true(parent_t::condition_) && loop_runtime_checker::check())
+               {
+                  try
+                  {
+                     result = parent_t::loop_body_.first->value();
+                  }
+                  catch(const break_exception<T>& e)
+                  {
+                     return e.value;
+                  }
+                  catch(const continue_exception&)
+                  {}
+               }
+            }
+
+            return result;
          }
 
-      private:
+         using parent_t::valid;
 
-         branch_t initialiser_;
-         branch_t condition_  ;
-         branch_t incrementor_;
-         branch_t loop_body_  ;
+         inline bool valid() const exprtk_override exprtk_final
+         {
+            return parent_t::valid() &&
+                   loop_runtime_checker::valid();
+         }
       };
       #endif
 
@@ -7224,7 +8109,7 @@ namespace exprtk
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
-               if (arg_list[i])
+               if (arg_list[i] && arg_list[i]->valid())
                {
                   construct_branch_pair(arg_list_[i], arg_list[i]);
                }
@@ -7234,42 +8119,44 @@ namespace exprtk
                   return;
                }
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (!arg_list_.empty())
+            const std::size_t upper_bound = (arg_list_.size() - 1);
+
+            for (std::size_t i = 0; i < upper_bound; i += 2)
             {
-               const std::size_t upper_bound = (arg_list_.size() - 1);
+               expression_ptr condition  = arg_list_[i    ].first;
+               expression_ptr consequent = arg_list_[i + 1].first;
 
-               for (std::size_t i = 0; i < upper_bound; i += 2)
+               if (is_true(condition))
                {
-                  expression_ptr condition  = arg_list_[i    ].first;
-                  expression_ptr consequent = arg_list_[i + 1].first;
-
-                  if (is_true(condition))
-                  {
-                     return consequent->value();
-                  }
+                  return consequent->value();
                }
-
-               return arg_list_[upper_bound].first->value();
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+
+            return arg_list_[upper_bound].first->value();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
          {
             return expression_node<T>::e_switch;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return !arg_list_.empty();
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override exprtk_final
          {
             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
          }
@@ -7280,7 +8167,7 @@ namespace exprtk
       };
 
       template <typename T, typename Switch_N>
-      class switch_n_node : public switch_node<T>
+      class switch_n_node exprtk_final : public switch_node<T>
       {
       public:
 
@@ -7292,14 +8179,14 @@ namespace exprtk
          : switch_node<T>(arg_list)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Switch_N::process(switch_node<T>::arg_list_);
          }
       };
 
       template <typename T>
-      class multi_switch_node : public expression_node<T>
+      class multi_switch_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -7317,7 +8204,7 @@ namespace exprtk
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
-               if (arg_list[i])
+               if (arg_list[i] && arg_list[i]->valid())
                {
                   construct_branch_pair(arg_list_[i], arg_list[i]);
                }
@@ -7327,19 +8214,16 @@ namespace exprtk
                   return;
                }
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            T result = T(0);
-
-            if (arg_list_.empty())
-            {
-               return std::numeric_limits<T>::quiet_NaN();
-            }
-
             const std::size_t upper_bound = (arg_list_.size() - 1);
 
+            T result = T(0);
+
             for (std::size_t i = 0; i < upper_bound; i += 2)
             {
                expression_ptr condition  = arg_list_[i    ].first;
@@ -7354,17 +8238,22 @@ namespace exprtk
             return result;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_mswitch;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return !arg_list_.empty() && (0 == (arg_list_.size() % 2));
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override exprtk_final
          {
             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
          }
@@ -7387,8 +8276,9 @@ namespace exprtk
       };
 
       template <typename T>
-      class variable_node : public expression_node<T>,
-                            public ivariable      <T>
+      class variable_node exprtk_final
+                          : public expression_node<T>
+                          , public ivariable      <T>
       {
       public:
 
@@ -7407,22 +8297,22 @@ namespace exprtk
             return this < (&v);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return (*value_);
          }
 
-         inline T& ref()
+         inline T& ref() exprtk_override
          {
             return (*value_);
          }
 
-         inline const T& ref() const
+         inline const T& ref() const exprtk_override
          {
             return (*value_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_variable;
          }
@@ -7442,11 +8332,11 @@ namespace exprtk
          typedef std::pair<std::size_t,std::size_t> cached_range_t;
 
          range_pack()
-         : n0_e (std::make_pair(false,expression_node_ptr(0))),
-           n1_e (std::make_pair(false,expression_node_ptr(0))),
-           n0_c (std::make_pair(false,0)),
-           n1_c (std::make_pair(false,0)),
-           cache(std::make_pair(0,0))
+         : n0_e (std::make_pair(false,expression_node_ptr(0)))
+         , n1_e (std::make_pair(false,expression_node_ptr(0)))
+         , n0_c (std::make_pair(false,0))
+         , n1_c (std::make_pair(false,0))
+         , cache(std::make_pair(0,0))
          {}
 
          void clear()
@@ -7525,13 +8415,13 @@ namespace exprtk
                  (std::numeric_limits<std::size_t>::max() == r1  )
                )
             {
-               r1 = size - 1;
+               r1 = size;
             }
 
             cache.first  = r0;
             cache.second = r1;
 
-            #ifndef exprtk_enable_runtime_checks
+            #ifndef exprtk_enable_range_runtime_checks
             return (r0 <= r1);
             #else
             return range_runtime_check(r0, r1, size);
@@ -7540,12 +8430,12 @@ namespace exprtk
 
          inline std::size_t const_size() const
          {
-            return (n1_c.second - n0_c.second + 1);
+            return (n1_c.second - n0_c.second);
          }
 
          inline std::size_t cache_size() const
          {
-            return (cache.second - cache.first + 1);
+            return (cache.second - cache.first);
          }
 
          std::pair<bool,expression_node_ptr> n0_e;
@@ -7554,21 +8444,25 @@ namespace exprtk
          std::pair<bool,std::size_t        > n1_c;
          mutable cached_range_t             cache;
 
-         #ifdef exprtk_enable_runtime_checks
+         #ifdef exprtk_enable_range_runtime_checks
          bool range_runtime_check(const std::size_t r0,
                                   const std::size_t r1,
                                   const std::size_t size) const
          {
-            if ((r0 < 0) || (r0 >= size))
+            if (r0 > size)
             {
-               throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)");
+               throw std::runtime_error("range error: (r0 < 0) || (r0 > size)");
+               #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
                return false;
+               #endif
             }
 
-            if ((r1 < 0) || (r1 >= size))
+            if (r1 > size)
             {
-               throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)");
+               throw std::runtime_error("range error: (r1 < 0) || (r1 > size)");
+               #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
                return false;
+               #endif
             }
 
             return (r0 <= r1);
@@ -7586,11 +8480,11 @@ namespace exprtk
          typedef string_base_node<T>* strbase_ptr_t;
 
          range_data_type()
-         : range(0),
-           data (0),
-           size (0),
-           type_size(0),
-           str_node (0)
+         : range(0)
+         , data (0)
+         , size (0)
+         , type_size(0)
+         , str_node (0)
          {}
 
          range_t*      range;
@@ -7608,78 +8502,97 @@ namespace exprtk
       public:
 
          typedef vector_node<T>*   vector_node_ptr;
-         typedef vec_data_store<T>           vds_t;
+         typedef vec_data_store<T> vds_t;
 
          virtual ~vector_interface()
          {}
 
-         virtual std::size_t size   () const = 0;
+         virtual std::size_t size     () const = 0;
 
-         virtual vector_node_ptr vec() const = 0;
+         virtual std::size_t base_size() const = 0;
 
-         virtual vector_node_ptr vec()       = 0;
+         virtual vector_node_ptr vec  () const = 0;
 
-         virtual       vds_t& vds   ()       = 0;
+         virtual vector_node_ptr vec  ()       = 0;
 
-         virtual const vds_t& vds   () const = 0;
+         virtual       vds_t& vds     ()       = 0;
 
-         virtual bool side_effect   () const { return false; }
+         virtual const vds_t& vds     () const = 0;
+
+         virtual bool side_effect     () const { return false; }
       };
 
       template <typename T>
-      class vector_node : public expression_node <T>,
-                          public vector_interface<T>
+      class vector_node exprtk_final
+                        : public expression_node <T>
+                        , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*  expression_ptr;
+         typedef expression_node<T>* expression_ptr;
          typedef vector_holder<T>    vector_holder_t;
          typedef vector_node<T>*     vector_node_ptr;
-         typedef vec_data_store<T>             vds_t;
+         typedef vec_data_store<T>   vds_t;
 
          explicit vector_node(vector_holder_t* vh)
-         : vector_holder_(vh),
-           vds_((*vector_holder_).size(),(*vector_holder_)[0])
+         : vector_holder_(vh)
+         , vds_((*vector_holder_).size(),(*vector_holder_)[0])
          {
             vector_holder_->set_ref(&vds_.ref());
          }
 
          vector_node(const vds_t& vds, vector_holder_t* vh)
-         : vector_holder_(vh),
-           vds_(vds)
+         : vector_holder_(vh)
+         , vds_(vds)
          {}
 
-         inline T value() const
+        ~vector_node()
+         {
+            assert(valid());
+            vector_holder_->remove_ref(&vds_.ref());
+         }
+
+         inline T value() const exprtk_override
          {
             return vds().data()[0];
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
             return const_cast<vector_node_ptr>(this);
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
             return this;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vector;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return vector_holder_;
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return vec_holder().size();
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds().size();
+            return vec_holder().base_size();
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
@@ -7689,6 +8602,11 @@ namespace exprtk
             return (*vector_holder_);
          }
 
+         inline vector_holder_t& vec_holder() const
+         {
+            return (*vector_holder_);
+         }
+
       private:
 
          vector_holder_t* vector_holder_;
@@ -7696,103 +8614,100 @@ namespace exprtk
       };
 
       template <typename T>
-      class vector_elem_node : public expression_node<T>,
-                               public ivariable      <T>
+      class vector_size_node exprtk_final
+                        : public expression_node <T>
       {
       public:
 
-         typedef expression_node<T>*            expression_ptr;
-         typedef vector_holder<T>               vector_holder_t;
-         typedef vector_holder_t*               vector_holder_ptr;
-         typedef std::pair<expression_ptr,bool> branch_t;
-
-         vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
-         : vec_holder_(vec_holder),
-           vector_base_((*vec_holder)[0])
-         {
-            construct_branch_pair(index_, index);
-         }
-
-         inline T value() const
-         {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
-         }
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_holder<T>    vector_holder_t;
 
-         inline T& ref()
-         {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
-         }
+         explicit vector_size_node(vector_holder_t* vh)
+         : vector_holder_(vh)
+         {}
 
-         inline const T& ref() const
+        ~vector_size_node()
          {
-            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
+            assert(valid());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline T value() const exprtk_override
          {
-            return expression_node<T>::e_vecelem;
+            assert(vector_holder_);
+            return static_cast<T>(vector_holder_->size());
          }
 
-         inline vector_holder_t& vec_holder()
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return (*vec_holder_);
+            return expression_node<T>::e_vecsize;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(index_, node_delete_list);
+            return vector_holder_ && vector_holder_->size();
          }
 
-         std::size_t node_depth() const
+         inline vector_holder_t* vec_holder()
          {
-            return expression_node<T>::ndb_t::compute_node_depth(index_);
+            return vector_holder_;
          }
 
       private:
 
-         vector_holder_ptr vec_holder_;
-         T* vector_base_;
-         branch_t index_;
+         vector_holder_t* vector_holder_;
       };
 
       template <typename T>
-      class rebasevector_elem_node : public expression_node<T>,
-                                     public ivariable      <T>
+      class vector_elem_node exprtk_final
+                             : public expression_node<T>
+                             , public ivariable      <T>
       {
       public:
 
          typedef expression_node<T>*            expression_ptr;
          typedef vector_holder<T>               vector_holder_t;
          typedef vector_holder_t*               vector_holder_ptr;
-         typedef vec_data_store<T>              vds_t;
          typedef std::pair<expression_ptr,bool> branch_t;
 
-         rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
-         : vector_holder_(vec_holder),
-           vds_((*vector_holder_).size(),(*vector_holder_)[0])
+         vector_elem_node(expression_ptr vec_node,
+                          expression_ptr index,
+                          vector_holder_ptr vec_holder)
+         : vector_holder_(vec_holder)
+         , vector_base_((*vec_holder)[0])
          {
-            vector_holder_->set_ref(&vds_.ref());
-            construct_branch_pair(index_, index);
+            construct_branch_pair(vector_node_, vec_node);
+            construct_branch_pair(index_      , index   );
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
+            return *access_vector();
          }
 
-         inline T& ref()
+         inline T& ref() exprtk_override
          {
-            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
+            return *access_vector();
          }
 
-         inline const T& ref() const
+         inline const T& ref() const exprtk_override
          {
-            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
+            return *access_vector();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return expression_node<T>::e_rbvecelem;
+            return expression_node<T>::e_vecelem;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return
+               vector_holder_        &&
+               index_.first          &&
+               vector_node_.first    &&
+               index_.first->valid() &&
+               vector_node_.first->valid();
          }
 
          inline vector_holder_t& vec_holder()
@@ -7800,60 +8715,81 @@ namespace exprtk
             return (*vector_holder_);
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(index_, node_delete_list);
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
+            expression_node<T>::ndb_t::collect(index_      , node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
-            return expression_node<T>::ndb_t::compute_node_depth(index_);
+            return expression_node<T>::ndb_t::compute_node_depth
+               (vector_node_, index_);
          }
 
       private:
 
+         inline T* access_vector() const
+         {
+            vector_node_.first->value();
+            return (vector_base_ + details::numeric::to_uint64(index_.first->value()));
+         }
+
          vector_holder_ptr vector_holder_;
-         vds_t             vds_;
-         branch_t          index_;
+         T* vector_base_;
+         branch_t vector_node_;
+         branch_t index_;
       };
 
       template <typename T>
-      class rebasevector_celem_node : public expression_node<T>,
-                                      public ivariable      <T>
+      class vector_celem_node exprtk_final
+                              : public expression_node<T>
+                              , public ivariable      <T>
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
-         typedef vector_holder<T>    vector_holder_t;
-         typedef vector_holder_t*    vector_holder_ptr;
-         typedef vec_data_store<T>   vds_t;
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
-         : index_(index),
-           vector_holder_(vec_holder),
-           vds_((*vector_holder_).size(),(*vector_holder_)[0])
+         vector_celem_node(expression_ptr vec_node,
+                           const std::size_t index,
+                           vector_holder_ptr vec_holder)
+         : index_(index)
+         , vector_holder_(vec_holder)
+         , vector_base_((*vec_holder)[0])
          {
-            vector_holder_->set_ref(&vds_.ref());
+            construct_branch_pair(vector_node_, vec_node);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            return *(vds_.data() + index_);
+            return *access_vector();
          }
 
-         inline T& ref()
+         inline T& ref() exprtk_override
          {
-            return *(vds_.data() + index_);
+            return *access_vector();
          }
 
-         inline const T& ref() const
+         inline const T& ref() const exprtk_override
          {
-            return *(vds_.data() + index_);
+            return *access_vector();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return expression_node<T>::e_rbveccelem;
+            return expression_node<T>::e_veccelem;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return
+               vector_holder_     &&
+               vector_node_.first &&
+               vector_node_.first->valid();
          }
 
          inline vector_holder_t& vec_holder()
@@ -7861,656 +8797,1745 @@ namespace exprtk
             return (*vector_holder_);
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
+         }
+
       private:
 
+         inline T* access_vector() const
+         {
+            vector_node_.first->value();
+            return (vector_base_ + index_);
+         }
+
          const std::size_t index_;
          vector_holder_ptr vector_holder_;
-         vds_t vds_;
+         T* vector_base_;
+         branch_t vector_node_;
       };
 
       template <typename T>
-      class vector_assignment_node : public expression_node<T>
+      class vector_elem_rtc_node exprtk_final
+                                 : public expression_node<T>
+                                 , public ivariable      <T>
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         vector_assignment_node(T* vector_base,
-                                const std::size_t& size,
-                                const std::vector<expression_ptr>& initialiser_list,
-                                const bool single_value_initialse)
-         : vector_base_(vector_base),
-           initialiser_list_(initialiser_list),
-           size_(size),
-           single_value_initialse_(single_value_initialse)
-         {}
+         vector_elem_rtc_node(expression_ptr vec_node,
+                              expression_ptr index,
+                              vector_holder_ptr vec_holder,
+                              vector_access_runtime_check_ptr vec_rt_chk)
+         : vector_holder_(vec_holder)
+         , vector_base_((*vec_holder)[0])
+         , vec_rt_chk_(vec_rt_chk)
+         , max_vector_index_(vector_holder_->size() - 1)
+         {
+            construct_branch_pair(vector_node_, vec_node);
+            construct_branch_pair(index_      , index   );
+            assert(valid());
+         }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (single_value_initialse_)
-            {
-               for (std::size_t i = 0; i < size_; ++i)
-               {
-                  *(vector_base_ + i) = initialiser_list_[0]->value();
-               }
-            }
-            else
-            {
-               std::size_t il_size = initialiser_list_.size();
+            return *access_vector();
+         }
 
-               for (std::size_t i = 0; i < il_size; ++i)
-               {
-                  *(vector_base_ + i) = initialiser_list_[i]->value();
-               }
+         inline T& ref() exprtk_override
+         {
+            return *access_vector();
+         }
 
-               if (il_size < size_)
-               {
-                  for (std::size_t i = il_size; i < size_; ++i)
-                  {
-                     *(vector_base_ + i) = T(0);
-                  }
-               }
-            }
+         inline const T& ref() const exprtk_override
+         {
+            return *access_vector();
+         }
 
-            return *(vector_base_);
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecelemrtc;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline bool valid() const exprtk_override
          {
-            return expression_node<T>::e_vecdefass;
+            return
+               vector_holder_        &&
+               index_.first          &&
+               vector_node_.first    &&
+               index_.first->valid() &&
+               vector_node_.first->valid();
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline vector_holder_t& vec_holder()
          {
-            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+            return (*vector_holder_);
          }
 
-         std::size_t node_depth() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
+            expression_node<T>::ndb_t::collect(index_,       node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (vector_node_, index_);
          }
 
       private:
 
-         vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
+         inline T* access_vector() const
+         {
+            const _uint64_t index = details::numeric::to_uint64(index_.first->value());
+            vector_node_.first->value();
 
-         mutable T* vector_base_;
-         std::vector<expression_ptr> initialiser_list_;
-         const std::size_t size_;
-         const bool single_value_initialse_;
+            if (index <= max_vector_index_)
+            {
+               return (vector_holder_->data() + index);
+            }
+
+            assert(vec_rt_chk_);
+
+            vector_access_runtime_check::violation_context context;
+            context.base_ptr   = reinterpret_cast<void*>(vector_base_);
+            context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
+            context.access_ptr = reinterpret_cast<void*>(vector_base_ + index);
+            context.type_size  = sizeof(T);
+
+            return vec_rt_chk_->handle_runtime_violation(context) ?
+               reinterpret_cast<T*>(context.access_ptr) :
+               vector_base_ ;
+         }
+
+         vector_holder_ptr vector_holder_;
+         T*                vector_base_;
+         branch_t          vector_node_;
+         branch_t          index_;
+         vector_access_runtime_check_ptr vec_rt_chk_;
+         const std::size_t max_vector_index_;
       };
 
       template <typename T>
-      class swap_node : public expression_node<T>
+      class vector_celem_rtc_node exprtk_final
+                                 : public expression_node<T>
+                                 , public ivariable      <T>
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
-         typedef variable_node<T>*   variable_node_ptr;
-
-         swap_node(variable_node_ptr var0, variable_node_ptr var1)
-         : var0_(var0),
-           var1_(var1)
-         {}
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         inline T value() const
+         vector_celem_rtc_node(expression_ptr vec_node,
+                               const std::size_t index,
+                               vector_holder_ptr vec_holder,
+                               vector_access_runtime_check_ptr vec_rt_chk)
+         : index_(index)
+         , max_vector_index_(vec_holder->size() - 1)
+         , vector_holder_(vec_holder)
+         , vector_base_((*vec_holder)[0])
+         , vec_rt_chk_(vec_rt_chk)
          {
-            std::swap(var0_->ref(),var1_->ref());
-            return var1_->ref();
+            construct_branch_pair(vector_node_, vec_node);
+            assert(valid());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline T value() const exprtk_override
          {
-            return expression_node<T>::e_swap;
+            return *access_vector();
          }
 
-      private:
+         inline T& ref() exprtk_override
+         {
+            return *access_vector();
+         }
 
-         variable_node_ptr var0_;
-         variable_node_ptr var1_;
-      };
+         inline const T& ref() const exprtk_override
+         {
+            return *access_vector();
+         }
 
-      template <typename T>
-      class swap_generic_node : public binary_node<T>
-      {
-      public:
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_veccelemrtc;
+         }
 
-         typedef expression_node<T>* expression_ptr;
-         typedef ivariable<T>* ivariable_ptr;
+         inline bool valid() const exprtk_override
+         {
+            return
+               vector_holder_     &&
+               vector_node_.first &&
+               vector_node_.first->valid();
+         }
 
-         swap_generic_node(expression_ptr var0, expression_ptr var1)
-         : binary_node<T>(details::e_swap, var0, var1),
-           var0_(dynamic_cast<ivariable_ptr>(var0)),
-           var1_(dynamic_cast<ivariable_ptr>(var1))
-         {}
+         inline vector_holder_t& vec_holder()
+         {
+            return (*vector_holder_);
+         }
 
-         inline T value() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            std::swap(var0_->ref(),var1_->ref());
-            return var1_->ref();
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         std::size_t node_depth() const exprtk_override
          {
-            return expression_node<T>::e_swap;
+            return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
          }
 
       private:
 
-         ivariable_ptr var0_;
-         ivariable_ptr var1_;
-      };
-
-      template <typename T>
-      class swap_vecvec_node : public binary_node     <T>,
-                               public vector_interface<T>
-      {
-      public:
-
-         typedef expression_node<T>*  expression_ptr;
-         typedef vector_node<T>*     vector_node_ptr;
-         typedef vec_data_store<T>             vds_t;
-
-         swap_vecvec_node(expression_ptr branch0,
-                          expression_ptr branch1)
-         : binary_node<T>(details::e_swap, branch0, branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           vec_size_     (0),
-           initialised_  (false)
+         inline T* access_vector() const
          {
-            if (is_ivector_node(binary_node<T>::branch_[0].first))
-            {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
-               {
-                  vec0_node_ptr_ = vi->vec();
-                  vds()          = vi->vds();
-               }
-            }
+            vector_node_.first->value();
 
-            if (is_ivector_node(binary_node<T>::branch_[1].first))
+            if (index_ <= max_vector_index_)
             {
-               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
-
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
-               {
-                  vec1_node_ptr_ = vi->vec();
-               }
+               return (vector_holder_->data() + index_);
             }
 
-            if (vec0_node_ptr_ && vec1_node_ptr_)
-            {
-               vec_size_ = std::min(vec0_node_ptr_->vds().size(),
-                                    vec1_node_ptr_->vds().size());
+            assert(vec_rt_chk_);
 
-               initialised_ = true;
-            }
+            vector_access_runtime_check::violation_context context;
+            context.base_ptr   = reinterpret_cast<void*>(vector_base_);
+            context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
+            context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
+            context.type_size  = sizeof(T);
+
+            return vec_rt_chk_->handle_runtime_violation(context) ?
+               reinterpret_cast<T*>(context.access_ptr) :
+               vector_base_ ;
          }
 
-         inline T value() const
-         {
-            assert(binary_node<T>::branch_[0].first);
-            assert(binary_node<T>::branch_[1].first);
+         const std::size_t index_;
+         const std::size_t max_vector_index_;
+         vector_holder_ptr vector_holder_;
+         T*                vector_base_;
+         branch_t          vector_node_;
+         vector_access_runtime_check_ptr vec_rt_chk_;
+      };
 
-            if (initialised_)
-            {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+      template <typename T>
+      class rebasevector_elem_node exprtk_final
+                                   : public expression_node<T>
+                                   , public ivariable      <T>
+      {
+      public:
 
-               T* vec0 = vec0_node_ptr_->vds().data();
-               T* vec1 = vec1_node_ptr_->vds().data();
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef vec_data_store<T>              vds_t;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-               for (std::size_t i = 0; i < vec_size_; ++i)
-               {
-                  std::swap(vec0[i],vec1[i]);
-               }
+         rebasevector_elem_node(expression_ptr vec_node,
+                                expression_ptr index,
+                                vector_holder_ptr vec_holder)
+         : vector_holder_(vec_holder)
+         {
+            construct_branch_pair(vector_node_, vec_node);
+            construct_branch_pair(index_      , index   );
+            assert(valid());
+         }
 
-               return vec1_node_ptr_->value();
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline T value() const exprtk_override
+         {
+            return *access_vector();
          }
 
-         vector_node_ptr vec() const
+         inline T& ref() exprtk_override
          {
-            return vec0_node_ptr_;
+            return *access_vector();
          }
 
-         vector_node_ptr vec()
+         inline const T& ref() const exprtk_override
          {
-            return vec0_node_ptr_;
+            return *access_vector();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return expression_node<T>::e_vecvecswap;
+            return expression_node<T>::e_rbvecelem;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
          {
-            return vec_size_;
+            return
+               vector_holder_        &&
+               index_.first          &&
+               vector_node_.first    &&
+               index_.first->valid() &&
+               vector_node_.first->valid();
          }
 
-         vds_t& vds()
+         inline vector_holder_t& vec_holder()
          {
-            return vds_;
+            return (*vector_holder_);
          }
 
-         const vds_t& vds() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return vds_;
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
+            expression_node<T>::ndb_t::collect(index_,       node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (vector_node_, index_);
          }
 
       private:
 
-         vector_node<T>* vec0_node_ptr_;
-         vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
-         bool            initialised_;
-         vds_t           vds_;
+         inline T* access_vector() const
+         {
+            vector_node_.first->value();
+            return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value()));
+         }
+
+         vector_holder_ptr vector_holder_;
+         branch_t          vector_node_;
+         branch_t          index_;
       };
 
-      #ifndef exprtk_disable_string_capabilities
       template <typename T>
-      class stringvar_node : public expression_node <T>,
-                             public string_base_node<T>,
-                             public range_interface <T>
+      class rebasevector_celem_node exprtk_final
+                                    : public expression_node<T>
+                                    , public ivariable      <T>
       {
       public:
 
-         typedef range_pack<T> range_t;
-
-         static std::string null_value;
-
-         explicit stringvar_node()
-         : value_(&null_value)
-         {}
-
-         explicit stringvar_node(std::string& v)
-         : value_(&v)
-         {
-            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
-            rp_.cache.first  = rp_.n0_c.second;
-            rp_.cache.second = rp_.n1_c.second;
-         }
-
-         inline bool operator <(const stringvar_node<T>& v) const
-         {
-            return this < (&v);
-         }
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_holder_t*    vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         inline T value() const
+         rebasevector_celem_node(expression_ptr vec_node,
+                                 const std::size_t index,
+                                 vector_holder_ptr vec_holder)
+         : index_(index)
+         , vector_holder_(vec_holder)
          {
-            rp_.n1_c.second  = (*value_).size() - 1;
-            rp_.cache.second = rp_.n1_c.second;
-
-            return std::numeric_limits<T>::quiet_NaN();
+            construct_branch_pair(vector_node_, vec_node);
+            assert(valid());
          }
 
-         std::string str() const
+         inline T value() const exprtk_override
          {
-            return ref();
+            vector_node_.first->value();
+            return ref();;
          }
 
-         char_cptr base() const
+         inline T& ref() exprtk_override
          {
-            return &(*value_)[0];
+            return *(vector_holder_->data() + index_);
          }
 
-         std::size_t size() const
+         inline const T& ref() const exprtk_override
          {
-            return ref().size();
+            return *(vector_holder_->data() + index_);
          }
 
-         std::string& ref()
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return (*value_);
+            return expression_node<T>::e_rbveccelem;
          }
 
-         const std::string& ref() const
+         inline bool valid() const exprtk_override
          {
-            return (*value_);
+            return
+               vector_holder_     &&
+               vector_node_.first &&
+               vector_node_.first->valid();
          }
 
-         range_t& range_ref()
+         inline vector_holder_t& vec_holder()
          {
-            return rp_;
+            return (*vector_holder_);
          }
 
-         const range_t& range_ref() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return rp_;
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         std::size_t node_depth() const exprtk_override
          {
-            return expression_node<T>::e_stringvar;
+            return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
          }
 
       private:
 
-         std::string* value_;
-         mutable range_t rp_;
+         const std::size_t index_;
+         vector_holder_ptr vector_holder_;
+         branch_t          vector_node_;
       };
 
       template <typename T>
-      std::string stringvar_node<T>::null_value = std::string("");
-
-      template <typename T>
-      class string_range_node : public expression_node <T>,
-                                public string_base_node<T>,
-                                public range_interface <T>
+      class rebasevector_elem_rtc_node exprtk_final
+                                       : public expression_node<T>
+                                       , public ivariable      <T>
       {
       public:
 
-         typedef range_pack<T> range_t;
-
-         static std::string null_value;
-
-         explicit string_range_node(std::string& v, const range_t& rp)
-         : value_(&v),
-           rp_(rp)
-         {}
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-         virtual ~string_range_node()
+         rebasevector_elem_rtc_node(expression_ptr vec_node,
+                                    expression_ptr index,
+                                    vector_holder_ptr vec_holder,
+                                    vector_access_runtime_check_ptr vec_rt_chk)
+         : vector_holder_(vec_holder)
+         , vec_rt_chk_(vec_rt_chk)
          {
-            rp_.free();
+            construct_branch_pair(vector_node_, vec_node);
+            construct_branch_pair(index_      , index   );
+            assert(valid());
          }
 
-         inline bool operator <(const string_range_node<T>& v) const
+         inline T value() const exprtk_override
          {
-            return this < (&v);
+            return *access_vector();
          }
 
-         inline T value() const
+         inline T& ref() exprtk_override
          {
-            return std::numeric_limits<T>::quiet_NaN();
+            return *access_vector();
          }
 
-         inline std::string str() const
+         inline const T& ref() const exprtk_override
          {
-            return (*value_);
+            return *access_vector();
          }
 
-         char_cptr base() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return &(*value_)[0];
+            return expression_node<T>::e_rbvecelemrtc;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
          {
-            return ref().size();
+            return
+               vector_holder_        &&
+               index_.first          &&
+               vector_node_.first    &&
+               index_.first->valid() &&
+               vector_node_.first->valid();
          }
 
-         inline range_t range() const
+         inline vector_holder_t& vec_holder()
          {
-            return rp_;
+            return (*vector_holder_);
          }
 
-         inline virtual std::string& ref()
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return (*value_);
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
+            expression_node<T>::ndb_t::collect(index_      , node_delete_list);
          }
 
-         inline virtual const std::string& ref() const
+         std::size_t node_depth() const exprtk_override
          {
-            return (*value_);
+            return expression_node<T>::ndb_t::compute_node_depth
+               (vector_node_, index_);
          }
 
-         inline range_t& range_ref()
-         {
-            return rp_;
-         }
+      private:
 
-         inline const range_t& range_ref() const
+         inline T* access_vector() const
          {
-            return rp_;
-         }
+            vector_node_.first->value();
+            const _uint64_t index = details::numeric::to_uint64(index_.first->value());
 
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_stringvarrng;
-         }
+            if (index <= (vector_holder_->size() - 1))
+            {
+               return (vector_holder_->data() + index);
+            }
 
-      private:
+            assert(vec_rt_chk_);
 
-         std::string* value_;
-         range_t      rp_;
-      };
+            vector_access_runtime_check::violation_context context;
+            context.base_ptr   = reinterpret_cast<void*>(vector_holder_->data());
+            context.end_ptr    = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size());
+            context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index);
+            context.type_size  = sizeof(T);
 
-      template <typename T>
-      std::string string_range_node<T>::null_value = std::string("");
+            return vec_rt_chk_->handle_runtime_violation(context) ?
+                   reinterpret_cast<T*>(context.access_ptr) :
+                   vector_holder_->data() ;
+         }
+
+         vector_holder_ptr vector_holder_;
+         branch_t          vector_node_;
+         branch_t          index_;
+         vector_access_runtime_check_ptr vec_rt_chk_;
+      };
 
       template <typename T>
-      class const_string_range_node : public expression_node <T>,
-                                      public string_base_node<T>,
-                                      public range_interface <T>
+      class rebasevector_celem_rtc_node exprtk_final
+                                    : public expression_node<T>
+                                    , public ivariable      <T>
       {
       public:
 
-         typedef range_pack<T> range_t;
-
-         explicit const_string_range_node(const std::string& v, const range_t& rp)
-         : value_(v),
-           rp_(rp)
-         {}
+         typedef expression_node<T>*            expression_ptr;
+         typedef vector_holder<T>               vector_holder_t;
+         typedef vector_holder_t*               vector_holder_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
 
-        ~const_string_range_node()
+         rebasevector_celem_rtc_node(expression_ptr vec_node,
+                                     const std::size_t index,
+                                     vector_holder_ptr vec_holder,
+                                     vector_access_runtime_check_ptr vec_rt_chk)
+         : index_(index)
+         , vector_holder_(vec_holder)
+         , vector_base_((*vec_holder)[0])
+         , vec_rt_chk_(vec_rt_chk)
          {
-            rp_.free();
+            construct_branch_pair(vector_node_, vec_node);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            return std::numeric_limits<T>::quiet_NaN();
+            return *access_vector();
          }
 
-         std::string str() const
+         inline T& ref() exprtk_override
          {
-            return value_;
+            return *access_vector();
          }
 
-         char_cptr base() const
+         inline const T& ref() const exprtk_override
          {
-            return value_.data();
+            return *access_vector();
          }
 
-         std::size_t size() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return value_.size();
+            return expression_node<T>::e_rbveccelemrtc;
          }
 
-         range_t range() const
+         inline bool valid() const exprtk_override
          {
-            return rp_;
+            return
+               vector_holder_     &&
+               vector_node_.first &&
+               vector_node_.first->valid();
          }
 
-         range_t& range_ref()
+         inline vector_holder_t& vec_holder()
          {
-            return rp_;
+            return (*vector_holder_);
          }
 
-         const range_t& range_ref() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return rp_;
+            expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         std::size_t node_depth() const exprtk_override
          {
-            return expression_node<T>::e_cstringvarrng;
+            return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
          }
 
       private:
 
-         const_string_range_node<T>& operator=(const const_string_range_node<T>&);
+         inline T* access_vector() const
+         {
+            vector_node_.first->value();
+
+            if (index_ <= vector_holder_->size() - 1)
+            {
+               return (vector_holder_->data() + index_);
+            }
 
-         const std::string value_;
-         range_t rp_;
+            assert(vec_rt_chk_);
+
+            vector_access_runtime_check::violation_context context;
+            context.base_ptr   = reinterpret_cast<void*>(vector_base_);
+            context.end_ptr    = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
+            context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
+            context.type_size  = sizeof(T);
+
+            return vec_rt_chk_->handle_runtime_violation(context) ?
+               reinterpret_cast<T*>(context.access_ptr) :
+               vector_base_ ;
+         }
+
+         const std::size_t index_;
+         vector_holder_ptr vector_holder_;
+         T*                vector_base_;
+         branch_t          vector_node_;
+         vector_access_runtime_check_ptr vec_rt_chk_;
       };
 
       template <typename T>
-      class generic_string_range_node : public expression_node <T>,
-                                        public string_base_node<T>,
-                                        public range_interface <T>
+      class vector_initialisation_node exprtk_final : public expression_node<T>
       {
       public:
 
-         typedef expression_node <T>*      expression_ptr;
-         typedef stringvar_node  <T>*     strvar_node_ptr;
-         typedef string_base_node<T>*        str_base_ptr;
-         typedef range_pack      <T>              range_t;
-         typedef range_t*                       range_ptr;
-         typedef range_interface<T>              irange_t;
-         typedef irange_t*                     irange_ptr;
-         typedef std::pair<expression_ptr,bool>  branch_t;
-
+         typedef expression_node<T>* expression_ptr;
 
-         generic_string_range_node(expression_ptr str_branch, const range_t& brange)
-         : initialised_(false),
-           str_base_ptr_ (0),
-           str_range_ptr_(0),
-           base_range_(brange)
+         vector_initialisation_node(T* vector_base,
+                                    const std::size_t& size,
+                                    const std::vector<expression_ptr>& initialiser_list,
+                                    const bool single_value_initialse)
+         : vector_base_(vector_base)
+         , initialiser_list_(initialiser_list)
+         , size_(size)
+         , single_value_initialse_(single_value_initialse)
+         , zero_value_initialse_(false)
+         , const_nonzero_literal_value_initialse_(false)
+         , single_initialiser_value_(T(0))
          {
-            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
-            range_.cache.first  = range_.n0_c.second;
-            range_.cache.second = range_.n1_c.second;
-
-            construct_branch_pair(branch_, str_branch);
-
-            if (is_generally_string_node(branch_.first))
+            if (single_value_initialse_)
             {
-               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
-
-               if (0 == str_base_ptr_)
-                  return;
-
-               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
+               if (initialiser_list_.empty())
+                  zero_value_initialse_ = true;
+               else if (
+                         (initialiser_list_.size() == 1) &&
+                         details::is_constant_node(initialiser_list_[0]) &&
+                         (T(0) == initialiser_list_[0]->value())
+                       )
+               {
+                  zero_value_initialse_ = true;
+               }
+               else
+               {
+                  assert(initialiser_list_.size() == 1);
 
-               if (0 == str_range_ptr_)
-                  return;
+                  if (details::is_constant_node(initialiser_list_[0]))
+                  {
+                     const_nonzero_literal_value_initialse_ = true;
+                     single_initialiser_value_ = initialiser_list_[0]->value();
+                     assert(T(0) != single_initialiser_value_);
+                  }
+               }
             }
-
-            initialised_ = (str_base_ptr_ && str_range_ptr_);
-         }
-
-        ~generic_string_range_node()
-         {
-            base_range_.free();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
+            if (single_value_initialse_)
             {
-               assert(branch_.first);
-
-               branch_.first->value();
-
-               std::size_t str_r0 = 0;
-               std::size_t str_r1 = 0;
-
-               std::size_t r0 = 0;
-               std::size_t r1 = 0;
-
-               const range_t& range = str_range_ptr_->range_ref();
-
-               const std::size_t base_str_size = str_base_ptr_->size();
-
-               if (
-                    range      (str_r0, str_r1, base_str_size) &&
-                    base_range_(    r0,     r1, base_str_size)
-                  )
+               if (zero_value_initialse_)
+               {
+                  details::set_zero_value(vector_base_, size_);
+               }
+               else if (const_nonzero_literal_value_initialse_)
+               {
+                  for (std::size_t i = 0; i < size_; ++i)
+                  {
+                     *(vector_base_ + i) = single_initialiser_value_;
+                  }
+               }
+               else
                {
-                  const std::size_t size = (r1 - r0) + 1;
+                  for (std::size_t i = 0; i < size_; ++i)
+                  {
+                     *(vector_base_ + i) = initialiser_list_[0]->value();
+                  }
+               }
+            }
+            else
+            {
+               const std::size_t initialiser_list_size = initialiser_list_.size();
 
-                  range_.n1_c.second  = size - 1;
-                  range_.cache.second = range_.n1_c.second;
+               for (std::size_t i = 0; i < initialiser_list_size; ++i)
+               {
+                  *(vector_base_ + i) = initialiser_list_[i]->value();
+               }
 
-                  value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
+               if (initialiser_list_size < size_)
+               {
+                  details::set_zero_value(
+                     vector_base_ + initialiser_list_size,
+                     (size_ - initialiser_list_size));
                }
             }
 
-            return std::numeric_limits<T>::quiet_NaN();
+            return *(vector_base_);
          }
 
-         std::string str() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return value_;
+            return expression_node<T>::e_vecinit;
          }
 
-         char_cptr base() const
+         inline bool valid() const exprtk_override
          {
-            return &value_[0];
+            return vector_base_;
          }
 
-         std::size_t size() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return value_.size();
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
          }
 
-         range_t& range_ref()
+         std::size_t node_depth() const exprtk_override
          {
-            return range_;
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
          }
 
-         const range_t& range_ref() const
+      private:
+
+         vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete;
+         vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         std::vector<expression_ptr> initialiser_list_;
+         const std::size_t size_;
+         const bool single_value_initialse_;
+         bool zero_value_initialse_;
+         bool const_nonzero_literal_value_initialse_;
+         T single_initialiser_value_;
+      };
+
+      template <typename T>
+      class vector_init_zero_value_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_zero_value_node(T* vector_base,
+                                     const std::size_t& size,
+                                     const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {}
+
+         inline T value() const exprtk_override
          {
-            return range_;
+            details::set_zero_value(vector_base_, size_);
+            return *(vector_base_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return expression_node<T>::e_strgenrange;
+            return expression_node<T>::e_vecinit;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+            return vector_base_;
          }
 
-         std::size_t node_depth() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            return expression_node<T>::ndb_t::compute_node_depth(branch_);
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete;
+         vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+      };
+
+      template <typename T>
+      class vector_init_single_constvalue_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_single_constvalue_node(T* vector_base,
+                                            const std::size_t& size,
+                                            const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {
+            single_initialiser_value_ = initialiser_list_[0]->value();
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            for (std::size_t i = 0; i < size_; ++i)
+            {
+               *(vector_base_ + i) = single_initialiser_value_;
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecinit;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vector_base_ &&
+                   (initialiser_list_.size() == 1) &&
+                   (details::is_constant_node(initialiser_list_[0])) &&
+                   (single_initialiser_value_ != T(0));
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete;
+         vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+         T single_initialiser_value_;
+      };
+
+      template <typename T>
+      class vector_init_single_value_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_single_value_node(T* vector_base,
+                                       const std::size_t& size,
+                                       const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            expression_node<T>& node = *initialiser_list_[0];
+
+            for (std::size_t i = 0; i < size_; ++i)
+            {
+               *(vector_base_ + i) = node.value();
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecinit;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vector_base_ &&
+                   (initialiser_list_.size() == 1) &&
+                   !details::is_constant_node(initialiser_list_[0]);
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete;
+         vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+      };
+
+      template <typename T>
+      class vector_init_iota_constconst_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_iota_constconst_node(T* vector_base,
+                                          const std::size_t& size,
+                                          const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {
+            base_value_      = initialiser_list_[0]->value();
+            increment_value_ = initialiser_list_[1]->value();
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T value = base_value_;
+
+            for (std::size_t i = 0; i < size_; ++i, value += increment_value_)
+            {
+               *(vector_base_ + i) = value;
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecinit;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vector_base_ &&
+                   (initialiser_list_.size() == 2) &&
+                   (details::is_constant_node(initialiser_list_[0])) &&
+                   (details::is_constant_node(initialiser_list_[1])) ;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete;
+         vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+         T base_value_;
+         T increment_value_;
+      };
+
+      template <typename T>
+      class vector_init_iota_constnconst_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_iota_constnconst_node(T* vector_base,
+                                           const std::size_t& size,
+                                           const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {
+            assert(valid());
+            base_value_ = initialiser_list_[0]->value();
+         }
+
+         inline T value() const exprtk_override
+         {
+            T value = base_value_;
+            expression_node<T>& increment = *initialiser_list_[1];
+
+            for (std::size_t i = 0; i < size_; ++i, value += increment.value())
+            {
+               *(vector_base_ + i) = value;
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecinit;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vector_base_ &&
+                  (initialiser_list_.size() == 2) &&
+                  ( details::is_constant_node(initialiser_list_[0])) &&
+                  (!details::is_constant_node(initialiser_list_[1]));
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete;
+         vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+         T base_value_;
+      };
+
+      template <typename T>
+      class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_iota_nconstconst_node(T* vector_base,
+                                           const std::size_t& size,
+                                           const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T value = initialiser_list_[0]->value();
+            const T increment = initialiser_list_[1]->value();
+
+            for (std::size_t i = 0; i < size_; ++i, value += increment)
+            {
+               *(vector_base_ + i) = value;
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecinit;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vector_base_ &&
+                   (initialiser_list_.size() == 2) &&
+                   (!details::is_constant_node(initialiser_list_[0])) &&
+                   (details::is_constant_node(initialiser_list_[1]));
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete;
+         vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+      };
+
+      template <typename T>
+      class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_init_iota_nconstnconst_node(T* vector_base,
+                                            const std::size_t& size,
+                                            const std::vector<expression_ptr>& initialiser_list)
+         : vector_base_(vector_base)
+         , size_(size)
+         , initialiser_list_(initialiser_list)
+         {
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T value = initialiser_list_[0]->value();
+            expression_node<T>& increment = *initialiser_list_[1];
+
+            for (std::size_t i = 0; i < size_; ++i, value += increment.value())
+            {
+               *(vector_base_ + i) = value;
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecinit;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vector_base_ &&
+                   (initialiser_list_.size() == 2) &&
+                   (!details::is_constant_node(initialiser_list_[0])) &&
+                   (!details::is_constant_node(initialiser_list_[1]));
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
+         }
+
+      private:
+
+         vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete;
+         vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete;
+
+         mutable T* vector_base_;
+         const std::size_t size_;
+         std::vector<expression_ptr> initialiser_list_;
+      };
+
+      template <typename T>
+      class swap_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef variable_node<T>*   variable_node_ptr;
+
+         swap_node(variable_node_ptr var0, variable_node_ptr var1)
+         : var0_(var0)
+         , var1_(var1)
+         {}
+
+         inline T value() const exprtk_override
+         {
+            std::swap(var0_->ref(),var1_->ref());
+            return var1_->ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_swap;
+         }
+
+      private:
+
+         variable_node_ptr var0_;
+         variable_node_ptr var1_;
+      };
+
+      template <typename T>
+      class swap_generic_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef ivariable<T>*       ivariable_ptr;
+
+         swap_generic_node(expression_ptr var0, expression_ptr var1)
+         : binary_node<T>(details::e_swap, var0, var1)
+         , var0_(dynamic_cast<ivariable_ptr>(var0))
+         , var1_(dynamic_cast<ivariable_ptr>(var1))
+         {}
+
+         inline T value() const exprtk_override
+         {
+            std::swap(var0_->ref(),var1_->ref());
+            return var1_->ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_swap;
+         }
+
+      private:
+
+         ivariable_ptr var0_;
+         ivariable_ptr var1_;
+      };
+
+      template <typename T>
+      class swap_vecvec_node exprtk_final
+                             : public binary_node     <T>
+                             , public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node    <T>* vector_node_ptr;
+         typedef vec_data_store <T>  vds_t;
+
+         using binary_node<T>::branch;
+
+         swap_vecvec_node(expression_ptr branch0,
+                          expression_ptr branch1)
+         : binary_node<T>(details::e_swap, branch0, branch1)
+         , vec0_node_ptr_(0)
+         , vec1_node_ptr_(0)
+         , initialised_  (false)
+         {
+            if (is_ivector_node(branch(0)))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
+               {
+                  vec0_node_ptr_ = vi->vec();
+                  vds()          = vi->vds();
+               }
+            }
+
+            if (is_ivector_node(branch(1)))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_ && vec1_node_ptr_)
+            {
+               initialised_ = size() <= base_size();
+            }
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            binary_node<T>::branch(0)->value();
+            binary_node<T>::branch(1)->value();
+
+            T* vec0 = vec0_node_ptr_->vds().data();
+            T* vec1 = vec1_node_ptr_->vds().data();
+
+            assert(size() <= base_size());
+            const std::size_t n = size();
+
+            for (std::size_t i = 0; i < n; ++i)
+            {
+               std::swap(vec0[i],vec1[i]);
+            }
+
+            return vec1_node_ptr_->value();
+         }
+
+         vector_node_ptr vec() const exprtk_override
+         {
+            return vec0_node_ptr_;
+         }
+
+         vector_node_ptr vec() exprtk_override
+         {
+            return vec0_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecvecswap;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && binary_node<T>::valid();
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return std::min(
+               vec0_node_ptr_->vec_holder().size(),
+               vec1_node_ptr_->vec_holder().size());
+         }
+
+         std::size_t base_size() const exprtk_override
+         {
+            return std::min(
+               vec0_node_ptr_->vec_holder().base_size(),
+               vec1_node_ptr_->vec_holder().base_size());
+         }
+
+         vds_t& vds() exprtk_override
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const exprtk_override
+         {
+            return vds_;
+         }
+
+      private:
+
+         vector_node<T>* vec0_node_ptr_;
+         vector_node<T>* vec1_node_ptr_;
+         bool            initialised_;
+         vds_t           vds_;
+      };
+
+      #ifndef exprtk_disable_string_capabilities
+      template <typename T>
+      class stringvar_node exprtk_final
+                           : public expression_node <T>
+                           , public string_base_node<T>
+                           , public range_interface <T>
+      {
+      public:
+
+         typedef typename range_interface<T>::range_t range_t;
+
+         static std::string null_value;
+
+         explicit stringvar_node()
+         : value_(&null_value)
+         {}
+
+         explicit stringvar_node(std::string& v)
+         : value_(&v)
+         {
+            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size());
+            rp_.cache.first  = rp_.n0_c.second;
+            rp_.cache.second = rp_.n1_c.second;
+         }
+
+         inline bool operator <(const stringvar_node<T>& v) const
+         {
+            return this < (&v);
+         }
+
+         inline T value() const exprtk_override
+         {
+            rp_.n1_c.second  = (*value_).size();
+            rp_.cache.second = rp_.n1_c.second;
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const exprtk_override
+         {
+            return ref();
+         }
+
+         char_cptr base() const exprtk_override
+         {
+            return &(*value_)[0];
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return ref().size();
+         }
+
+         std::string& ref()
+         {
+            return (*value_);
+         }
+
+         const std::string& ref() const
+         {
+            return (*value_);
+         }
+
+         range_t& range_ref() exprtk_override
+         {
+            return rp_;
+         }
+
+         const range_t& range_ref() const exprtk_override
+         {
+            return rp_;
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_stringvar;
+         }
+
+         void rebase(std::string& s)
+         {
+            value_ = &s;
+            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1);
+            rp_.cache.first  = rp_.n0_c.second;
+            rp_.cache.second = rp_.n1_c.second;
+         }
+
+      private:
+
+         std::string* value_;
+         mutable range_t rp_;
+      };
+
+      template <typename T>
+      std::string stringvar_node<T>::null_value = std::string("");
+
+      template <typename T>
+      class string_range_node exprtk_final
+                              : public expression_node <T>
+                              , public string_base_node<T>
+                              , public range_interface <T>
+      {
+      public:
+
+         typedef typename range_interface<T>::range_t range_t;
+
+         static std::string null_value;
+
+         explicit string_range_node(std::string& v, const range_t& rp)
+         : value_(&v)
+         , rp_(rp)
+         {}
+
+         virtual ~string_range_node()
+         {
+            rp_.free();
+         }
+
+         inline bool operator <(const string_range_node<T>& v) const
+         {
+            return this < (&v);
+         }
+
+         inline T value() const exprtk_override
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline std::string str() const exprtk_override
+         {
+            return (*value_);
+         }
+
+         char_cptr base() const exprtk_override
+         {
+            return &(*value_)[0];
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return ref().size();
+         }
+
+         inline range_t range() const
+         {
+            return rp_;
+         }
+
+         inline virtual std::string& ref()
+         {
+            return (*value_);
+         }
+
+         inline virtual const std::string& ref() const
+         {
+            return (*value_);
+         }
+
+         inline range_t& range_ref() exprtk_override
+         {
+            return rp_;
+         }
+
+         inline const range_t& range_ref() const exprtk_override
+         {
+            return rp_;
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_stringvarrng;
+         }
+
+      private:
+
+         std::string* value_;
+         range_t      rp_;
+      };
+
+      template <typename T>
+      std::string string_range_node<T>::null_value = std::string("");
+
+      template <typename T>
+      class const_string_range_node exprtk_final
+                                    : public expression_node <T>
+                                    , public string_base_node<T>
+                                    , public range_interface <T>
+      {
+      public:
+
+         typedef typename range_interface<T>::range_t range_t;
+
+         explicit const_string_range_node(const std::string& v, const range_t& rp)
+         : value_(v)
+         , rp_(rp)
+         {}
+
+        ~const_string_range_node()
+         {
+            rp_.free();
+         }
+
+         inline T value() const exprtk_override
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const exprtk_override
+         {
+            return value_;
+         }
+
+         char_cptr base() const exprtk_override
+         {
+            return value_.data();
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return value_.size();
+         }
+
+         range_t range() const
+         {
+            return rp_;
+         }
+
+         range_t& range_ref() exprtk_override
+         {
+            return rp_;
+         }
+
+         const range_t& range_ref() const exprtk_override
+         {
+            return rp_;
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_cstringvarrng;
+         }
+
+      private:
+
+         const_string_range_node(const const_string_range_node<T>&) exprtk_delete;
+         const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete;
+
+         const std::string value_;
+         range_t rp_;
+      };
+
+      template <typename T>
+      class generic_string_range_node exprtk_final
+                                      : public expression_node <T>
+                                      , public string_base_node<T>
+                                      , public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>* expression_ptr;
+         typedef stringvar_node  <T>* strvar_node_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface<T>   irange_t;
+         typedef irange_t*            irange_ptr;
+         typedef std::pair<expression_ptr,bool>  branch_t;
+
+         generic_string_range_node(expression_ptr str_branch, const range_t& brange)
+         : initialised_(false)
+         , str_base_ptr_ (0)
+         , str_range_ptr_(0)
+         , base_range_(brange)
+         {
+            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.cache.first  = range_.n0_c.second;
+            range_.cache.second = range_.n1_c.second;
+
+            construct_branch_pair(branch_, str_branch);
+
+            if (is_generally_string_node(branch_.first))
+            {
+               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
+
+               if (0 == str_base_ptr_)
+                  return;
+
+               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
+
+               if (0 == str_range_ptr_)
+                  return;
+            }
+
+            initialised_ = (str_base_ptr_ && str_range_ptr_);
+            assert(valid());
+         }
+
+        ~generic_string_range_node()
+         {
+            base_range_.free();
+         }
+
+         inline T value() const exprtk_override
+         {
+            branch_.first->value();
+
+            std::size_t str_r0 = 0;
+            std::size_t str_r1 = 0;
+
+            std::size_t r0 = 0;
+            std::size_t r1 = 0;
+
+            const range_t& range = str_range_ptr_->range_ref();
+
+            const std::size_t base_str_size = str_base_ptr_->size();
+
+            if (
+                  range      (str_r0, str_r1, base_str_size         ) &&
+                  base_range_(r0    , r1    , base_str_size - str_r0)
+               )
+            {
+               const std::size_t size = r1 - r0;
+
+               range_.n1_c.second  = size;
+               range_.cache.second = range_.n1_c.second;
+
+               value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const exprtk_override
+         {
+            return value_;
+         }
+
+         char_cptr base() const exprtk_override
+         {
+            return &value_[0];
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return value_.size();
+         }
+
+         range_t& range_ref() exprtk_override
+         {
+            return range_;
+         }
+
+         const range_t& range_ref() const exprtk_override
+         {
+            return range_;
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_strgenrange;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && branch_.first;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
          bool                initialised_;
-         branch_t                 branch_;
-         str_base_ptr       str_base_ptr_;
-         irange_ptr        str_range_ptr_;
-         mutable range_t      base_range_;
-         mutable range_t           range_;
-         mutable std::string       value_;
+         branch_t            branch_;
+         str_base_ptr        str_base_ptr_;
+         irange_ptr          str_range_ptr_;
+         mutable range_t     base_range_;
+         mutable range_t     range_;
+         mutable std::string value_;
       };
 
       template <typename T>
-      class string_concat_node : public binary_node     <T>,
-                                 public string_base_node<T>,
-                                 public range_interface <T>
+      class string_concat_node exprtk_final
+                               : public binary_node     <T>
+                               , public string_base_node<T>
+                               , public range_interface <T>
       {
       public:
 
-         typedef expression_node <T>*  expression_ptr;
-         typedef string_base_node<T>*    str_base_ptr;
-         typedef range_pack      <T>          range_t;
-         typedef range_t*                   range_ptr;
-         typedef range_interface<T>          irange_t;
-         typedef irange_t*                 irange_ptr;
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_interface<T>   irange_t;
+         typedef irange_t*            irange_ptr;
+         typedef range_t*             range_ptr;
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+
+         using binary_node<T>::branch;
 
          string_concat_node(const operator_type& opr,
                             expression_ptr branch0,
                             expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           initialised_(false),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_range_ptr_(0),
-           str1_range_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , initialised_(false)
+         , str0_base_ptr_ (0)
+         , str1_base_ptr_ (0)
+         , str0_range_ptr_(0)
+         , str1_range_ptr_(0)
          {
             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
@@ -8518,27 +10543,27 @@ namespace exprtk
             range_.cache.first  = range_.n0_c.second;
             range_.cache.second = range_.n1_c.second;
 
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == str0_range_ptr_)
                   return;
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == str1_range_ptr_)
                   return;
@@ -8548,167 +10573,171 @@ namespace exprtk
                            str1_base_ptr_  &&
                            str0_range_ptr_ &&
                            str1_range_ptr_ ;
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+            branch(0)->value();
+            branch(1)->value();
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+            std::size_t str0_r0 = 0;
+            std::size_t str0_r1 = 0;
 
-               std::size_t str0_r0 = 0;
-               std::size_t str0_r1 = 0;
+            std::size_t str1_r0 = 0;
+            std::size_t str1_r1 = 0;
 
-               std::size_t str1_r0 = 0;
-               std::size_t str1_r1 = 0;
+            const range_t& range0 = str0_range_ptr_->range_ref();
+            const range_t& range1 = str1_range_ptr_->range_ref();
 
-               const range_t& range0 = str0_range_ptr_->range_ref();
-               const range_t& range1 = str1_range_ptr_->range_ref();
-
-               if (
-                    range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
-                    range1(str1_r0, str1_r1, str1_base_ptr_->size())
-                  )
-               {
-                  const std::size_t size0 = (str0_r1 - str0_r0) + 1;
-                  const std::size_t size1 = (str1_r1 - str1_r0) + 1;
+            if (
+                  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
+                  range1(str1_r0, str1_r1, str1_base_ptr_->size())
+               )
+            {
+               const std::size_t size0 = (str0_r1 - str0_r0);
+               const std::size_t size1 = (str1_r1 - str1_r0);
 
-                  value_.assign(str0_base_ptr_->base() + str0_r0, size0);
-                  value_.append(str1_base_ptr_->base() + str1_r0, size1);
+               value_.assign(str0_base_ptr_->base() + str0_r0, size0);
+               value_.append(str1_base_ptr_->base() + str1_r0, size1);
 
-                  range_.n1_c.second  = value_.size() - 1;
-                  range_.cache.second = range_.n1_c.second;
-               }
+               range_.n1_c.second  = value_.size();
+               range_.cache.second = range_.n1_c.second;
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return value_;
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
             return &value_[0];
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return value_.size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return range_;
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return range_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strconcat;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && binary_node<T>::valid();
+         }
+
       private:
 
-         bool initialised_;
-         str_base_ptr str0_base_ptr_;
-         str_base_ptr str1_base_ptr_;
-         irange_ptr   str0_range_ptr_;
-         irange_ptr   str1_range_ptr_;
+         bool                initialised_;
+         str_base_ptr        str0_base_ptr_;
+         str_base_ptr        str1_base_ptr_;
+         irange_ptr          str0_range_ptr_;
+         irange_ptr          str1_range_ptr_;
          mutable range_t     range_;
          mutable std::string value_;
       };
 
       template <typename T>
-      class swap_string_node : public binary_node     <T>,
-                               public string_base_node<T>,
-                               public range_interface <T>
+      class swap_string_node exprtk_final
+                             : public binary_node     <T>
+                             , public string_base_node<T>
+                             , public range_interface <T>
       {
       public:
 
-         typedef expression_node <T>*  expression_ptr;
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface<T>   irange_t;
+         typedef irange_t*            irange_ptr;
+         typedef expression_node <T>* expression_ptr;
          typedef stringvar_node  <T>* strvar_node_ptr;
-         typedef string_base_node<T>*    str_base_ptr;
-         typedef range_pack      <T>          range_t;
-         typedef range_t*                   range_ptr;
-         typedef range_interface<T>          irange_t;
-         typedef irange_t*                 irange_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+
+         using binary_node<T>::branch;
 
          swap_string_node(expression_ptr branch0, expression_ptr branch1)
-         : binary_node<T>(details::e_swap, branch0, branch1),
-           initialised_(false),
-           str0_node_ptr_(0),
-           str1_node_ptr_(0)
+         : binary_node<T>(details::e_swap, branch0, branch1)
+         , initialised_(false)
+         , str0_node_ptr_(0)
+         , str1_node_ptr_(0)
          {
-            if (is_string_node(binary_node<T>::branch_[0].first))
+            if (is_string_node(branch(0)))
             {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
             }
 
-            if (is_string_node(binary_node<T>::branch_[1].first))
+            if (is_string_node(branch(1)))
             {
-               str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
+               str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1));
             }
 
             initialised_ = (str0_node_ptr_ && str1_node_ptr_);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
-
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+            branch(0)->value();
+            branch(1)->value();
 
-               std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
-            }
+            std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return str0_node_ptr_->str();
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
            return str0_node_ptr_->base();
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return str0_node_ptr_->size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return str0_node_ptr_->range_ref();
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return str0_node_ptr_->range_ref();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strswap;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && binary_node<T>::valid();
+         }
+
       private:
 
          bool initialised_;
@@ -8717,34 +10746,36 @@ namespace exprtk
       };
 
       template <typename T>
-      class swap_genstrings_node : public binary_node<T>
+      class swap_genstrings_node exprtk_final : public binary_node<T>
       {
       public:
 
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface<T>   irange_t;
+         typedef irange_t*            irange_ptr;
          typedef expression_node <T>* expression_ptr;
-         typedef string_base_node<T>*   str_base_ptr;
-         typedef range_pack      <T>         range_t;
-         typedef range_t*                  range_ptr;
-         typedef range_interface<T>         irange_t;
-         typedef irange_t*                irange_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+
+         using binary_node<T>::branch;
 
          swap_genstrings_node(expression_ptr branch0,
                               expression_ptr branch1)
-         : binary_node<T>(details::e_default, branch0, branch1),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_range_ptr_(0),
-           str1_range_ptr_(0),
-           initialised_(false)
+         : binary_node<T>(details::e_default, branch0, branch1)
+         , str0_base_ptr_ (0)
+         , str1_base_ptr_ (0)
+         , str0_range_ptr_(0)
+         , str1_range_ptr_(0)
+         , initialised_(false)
          {
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == range)
                   return;
@@ -8752,14 +10783,14 @@ namespace exprtk
                str0_range_ptr_ = &(range->range_ref());
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -8771,100 +10802,101 @@ namespace exprtk
                            str1_base_ptr_  &&
                            str0_range_ptr_ &&
                            str1_range_ptr_ ;
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+            branch(0)->value();
+            branch(1)->value();
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+            std::size_t str0_r0 = 0;
+            std::size_t str0_r1 = 0;
 
-               std::size_t str0_r0 = 0;
-               std::size_t str0_r1 = 0;
+            std::size_t str1_r0 = 0;
+            std::size_t str1_r1 = 0;
 
-               std::size_t str1_r0 = 0;
-               std::size_t str1_r1 = 0;
+            const range_t& range0 = (*str0_range_ptr_);
+            const range_t& range1 = (*str1_range_ptr_);
 
-               const range_t& range0 = (*str0_range_ptr_);
-               const range_t& range1 = (*str1_range_ptr_);
+            if (
+                  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
+                  range1(str1_r0, str1_r1, str1_base_ptr_->size())
+               )
+            {
+               const std::size_t size0    = range0.cache_size();
+               const std::size_t size1    = range1.cache_size();
+               const std::size_t max_size = std::min(size0,size1);
 
-               if (
-                    range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
-                    range1(str1_r0, str1_r1, str1_base_ptr_->size())
-                  )
-               {
-                  const std::size_t size0    = range0.cache_size();
-                  const std::size_t size1    = range1.cache_size();
-                  const std::size_t max_size = std::min(size0,size1);
+               char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
+               char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
 
-                  char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
-                  char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
+               loop_unroll::details lud(max_size);
+               char_cptr upper_bound = s0 + lud.upper_bound;
 
-                  loop_unroll::details lud(max_size);
-                  char_cptr upper_bound = s0 + lud.upper_bound;
+               while (s0 < upper_bound)
+               {
+                  #define exprtk_loop(N)   \
+                  std::swap(s0[N], s1[N]); \
 
-                  while (s0 < upper_bound)
-                  {
-                     #define exprtk_loop(N)   \
-                     std::swap(s0[N], s1[N]); \
-
-                     exprtk_loop( 0) exprtk_loop( 1)
-                     exprtk_loop( 2) exprtk_loop( 3)
-                     #ifndef exprtk_disable_superscalar_unroll
-                     exprtk_loop( 4) exprtk_loop( 5)
-                     exprtk_loop( 6) exprtk_loop( 7)
-                     exprtk_loop( 8) exprtk_loop( 9)
-                     exprtk_loop(10) exprtk_loop(11)
-                     exprtk_loop(12) exprtk_loop(13)
-                     exprtk_loop(14) exprtk_loop(15)
-                     #endif
-
-                     s0 += lud.batch_size;
-                     s1 += lud.batch_size;
-                  }
+                  exprtk_loop( 0) exprtk_loop( 1)
+                  exprtk_loop( 2) exprtk_loop( 3)
+                  #ifndef exprtk_disable_superscalar_unroll
+                  exprtk_loop( 4) exprtk_loop( 5)
+                  exprtk_loop( 6) exprtk_loop( 7)
+                  exprtk_loop( 8) exprtk_loop( 9)
+                  exprtk_loop(10) exprtk_loop(11)
+                  exprtk_loop(12) exprtk_loop(13)
+                  exprtk_loop(14) exprtk_loop(15)
+                  #endif
 
-                  int i = 0;
+                  s0 += lud.batch_size;
+                  s1 += lud.batch_size;
+               }
 
-                  exprtk_disable_fallthrough_begin
-                  switch (lud.remainder)
-                  {
-                     #define case_stmt(N)                       \
-                     case N : { std::swap(s0[i], s1[i]); ++i; } \
-
-                     #ifndef exprtk_disable_superscalar_unroll
-                     case_stmt(15) case_stmt(14)
-                     case_stmt(13) case_stmt(12)
-                     case_stmt(11) case_stmt(10)
-                     case_stmt( 9) case_stmt( 8)
-                     case_stmt( 7) case_stmt( 6)
-                     case_stmt( 5) case_stmt( 4)
-                     #endif
-                     case_stmt( 3) case_stmt( 2)
-                     case_stmt( 1)
-                  }
-                  exprtk_disable_fallthrough_end
+               int i = 0;
 
-                  #undef exprtk_loop
-                  #undef case_stmt
+               switch (lud.remainder)
+               {
+                  #define case_stmt(N)                       \
+                  case N : { std::swap(s0[i], s1[i]); ++i; } \
+                  exprtk_fallthrough                         \
+
+                  #ifndef exprtk_disable_superscalar_unroll
+                  case_stmt(15) case_stmt(14)
+                  case_stmt(13) case_stmt(12)
+                  case_stmt(11) case_stmt(10)
+                  case_stmt( 9) case_stmt( 8)
+                  case_stmt( 7) case_stmt( 6)
+                  case_stmt( 5) case_stmt( 4)
+                  #endif
+                  case_stmt( 3) case_stmt( 2)
+                  case_stmt( 1)
+                  default: break;
                }
+
+               #undef exprtk_loop
+               #undef case_stmt
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strswap;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && binary_node<T>::valid();
+         }
+
       private:
 
-         swap_genstrings_node(swap_genstrings_node<T>&);
-         swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
+         swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete;
+         swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete;
 
          str_base_ptr str0_base_ptr_;
          str_base_ptr str1_base_ptr_;
@@ -8874,11 +10906,11 @@ namespace exprtk
       };
 
       template <typename T>
-      class stringvar_size_node : public expression_node<T>
+      class stringvar_size_node exprtk_final : public expression_node<T>
       {
       public:
 
-         static std::string null_value;
+         static const std::string null_value;
 
          explicit stringvar_size_node()
          : value_(&null_value)
@@ -8888,34 +10920,33 @@ namespace exprtk
          : value_(&v)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return T((*value_).size());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_stringvarsize;
          }
 
       private:
 
-         std::string* value_;
+         const std::string* value_;
       };
 
       template <typename T>
-      std::string stringvar_size_node<T>::null_value = std::string("");
+      const std::string stringvar_size_node<T>::null_value = std::string("");
 
       template <typename T>
-      class string_size_node : public expression_node<T>
+      class string_size_node exprtk_final : public expression_node<T>
       {
       public:
 
-         typedef expression_node <T>*      expression_ptr;
-         typedef string_base_node<T>*        str_base_ptr;
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>* str_base_ptr;
          typedef std::pair<expression_ptr,bool>  branch_t;
 
-
          explicit string_size_node(expression_ptr branch)
          : str_base_ptr_(0)
          {
@@ -8924,43 +10955,40 @@ namespace exprtk
             if (is_generally_string_node(branch_.first))
             {
                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
-
-               if (0 == str_base_ptr_)
-                  return;
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            T result = std::numeric_limits<T>::quiet_NaN();
-
-            if (str_base_ptr_)
-            {
-               branch_.first->value();
-               result = T(str_base_ptr_->size());
-            }
-
-            return result;
+            branch_.first->value();
+            return T(str_base_ptr_->size());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_stringsize;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return str_base_ptr_;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         branch_t           branch_;
+         branch_t     branch_;
          str_base_ptr str_base_ptr_;
       };
 
@@ -8977,45 +11005,47 @@ namespace exprtk
       };
 
       template <typename T, typename AssignmentProcess = asn_assignment>
-      class assignment_string_node : public binary_node     <T>,
-                                     public string_base_node<T>,
-                                     public range_interface <T>
+      class assignment_string_node exprtk_final
+                                   : public binary_node     <T>
+                                   , public string_base_node<T>
+                                   , public range_interface <T>
       {
       public:
 
-         typedef expression_node <T>*  expression_ptr;
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface <T>  irange_t;
+         typedef irange_t*            irange_ptr;
+         typedef expression_node <T>* expression_ptr;
          typedef stringvar_node  <T>* strvar_node_ptr;
-         typedef string_base_node<T>*    str_base_ptr;
-         typedef range_pack      <T>          range_t;
-         typedef range_t*                   range_ptr;
-         typedef range_interface<T>          irange_t;
-         typedef irange_t*                 irange_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+
+         using binary_node<T>::branch;
 
          assignment_string_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           initialised_(false),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_node_ptr_ (0),
-           str1_range_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , initialised_(false)
+         , str0_base_ptr_ (0)
+         , str1_base_ptr_ (0)
+         , str0_node_ptr_ (0)
+         , str1_range_ptr_(0)
          {
-            if (is_string_node(binary_node<T>::branch_[0].first))
+            if (is_string_node(branch(0)))
             {
-               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
-
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -9027,65 +11057,66 @@ namespace exprtk
                            str1_base_ptr_  &&
                            str0_node_ptr_  &&
                            str1_range_ptr_ ;
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+            branch(1)->value();
 
-               binary_node<T>::branch_[1].first->value();
-
-               std::size_t r0 = 0;
-               std::size_t r1 = 0;
+            std::size_t r0 = 0;
+            std::size_t r1 = 0;
 
-               const range_t& range = (*str1_range_ptr_);
+            const range_t& range = (*str1_range_ptr_);
 
-               if (range(r0, r1, str1_base_ptr_->size()))
-               {
-                  AssignmentProcess::execute(str0_node_ptr_->ref(),
-                                             str1_base_ptr_->base() + r0,
-                                             (r1 - r0) + 1);
+            if (range(r0, r1, str1_base_ptr_->size()))
+            {
+               AssignmentProcess::execute(
+                  str0_node_ptr_->ref(),
+                  str1_base_ptr_->base() + r0, (r1 - r0));
 
-                  binary_node<T>::branch_[0].first->value();
-               }
+               branch(0)->value();
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return str0_node_ptr_->str();
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
            return str0_node_ptr_->base();
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return str0_node_ptr_->size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return str0_node_ptr_->range_ref();
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return str0_node_ptr_->range_ref();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strass;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && binary_node<T>::valid();
+         }
+
       private:
 
          bool            initialised_;
@@ -9096,39 +11127,40 @@ namespace exprtk
       };
 
       template <typename T, typename AssignmentProcess = asn_assignment>
-      class assignment_string_range_node : public binary_node     <T>,
-                                           public string_base_node<T>,
-                                           public range_interface <T>
+      class assignment_string_range_node exprtk_final
+                                         : public binary_node     <T>
+                                         , public string_base_node<T>
+                                         , public range_interface <T>
       {
       public:
 
-         typedef expression_node  <T>*   expression_ptr;
-         typedef stringvar_node   <T>*  strvar_node_ptr;
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*              range_ptr;
+         typedef range_interface  <T>  irange_t;
+         typedef irange_t*             irange_ptr;
+         typedef expression_node  <T>* expression_ptr;
+         typedef stringvar_node   <T>* strvar_node_ptr;
          typedef string_range_node<T>* str_rng_node_ptr;
-         typedef string_base_node <T>*     str_base_ptr;
-         typedef range_pack       <T>           range_t;
-         typedef range_t*                     range_ptr;
-         typedef range_interface<T>            irange_t;
-         typedef irange_t*                   irange_ptr;
+         typedef string_base_node <T>* str_base_ptr;
+
+         using binary_node<T>::branch;
 
          assignment_string_range_node(const operator_type& opr,
                                       expression_ptr branch0,
                                       expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           initialised_(false),
-           str0_base_ptr_     (0),
-           str1_base_ptr_     (0),
-           str0_rng_node_ptr_ (0),
-           str0_range_ptr_    (0),
-           str1_range_ptr_    (0)
+         : binary_node<T>(opr, branch0, branch1)
+         , initialised_(false)
+         , str0_base_ptr_    (0)
+         , str1_base_ptr_    (0)
+         , str0_rng_node_ptr_(0)
+         , str0_range_ptr_   (0)
+         , str1_range_ptr_   (0)
          {
-            if (is_string_range_node(binary_node<T>::branch_[0].first))
+            if (is_string_range_node(branch(0)))
             {
-               str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first);
-
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
-
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0));
+               str0_base_ptr_     = dynamic_cast<str_base_ptr>(branch(0));
+               irange_ptr range   = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == range)
                   return;
@@ -9136,14 +11168,14 @@ namespace exprtk
                str0_range_ptr_ = &(range->range_ref());
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
@@ -9156,73 +11188,75 @@ namespace exprtk
                            str0_rng_node_ptr_ &&
                            str0_range_ptr_    &&
                            str1_range_ptr_    ;
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
-
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+            branch(0)->value();
+            branch(1)->value();
 
-               std::size_t s0_r0 = 0;
-               std::size_t s0_r1 = 0;
+            std::size_t s0_r0 = 0;
+            std::size_t s0_r1 = 0;
 
-               std::size_t s1_r0 = 0;
-               std::size_t s1_r1 = 0;
+            std::size_t s1_r0 = 0;
+            std::size_t s1_r1 = 0;
 
-               const range_t& range0 = (*str0_range_ptr_);
-               const range_t& range1 = (*str1_range_ptr_);
+            const range_t& range0 = (*str0_range_ptr_);
+            const range_t& range1 = (*str1_range_ptr_);
 
-               if (
-                    range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
-                    range1(s1_r0, s1_r1, str1_base_ptr_->size())
-                  )
-               {
-                  const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
+            if (
+                  range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
+                  range1(s1_r0, s1_r1, str1_base_ptr_->size())
+               )
+            {
+               const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0));
 
-                  std::copy(str1_base_ptr_->base() + s1_r0,
-                            str1_base_ptr_->base() + s1_r0 + size,
-                            const_cast<char_ptr>(base() + s0_r0));
-               }
+               std::copy(
+                  str1_base_ptr_->base() + s1_r0,
+                  str1_base_ptr_->base() + s1_r0 + size,
+                  const_cast<char_ptr>(base() + s0_r0));
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return str0_base_ptr_->str();
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
             return str0_base_ptr_->base();
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return str0_base_ptr_->size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return str0_rng_node_ptr_->range_ref();
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return str0_rng_node_ptr_->range_ref();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strass;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return initialised_ && binary_node<T>::valid();
+         }
+
       private:
 
          bool             initialised_;
@@ -9234,31 +11268,32 @@ namespace exprtk
       };
 
       template <typename T>
-      class conditional_string_node : public trinary_node    <T>,
-                                      public string_base_node<T>,
-                                      public range_interface <T>
+      class conditional_string_node exprtk_final
+                                    : public trinary_node    <T>
+                                    , public string_base_node<T>
+                                    , public range_interface <T>
       {
       public:
 
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface <T>  irange_t;
+         typedef irange_t*            irange_ptr;
          typedef expression_node <T>* expression_ptr;
-         typedef string_base_node<T>*   str_base_ptr;
-         typedef range_pack      <T>         range_t;
-         typedef range_t*                  range_ptr;
-         typedef range_interface<T>         irange_t;
-         typedef irange_t*                irange_ptr;
+         typedef string_base_node<T>* str_base_ptr;
 
          conditional_string_node(expression_ptr condition,
                                  expression_ptr consequent,
                                  expression_ptr alternative)
-         : trinary_node<T>(details::e_default,consequent,alternative,condition),
-           initialised_(false),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_range_ptr_(0),
-           str1_range_ptr_(0),
-           condition_    (condition),
-           consequent_  (consequent),
-           alternative_(alternative)
+         : trinary_node<T>(details::e_default, consequent, alternative, condition)
+         , initialised_(false)
+         , str0_base_ptr_ (0)
+         , str1_base_ptr_ (0)
+         , str0_range_ptr_(0)
+         , str1_range_ptr_(0)
+         , condition_  (condition  )
+         , consequent_ (consequent )
+         , alternative_(alternative)
          {
             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
@@ -9297,90 +11332,93 @@ namespace exprtk
                            str0_range_ptr_ &&
                            str1_range_ptr_ ;
 
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
+            std::size_t r0 = 0;
+            std::size_t r1 = 0;
+
+            if (is_true(condition_))
             {
-               assert(condition_  );
-               assert(consequent_ );
-               assert(alternative_);
+               consequent_->value();
 
-               std::size_t r0 = 0;
-               std::size_t r1 = 0;
+               const range_t& range = str0_range_ptr_->range_ref();
 
-               if (is_true(condition_))
+               if (range(r0, r1, str0_base_ptr_->size()))
                {
-                  consequent_->value();
+                  const std::size_t size = (r1 - r0);
 
-                  const range_t& range = str0_range_ptr_->range_ref();
+                  value_.assign(str0_base_ptr_->base() + r0, size);
 
-                  if (range(r0, r1, str0_base_ptr_->size()))
-                  {
-                     const std::size_t size = (r1 - r0) + 1;
-
-                     value_.assign(str0_base_ptr_->base() + r0, size);
-
-                     range_.n1_c.second  = value_.size() - 1;
-                     range_.cache.second = range_.n1_c.second;
+                  range_.n1_c.second  = value_.size();
+                  range_.cache.second = range_.n1_c.second;
 
-                     return T(1);
-                  }
+                  return T(1);
                }
-               else
-               {
-                  alternative_->value();
+            }
+            else
+            {
+               alternative_->value();
 
-                  const range_t& range = str1_range_ptr_->range_ref();
+               const range_t& range = str1_range_ptr_->range_ref();
 
-                  if (range(r0, r1, str1_base_ptr_->size()))
-                  {
-                     const std::size_t size = (r1 - r0) + 1;
+               if (range(r0, r1, str1_base_ptr_->size()))
+               {
+                  const std::size_t size = (r1 - r0);
 
-                     value_.assign(str1_base_ptr_->base() + r0, size);
+                  value_.assign(str1_base_ptr_->base() + r0, size);
 
-                     range_.n1_c.second  = value_.size() - 1;
-                     range_.cache.second = range_.n1_c.second;
+                  range_.n1_c.second  = value_.size();
+                  range_.cache.second = range_.n1_c.second;
 
-                     return T(0);
-                  }
+                  return T(0);
                }
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return value_;
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
             return &value_[0];
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return value_.size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return range_;
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return range_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strcondition;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return
+               initialised_                         &&
+               condition_  && condition_  ->valid() &&
+               consequent_ && consequent_ ->valid() &&
+               alternative_&& alternative_->valid() ;
+         }
+
       private:
 
          bool initialised_;
@@ -9397,27 +11435,30 @@ namespace exprtk
       };
 
       template <typename T>
-      class cons_conditional_str_node : public binary_node     <T>,
-                                        public string_base_node<T>,
-                                        public range_interface <T>
+      class cons_conditional_str_node exprtk_final
+                                      : public binary_node     <T>
+                                      , public string_base_node<T>
+                                      , public range_interface <T>
       {
       public:
 
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface <T>  irange_t;
+         typedef irange_t*            irange_ptr;
          typedef expression_node <T>* expression_ptr;
-         typedef string_base_node<T>*   str_base_ptr;
-         typedef range_pack      <T>         range_t;
-         typedef range_t*                  range_ptr;
-         typedef range_interface<T>         irange_t;
-         typedef irange_t*                irange_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+
+         using binary_node<T>::branch;
 
          cons_conditional_str_node(expression_ptr condition,
                                    expression_ptr consequent)
-         : binary_node<T>(details::e_default, consequent, condition),
-           initialised_(false),
-           str0_base_ptr_ (0),
-           str0_range_ptr_(0),
-           condition_ (condition),
-           consequent_(consequent)
+         : binary_node<T>(details::e_default, consequent, condition)
+         , initialised_(false)
+         , str0_base_ptr_ (0)
+         , str0_range_ptr_(0)
+         , condition_ (condition )
+         , consequent_(consequent)
          {
             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
@@ -9425,49 +11466,44 @@ namespace exprtk
             range_.cache.first  = range_.n0_c.second;
             range_.cache.second = range_.n1_c.second;
 
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == str0_range_ptr_)
                   return;
             }
 
             initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
+            if (is_true(condition_))
             {
-               assert(condition_ );
-               assert(consequent_);
-
-               if (is_true(condition_))
-               {
-                  consequent_->value();
+               consequent_->value();
 
-                  const range_t& range = str0_range_ptr_->range_ref();
+               const range_t& range = str0_range_ptr_->range_ref();
 
-                  std::size_t r0 = 0;
-                  std::size_t r1 = 0;
+               std::size_t r0 = 0;
+               std::size_t r1 = 0;
 
-                  if (range(r0, r1, str0_base_ptr_->size()))
-                  {
-                     const std::size_t size = (r1 - r0) + 1;
+               if (range(r0, r1, str0_base_ptr_->size()))
+               {
+                  const std::size_t size = (r1 - r0);
 
-                     value_.assign(str0_base_ptr_->base() + r0, size);
+                  value_.assign(str0_base_ptr_->base() + r0, size);
 
-                     range_.n1_c.second  = value_.size() - 1;
-                     range_.cache.second = range_.n1_c.second;
+                  range_.n1_c.second  = value_.size();
+                  range_.cache.second = range_.n1_c.second;
 
-                     return T(1);
-                  }
+                  return T(1);
                }
             }
 
@@ -9499,11 +11535,19 @@ namespace exprtk
             return range_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strccondition;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return
+               initialised_                         &&
+               condition_  && condition_  ->valid() &&
+               consequent_ && consequent_ ->valid() ;
+         }
+
       private:
 
          bool initialised_;
@@ -9517,26 +11561,27 @@ namespace exprtk
       };
 
       template <typename T, typename VarArgFunction>
-      class str_vararg_node  : public expression_node <T>,
-                               public string_base_node<T>,
-                               public range_interface <T>
+      class str_vararg_node exprtk_final
+                            : public expression_node <T>
+                            , public string_base_node<T>
+                            , public range_interface <T>
       {
       public:
 
-         typedef expression_node <T>*     expression_ptr;
-         typedef string_base_node<T>*       str_base_ptr;
-         typedef range_pack      <T>             range_t;
-         typedef range_t*                      range_ptr;
-         typedef range_interface<T>             irange_t;
-         typedef irange_t*                    irange_ptr;
+         typedef typename range_interface<T>::range_t range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface <T>  irange_t;
+         typedef irange_t*            irange_ptr;
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>* str_base_ptr;
          typedef std::pair<expression_ptr,bool> branch_t;
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
          explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
-         : initialised_(false),
-           str_base_ptr_ (0),
-           str_range_ptr_(0)
+         : initialised_(false)
+         , str_base_ptr_ (0)
+         , str_range_ptr_(0)
          {
             construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
 
@@ -9555,8 +11600,6 @@ namespace exprtk
             if (0 == str_range_ptr_)
                return;
 
-            initialised_ = str_base_ptr_  && str_range_ptr_;
-
             if (arg_list.size() > 1)
             {
                const std::size_t arg_list_size = arg_list.size() - 1;
@@ -9565,7 +11608,7 @@ namespace exprtk
 
                for (std::size_t i = 0; i < arg_list_size; ++i)
                {
-                  if (arg_list[i])
+                  if (arg_list[i] && arg_list[i]->valid())
                   {
                      construct_branch_pair(arg_list_[i], arg_list[i]);
                   }
@@ -9575,10 +11618,15 @@ namespace exprtk
                      return;
                   }
                }
+
+               initialised_ = true;
             }
+
+            initialised_ &= str_base_ptr_ && str_range_ptr_;
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             if (!arg_list_.empty())
             {
@@ -9590,43 +11638,50 @@ namespace exprtk
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         std::string str() const
+         std::string str() const exprtk_override
          {
             return str_base_ptr_->str();
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
             return str_base_ptr_->base();
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return str_base_ptr_->size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return str_range_ptr_->range_ref();
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return str_range_ptr_->range_ref();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_stringvararg;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return
+               initialised_ &&
+               final_node_.first && final_node_.first->valid();
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::collect(final_node_, node_delete_list);
-            expression_node<T>::ndb_t::collect(arg_list_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(final_node_ , node_delete_list);
+            expression_node<T>::ndb_t::collect(arg_list_   , node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return std::max(
                expression_node<T>::ndb_t::compute_node_depth(final_node_),
@@ -9643,15 +11698,113 @@ namespace exprtk
       };
       #endif
 
+      template <typename T>
+      class assert_node exprtk_final : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef string_base_node<T>* str_base_ptr;
+         typedef assert_check::assert_context assert_context_t;
+
+         assert_node(expression_ptr   assert_condition_node,
+                     expression_ptr   assert_message_node,
+                     assert_check_ptr assert_check,
+                     assert_context_t context)
+         : assert_message_str_base_(0)
+         , assert_check_(assert_check)
+         , context_(context)
+         {
+            construct_branch_pair(assert_condition_node_, assert_condition_node);
+            construct_branch_pair(assert_message_node_  , assert_message_node  );
+
+            #ifndef exprtk_disable_string_capabilities
+            if (
+                  assert_message_node_.first &&
+                  details::is_generally_string_node(assert_message_node_.first)
+               )
+            {
+               assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first);
+            }
+            #endif
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            if (details::is_true(assert_condition_node_.first->value()))
+            {
+               return T(1);
+            }
+
+            #ifndef exprtk_disable_string_capabilities
+            if (assert_message_node_.first)
+            {
+               assert_message_node_.first->value();
+               assert(assert_message_str_base_);
+               context_.message = assert_message_str_base_->str();
+            }
+            #endif
+
+            assert_check_->handle_assert(context_);
+            return T(0);
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_assert;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return (
+                     assert_check_ &&
+                     assert_condition_node_.first &&
+                     assert_condition_node_.first->valid()
+                   ) &&
+                   (
+                     (0 == assert_message_node_.first) ||
+                     (
+                       assert_message_node_.first &&
+                       assert_message_str_base_   &&
+                       assert_message_node_.first->valid() &&
+                       details::is_generally_string_node(assert_message_node_.first)
+                     )
+                   );
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list);
+            expression_node<T>::ndb_t::collect(assert_message_node_  , node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (assert_condition_node_, assert_message_node_);
+         }
+
+      private:
+
+         branch_t         assert_condition_node_;
+         branch_t         assert_message_node_;
+         str_base_ptr     assert_message_str_base_;
+         assert_check_ptr assert_check_;
+         mutable assert_context_t context_;
+      };
+
       template <typename T, std::size_t N>
-      inline T axn(T a, T x)
+      inline T axn(const T a, const T x)
       {
          // a*x^n
          return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
       }
 
       template <typename T, std::size_t N>
-      inline T axnb(T a, T x, T b)
+      inline T axnb(const T a, const T x, const T b)
       {
          // a*x^n+b
          return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
@@ -9663,12 +11816,12 @@ namespace exprtk
          typedef typename details::functor_t<T>::Type Type;
          typedef typename details::functor_t<T> functor_t;
          typedef typename functor_t::qfunc_t quaternary_functor_t;
-         typedef typename functor_t::tfunc_t    trinary_functor_t;
-         typedef typename functor_t::bfunc_t     binary_functor_t;
-         typedef typename functor_t::ufunc_t      unary_functor_t;
+         typedef typename functor_t::tfunc_t trinary_functor_t;
+         typedef typename functor_t::bfunc_t binary_functor_t;
+         typedef typename functor_t::ufunc_t unary_functor_t;
       };
 
-      #define define_sfop3(NN,OP0,OP1)                   \
+      #define define_sfop3(NN, OP0, OP1)                 \
       template <typename T>                              \
       struct sf##NN##_op : public sf_base<T>             \
       {                                                  \
@@ -9732,7 +11885,7 @@ namespace exprtk
       define_sfop3(46,x * numeric::cos(y) - z  ,"")
       define_sfop3(47,details::is_true(x) ? y : z,"")
 
-      #define define_sfop4(NN,OP0,OP1)                           \
+      #define define_sfop4(NN, OP0, OP1)                         \
       template <typename T>                                      \
       struct sf##NN##_op : public sf_base<T>                     \
       {                                                          \
@@ -9868,7 +12021,7 @@ namespace exprtk
       #undef define_sfop4
 
       template <typename T, typename SpecialFunction>
-      class sf3_node : public trinary_node<T>
+      class sf3_node exprtk_final : public trinary_node<T>
       {
       public:
 
@@ -9881,12 +12034,8 @@ namespace exprtk
          : trinary_node<T>(opr, branch0, branch1, branch2)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(trinary_node<T>::branch_[0].first);
-            assert(trinary_node<T>::branch_[1].first);
-            assert(trinary_node<T>::branch_[2].first);
-
             const T x = trinary_node<T>::branch_[0].first->value();
             const T y = trinary_node<T>::branch_[1].first->value();
             const T z = trinary_node<T>::branch_[2].first->value();
@@ -9896,7 +12045,7 @@ namespace exprtk
       };
 
       template <typename T, typename SpecialFunction>
-      class sf4_node : public quaternary_node<T>
+      class sf4_node exprtk_final : public quaternary_node<T>
       {
       public:
 
@@ -9910,13 +12059,8 @@ namespace exprtk
          : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(quaternary_node<T>::branch_[0].first);
-            assert(quaternary_node<T>::branch_[1].first);
-            assert(quaternary_node<T>::branch_[2].first);
-            assert(quaternary_node<T>::branch_[3].first);
-
             const T x = quaternary_node<T>::branch_[0].first->value();
             const T y = quaternary_node<T>::branch_[1].first->value();
             const T z = quaternary_node<T>::branch_[2].first->value();
@@ -9927,32 +12071,32 @@ namespace exprtk
       };
 
       template <typename T, typename SpecialFunction>
-      class sf3_var_node : public expression_node<T>
+      class sf3_var_node exprtk_final : public expression_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
 
          sf3_var_node(const T& v0, const T& v1, const T& v2)
-         : v0_(v0),
-           v1_(v1),
-           v2_(v2)
+         : v0_(v0)
+         , v1_(v1)
+         , v2_(v2)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return SpecialFunction::process(v0_, v1_, v2_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_trinary;
          }
 
       private:
 
-         sf3_var_node(sf3_var_node<T,SpecialFunction>&);
-         sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
+         sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
+         sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
 
          const T& v0_;
          const T& v1_;
@@ -9960,33 +12104,33 @@ namespace exprtk
       };
 
       template <typename T, typename SpecialFunction>
-      class sf4_var_node : public expression_node<T>
+      class sf4_var_node exprtk_final : public expression_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
 
          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
-         : v0_(v0),
-           v1_(v1),
-           v2_(v2),
-           v3_(v3)
+         : v0_(v0)
+         , v1_(v1)
+         , v2_(v2)
+         , v3_(v3)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return SpecialFunction::process(v0_, v1_, v2_, v3_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_trinary;
          }
 
       private:
 
-         sf4_var_node(sf4_var_node<T,SpecialFunction>&);
-         sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
+         sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
+         sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
 
          const T& v0_;
          const T& v1_;
@@ -9995,7 +12139,7 @@ namespace exprtk
       };
 
       template <typename T, typename VarArgFunction>
-      class vararg_node : public expression_node<T>
+      class vararg_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -10005,12 +12149,13 @@ namespace exprtk
          template <typename Allocator,
                    template <typename, typename> class Sequence>
          explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
+         : initialised_(false)
          {
             arg_list_.resize(arg_list.size());
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
-               if (arg_list[i])
+               if (arg_list[i] && arg_list[i]->valid())
                {
                   construct_branch_pair(arg_list_[i],arg_list[i]);
                }
@@ -10020,35 +12165,54 @@ namespace exprtk
                   return;
                }
             }
+
+            initialised_ = (arg_list_.size() == arg_list.size());
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return VarArgFunction::process(arg_list_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vararg;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return initialised_;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
          }
 
+         std::size_t size() const
+         {
+            return arg_list_.size();
+         }
+
+         expression_ptr operator[](const std::size_t& index) const
+         {
+            return arg_list_[index].first;
+         }
+
       private:
 
          std::vector<branch_t> arg_list_;
+         bool initialised_;
       };
 
       template <typename T, typename VarArgFunction>
-      class vararg_varnode : public expression_node<T>
+      class vararg_varnode exprtk_final : public expression_node<T>
       {
       public:
 
@@ -10057,12 +12221,13 @@ namespace exprtk
          template <typename Allocator,
                    template <typename, typename> class Sequence>
          explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
+         : initialised_(false)
          {
             arg_list_.resize(arg_list.size());
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
             {
-               if (arg_list[i] && is_variable_node(arg_list[i]))
+               if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i]))
                {
                   variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
                   arg_list_[i] = (&var_node_ptr->ref());
@@ -10073,28 +12238,34 @@ namespace exprtk
                   return;
                }
             }
+
+            initialised_ = (arg_list.size() == arg_list_.size());
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (!arg_list_.empty())
-               return VarArgFunction::process(arg_list_);
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return VarArgFunction::process(arg_list_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vararg;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return initialised_;
+         }
+
       private:
 
          std::vector<const T*> arg_list_;
+         bool initialised_;
       };
 
       template <typename T, typename VecFunction>
-      class vectorize_node : public expression_node<T>
+      class vectorize_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -10110,35 +12281,30 @@ namespace exprtk
             {
                ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
             }
-            else
-               ivec_ptr_ = 0;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (ivec_ptr_)
-            {
-               assert(v_.first);
-
-               v_.first->value();
-
-               return VecFunction::process(ivec_ptr_);
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            v_.first->value();
+            return VecFunction::process(ivec_ptr_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecfunc;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return ivec_ptr_ && v_.first && v_.first->valid();
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(v_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(v_);
          }
@@ -10150,38 +12316,36 @@ namespace exprtk
       };
 
       template <typename T>
-      class assignment_node : public binary_node<T>
+      class assignment_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_node(const operator_type& opr,
                          expression_ptr branch0,
                          expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           var_node_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , var_node_ptr_(0)
          {
-            if (is_variable_node(binary_node<T>::branch_[0].first))
+            if (is_variable_node(branch(0)))
             {
-               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+               var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
             }
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (var_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& result = var_node_ptr_->ref();
+               result = branch(1)->value();
 
-               T& result = var_node_ptr_->ref();
-
-               result = binary_node<T>::branch_[1].first->value();
+            return result;
+         }
 
-               return result;
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return var_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
@@ -10190,118 +12354,198 @@ namespace exprtk
       };
 
       template <typename T>
-      class assignment_vec_elem_node : public binary_node<T>
+      class assignment_vec_elem_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_vec_elem_node(const operator_type& opr,
                                   expression_ptr branch0,
                                   expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec_node_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
          {
-            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_vector_elem_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (vec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& result = vec_node_ptr_->ref();
+               result = branch(1)->value();
 
-               T& result = vec_node_ptr_->ref();
+            return result;
+         }
 
-               result = binary_node<T>::branch_[1].first->value();
+         inline bool valid() const exprtk_override
+         {
+            return vec_node_ptr_ && binary_node<T>::valid();
+         }
 
-               return result;
+      private:
+
+         vector_elem_node<T>* vec_node_ptr_;
+      };
+
+      template <typename T>
+      class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
+
+         assignment_vec_elem_rtc_node(const operator_type& opr,
+                                      expression_ptr branch0,
+                                      expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
+         {
+            if (is_vector_elem_rtc_node(branch(0)))
+            {
+               vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T& result = vec_node_ptr_->ref();
+               result = branch(1)->value();
+
+            return result;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         vector_elem_node<T>* vec_node_ptr_;
+         vector_elem_rtc_node<T>* vec_node_ptr_;
       };
 
       template <typename T>
-      class assignment_rebasevec_elem_node : public binary_node<T>
+      class assignment_rebasevec_elem_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using expression_node<T>::branch;
 
          assignment_rebasevec_elem_node(const operator_type& opr,
                                         expression_ptr branch0,
                                         expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           rbvec_node_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_elem_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (rbvec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& result = rbvec_node_ptr_->ref();
+               result = branch(1)->value();
+
+            return result;
+         }
 
-               T& result = rbvec_node_ptr_->ref();
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
+         }
 
-               result = binary_node<T>::branch_[1].first->value();
+      private:
 
-               return result;
+         rebasevector_elem_node<T>* rbvec_node_ptr_;
+      };
+
+      template <typename T>
+      class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         using expression_node<T>::branch;
+
+         assignment_rebasevec_elem_rtc_node(const operator_type& opr,
+                                            expression_ptr branch0,
+                                            expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
+         {
+            if (is_rebasevector_elem_rtc_node(branch(0)))
+            {
+               rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
             }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T& result = rbvec_node_ptr_->ref();
+               result = branch(1)->value();
+
+            return result;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         rebasevector_elem_node<T>* rbvec_node_ptr_;
+         rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
       };
 
       template <typename T>
-      class assignment_rebasevec_celem_node : public binary_node<T>
+      class assignment_rebasevec_celem_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          assignment_rebasevec_celem_node(const operator_type& opr,
                                          expression_ptr branch0,
                                          expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           rbvec_node_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_celem_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (rbvec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
-
-               T& result = rbvec_node_ptr_->ref();
+            T& result = rbvec_node_ptr_->ref();
+               result = branch(1)->value();
 
-               result = binary_node<T>::branch_[1].first->value();
+            return result;
+         }
 
-               return result;
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
@@ -10310,114 +12554,124 @@ namespace exprtk
       };
 
       template <typename T>
-      class assignment_vec_node : public binary_node     <T>,
-                                  public vector_interface<T>
+      class assignment_vec_node exprtk_final
+                                : public binary_node     <T>
+                                , public vector_interface<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
-         typedef vector_node<T>*    vector_node_ptr;
-         typedef vec_data_store<T>            vds_t;
+         typedef vector_node<T>*     vector_node_ptr;
+         typedef vec_data_store<T>   vds_t;
+
+         using binary_node<T>::branch;
 
          assignment_vec_node(const operator_type& opr,
                              expression_ptr branch0,
                              expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec_node_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()         = vec_node_ptr_->vds();
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (vec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            const T v = branch(1)->value();
 
-               const T v = binary_node<T>::branch_[1].first->value();
+            T* vec = vds().data();
 
-               T* vec = vds().data();
-
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec + lud.upper_bound;
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec + lud.upper_bound;
 
-               while (vec < upper_bound)
-               {
-                  #define exprtk_loop(N) \
-                  vec[N] = v;            \
+            while (vec < upper_bound)
+            {
+               #define exprtk_loop(N) \
+               vec[N] = v;            \
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-                  vec += lud.batch_size;
-               }
+               vec += lud.batch_size;
+            }
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N) \
-                  case N : *vec++ = v; \
+            switch (lud.remainder)
+            {
+               #define case_stmt(N) \
+               case N : *vec++ = v; \
+               exprtk_fallthrough   \
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15) case_stmt(14)
+               case_stmt(13) case_stmt(12)
+               case_stmt(11) case_stmt(10)
+               case_stmt( 9) case_stmt( 8)
+               case_stmt( 7) case_stmt( 6)
+               case_stmt( 5) case_stmt( 4)
+               #endif
+               case_stmt( 3) case_stmt( 2)
+               case 1 : *vec++ = v;
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            #undef exprtk_loop
+            #undef case_stmt
 
-               return vec_node_ptr_->value();
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return vec_node_ptr_->value();
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
             return vec_node_ptr_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
             return vec_node_ptr_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecvalass;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return
+               vec_node_ptr_ &&
+               (vds().size() <= vec_node_ptr_->vec_holder().base_size()) &&
+               binary_node<T>::valid();
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return vec_node_ptr_->vec_holder().size();
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds().size();
+            return vec_node_ptr_->vec_holder().base_size();
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
@@ -10429,40 +12683,43 @@ namespace exprtk
       };
 
       template <typename T>
-      class assignment_vecvec_node : public binary_node     <T>,
-                                     public vector_interface<T>
+      class assignment_vecvec_node exprtk_final
+                                   : public binary_node     <T>
+                                   , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*  expression_ptr;
+         typedef expression_node<T>* expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
-         typedef vec_data_store<T>             vds_t;
+         typedef vec_data_store<T>   vds_t;
+
+         using binary_node<T>::branch;
 
          assignment_vecvec_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           initialised_(false),
-           src_is_ivec_(false)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec0_node_ptr_(0)
+         , vec1_node_ptr_(0)
+         , initialised_(false)
+         , src_is_ivec_(false)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()          = vec0_node_ptr_->vds();
             }
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
                vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
 
@@ -10476,384 +12733,570 @@ namespace exprtk
                }
             }
 
-            initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
+            initialised_ =
+               vec0_node_ptr_               &&
+               vec1_node_ptr_               &&
+               (size() <= base_size())      &&
+               (vds_.size() <= base_size()) &&
+               binary_node<T>::valid();
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
+            branch(1)->value();
+
+            if (src_is_ivec_)
+               return vec0_node_ptr_->value();
+
+            T* vec0 = vec0_node_ptr_->vds().data();
+            T* vec1 = vec1_node_ptr_->vds().data();
+
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec0 + lud.upper_bound;
+
+            while (vec0 < upper_bound)
             {
-               assert(binary_node<T>::branch_[1].first);
+               #define exprtk_loop(N) \
+               vec0[N] = vec1[N];     \
 
-               binary_node<T>::branch_[1].first->value();
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-               if (src_is_ivec_)
-                  return vec0_node_ptr_->value();
+               vec0 += lud.batch_size;
+               vec1 += lud.batch_size;
+            }
 
-               T* vec0 = vec0_node_ptr_->vds().data();
-               T* vec1 = vec1_node_ptr_->vds().data();
+            switch (lud.remainder)
+            {
+               #define case_stmt(N,fall_through) \
+               case N : *vec0++ = *vec1++;       \
+               fall_through                      \
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec0 + lud.upper_bound;
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
+               #endif
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
+            }
 
-               while (vec0 < upper_bound)
-               {
-                  #define exprtk_loop(N) \
-                  vec0[N] = vec1[N];     \
+            #undef exprtk_loop
+            #undef case_stmt
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+            return vec0_node_ptr_->value();
+         }
 
-                  vec0 += lud.batch_size;
-                  vec1 += lud.batch_size;
-               }
+         vector_node_ptr vec() exprtk_override
+         {
+            return vec0_node_ptr_;
+         }
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N)        \
-                  case N : *vec0++ = *vec1++; \
+         vector_node_ptr vec() const exprtk_override
+         {
+            return vec0_node_ptr_;
+         }
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecvecass;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return initialised_;
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return std::min(
+               vec0_node_ptr_->vec_holder().size(),
+               vec1_node_ptr_->vec_holder().size());
+         }
+
+         std::size_t base_size() const exprtk_override
+         {
+            return std::min(
+               vec0_node_ptr_->vec_holder().base_size(),
+               vec1_node_ptr_->vec_holder().base_size());
+         }
+
+         vds_t& vds() exprtk_override
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const exprtk_override
+         {
+            return vds_;
+         }
+
+      private:
+
+         vector_node<T>* vec0_node_ptr_;
+         vector_node<T>* vec1_node_ptr_;
+         bool            initialised_;
+         bool            src_is_ivec_;
+         vds_t           vds_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_op_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
+
+         assignment_op_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , var_node_ptr_(0)
+         {
+            if (is_variable_node(branch(0)))
+            {
+               var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
+            }
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T& v = var_node_ptr_->ref();
+            v = Operation::process(v,branch(1)->value());
+
+            return v;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return var_node_ptr_ && binary_node<T>::valid();
+         }
+
+      private:
+
+         variable_node<T>* var_node_ptr_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_vec_elem_op_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
+
+         assignment_vec_elem_op_node(const operator_type& opr,
+                                     expression_ptr branch0,
+                                     expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
+         {
+            if (is_vector_elem_node(branch(0)))
+            {
+               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
+            }
+
+            assert(valid());
+         }
+
+         inline T value() const exprtk_override
+         {
+            T& v = vec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
 
-               #undef exprtk_loop
-               #undef case_stmt
+            return v;
+         }
 
-               return vec0_node_ptr_->value();
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return vec_node_ptr_ && binary_node<T>::valid();
          }
 
-         vector_node_ptr vec() const
+      private:
+
+         vector_elem_node<T>* vec_node_ptr_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
+
+         assignment_vec_elem_op_rtc_node(const operator_type& opr,
+                                         expression_ptr branch0,
+                                         expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
          {
-            return vec0_node_ptr_;
+            if (is_vector_elem_rtc_node(branch(0)))
+            {
+               vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
+            }
+
+            assert(valid());
          }
 
-         vector_node_ptr vec()
+         inline T value() const exprtk_override
          {
-            return vec0_node_ptr_;
+            T& v = vec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
+
+            return v;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline bool valid() const exprtk_override
          {
-            return expression_node<T>::e_vecvecass;
+            return vec_node_ptr_ && binary_node<T>::valid();
          }
 
-         std::size_t size() const
+      private:
+
+         vector_elem_rtc_node<T>* vec_node_ptr_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
+
+         assignment_vec_celem_op_rtc_node(const operator_type& opr,
+                                          expression_ptr branch0,
+                                          expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
          {
-            return vds().size();
+            if (is_vector_celem_rtc_node(branch(0)))
+            {
+               vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0));
+            }
+
+            assert(valid());
          }
 
-         vds_t& vds()
+         inline T value() const exprtk_override
          {
-            return vds_;
+            T& v = vec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
+
+            return v;
          }
 
-         const vds_t& vds() const
+         inline bool valid() const exprtk_override
          {
-            return vds_;
+            return vec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         vector_node<T>* vec0_node_ptr_;
-         vector_node<T>* vec1_node_ptr_;
-         bool            initialised_;
-         bool            src_is_ivec_;
-         vds_t           vds_;
+         vector_celem_rtc_node<T>* vec_node_ptr_;
       };
 
       template <typename T, typename Operation>
-      class assignment_op_node : public binary_node<T>
+      class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
-         assignment_op_node(const operator_type& opr,
-                            expression_ptr branch0,
-                            expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           var_node_ptr_(0)
+         assignment_rebasevec_elem_op_node(const operator_type& opr,
+                                           expression_ptr branch0,
+                                           expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
          {
-            if (is_variable_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_elem_node(branch(0)))
             {
-               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (var_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& v = rbvec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
 
-               T& v = var_node_ptr_->ref();
-               v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+            return v;
+         }
 
-               return v;
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         variable_node<T>* var_node_ptr_;
+         rebasevector_elem_node<T>* rbvec_node_ptr_;
       };
 
       template <typename T, typename Operation>
-      class assignment_vec_elem_op_node : public binary_node<T>
+      class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
-         assignment_vec_elem_op_node(const operator_type& opr,
-                                     expression_ptr branch0,
-                                     expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec_node_ptr_(0)
+         assignment_rebasevec_celem_op_node(const operator_type& opr,
+                                            expression_ptr branch0,
+                                            expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
          {
-            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_celem_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (vec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& v = rbvec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
 
-               T& v = vec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+            return v;
+         }
 
-               return v;
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         vector_elem_node<T>* vec_node_ptr_;
+         rebasevector_celem_node<T>* rbvec_node_ptr_;
       };
 
       template <typename T, typename Operation>
-      class assignment_rebasevec_elem_op_node : public binary_node<T>
+      class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
-         assignment_rebasevec_elem_op_node(const operator_type& opr,
-                                           expression_ptr branch0,
-                                           expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           rbvec_node_ptr_(0)
+         assignment_rebasevec_elem_op_rtc_node(const operator_type& opr,
+                                               expression_ptr branch0,
+                                               expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_elem_rtc_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (rbvec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& v = rbvec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
 
-               T& v = rbvec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+            return v;
+         }
 
-               return v;
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         rebasevector_elem_node<T>* rbvec_node_ptr_;
+         rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
       };
 
       template <typename T, typename Operation>
-      class assignment_rebasevec_celem_op_node : public binary_node<T>
+      class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
-         assignment_rebasevec_celem_op_node(const operator_type& opr,
-                                            expression_ptr branch0,
-                                            expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           rbvec_node_ptr_(0)
+         assignment_rebasevec_celem_op_rtc_node(const operator_type& opr,
+                                                expression_ptr branch0,
+                                                expression_ptr branch1)
+         : binary_node<T>(opr, branch0, branch1)
+         , rbvec_node_ptr_(0)
          {
-            if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
+            if (is_rebasevector_celem_rtc_node(branch(0)))
             {
-               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
+               rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0));
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (rbvec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
+            T& v = rbvec_node_ptr_->ref();
+               v = Operation::process(v,branch(1)->value());
 
-               T& v = rbvec_node_ptr_->ref();
-                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+            return v;
+         }
 
-               return v;
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+         inline bool valid() const exprtk_override
+         {
+            return rbvec_node_ptr_ && binary_node<T>::valid();
          }
 
       private:
 
-         rebasevector_celem_node<T>* rbvec_node_ptr_;
+         rebasevector_celem_rtc_node<T>* rbvec_node_ptr_;
       };
 
       template <typename T, typename Operation>
-      class assignment_vec_op_node : public binary_node     <T>,
-                                     public vector_interface<T>
+      class assignment_vec_op_node exprtk_final
+                                   : public binary_node     <T>
+                                   , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*  expression_ptr;
+         typedef expression_node<T>* expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
-         typedef vec_data_store<T>             vds_t;
+         typedef vec_data_store<T>   vds_t;
+
+         using binary_node<T>::branch;
 
          assignment_vec_op_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec_node_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec_node_ptr_(0)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()         = vec_node_ptr_->vds();
             }
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (vec_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[1].first);
-
-               const T v = binary_node<T>::branch_[1].first->value();
+            const T v = branch(1)->value();
 
-               T* vec = vds().data();
+            T* vec = vds().data();
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec + lud.upper_bound;
-
-               while (vec < upper_bound)
-               {
-                  #define exprtk_loop(N)       \
-                  Operation::assign(vec[N],v); \
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec + lud.upper_bound;
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+            while (vec < upper_bound)
+            {
+               #define exprtk_loop(N)       \
+               Operation::assign(vec[N],v); \
 
-                  vec += lud.batch_size;
-               }
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N)                  \
-                  case N : Operation::assign(*vec++,v); \
+               vec += lud.batch_size;
+            }
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+            switch (lud.remainder)
+            {
+               #define case_stmt(N,fall_through)     \
+               case N : Operation::assign(*vec++,v); \
+               fall_through                          \
 
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
+               #endif
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            #undef exprtk_loop
+            #undef case_stmt
 
-               return vec_node_ptr_->value();
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return vec_node_ptr_->value();
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
             return vec_node_ptr_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
             return vec_node_ptr_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecopvalass;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return
+               vec_node_ptr_           &&
+               (size() <= base_size()) &&
+               binary_node<T>::valid() ;
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return vec_node_ptr_->vec_holder().size();
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds().size();
+            return vec_node_ptr_->vec_holder().base_size();
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
 
-         bool side_effect() const
+         bool side_effect() const exprtk_override
          {
             return true;
          }
@@ -10865,147 +13308,161 @@ namespace exprtk
       };
 
       template <typename T, typename Operation>
-      class assignment_vecvec_op_node : public binary_node     <T>,
-                                        public vector_interface<T>
+      class assignment_vecvec_op_node exprtk_final
+                                      : public binary_node     <T>
+                                      , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*  expression_ptr;
+         typedef expression_node<T>* expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
-         typedef vec_data_store<T>             vds_t;
+         typedef vec_data_store<T>   vds_t;
+
+         using binary_node<T>::branch;
 
          assignment_vecvec_op_node(const operator_type& opr,
                                    expression_ptr branch0,
                                    expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           initialised_(false)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec0_node_ptr_(0)
+         , vec1_node_ptr_(0)
+         , initialised_(false)
          {
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
                vds()          = vec0_node_ptr_->vds();
             }
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
                vec1_node_ptr_->vds() = vds();
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
-                  vec1_node_ptr_->vds() = vds();
+                  vec1_node_ptr_->vds() = vi->vds();
                }
                else
                   vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
             }
 
-            initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
+            initialised_ =
+               vec0_node_ptr_          &&
+               vec1_node_ptr_          &&
+               (size() <= base_size()) &&
+               binary_node<T>::valid();
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+            branch(0)->value();
+            branch(1)->value();
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+                  T* vec0 = vec0_node_ptr_->vds().data();
+            const T* vec1 = vec1_node_ptr_->vds().data();
 
-                     T* vec0 = vec0_node_ptr_->vds().data();
-               const T* vec1 = vec1_node_ptr_->vds().data();
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec0 + lud.upper_bound;
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec0 + lud.upper_bound;
-
-               while (vec0 < upper_bound)
-               {
-                  #define exprtk_loop(N)                          \
-                  vec0[N] = Operation::process(vec0[N], vec1[N]); \
+            while (vec0 < upper_bound)
+            {
+               #define exprtk_loop(N)                          \
+               vec0[N] = Operation::process(vec0[N], vec1[N]); \
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-                  vec0 += lud.batch_size;
-                  vec1 += lud.batch_size;
-               }
+               vec0 += lud.batch_size;
+               vec1 += lud.batch_size;
+            }
 
-               int i = 0;
+            int i = 0;
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N)                                              \
-                  case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
+            switch (lud.remainder)
+            {
+               #define case_stmt(N,fall_through)                                 \
+               case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
+               fall_through                                                      \
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
+               #endif
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            #undef exprtk_loop
+            #undef case_stmt
 
-               return vec0_node_ptr_->value();
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return vec0_node_ptr_->value();
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
             return vec0_node_ptr_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
             return vec0_node_ptr_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecopvecass;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return initialised_;
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return std::min(
+               vec0_node_ptr_->vec_holder().size(),
+               vec1_node_ptr_->vec_holder().size());
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds().size();
+            return std::min(
+               vec0_node_ptr_->vec_holder().base_size(),
+               vec1_node_ptr_->vec_holder().base_size());
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
 
-         bool side_effect() const
+         bool side_effect() const exprtk_override
          {
             return true;
          }
@@ -11018,54 +13475,115 @@ namespace exprtk
          vds_t           vds_;
       };
 
+      template <typename T>
+      struct memory_context_t
+      {
+         typedef vector_node<T>*  vector_node_ptr;
+         typedef vector_holder<T> vector_holder_t;
+         typedef vector_holder_t* vector_holder_ptr;
+
+         memory_context_t()
+         : temp_(0)
+         , temp_vec_node_(0)
+         {}
+
+         void clear()
+         {
+            delete temp_vec_node_;
+            delete temp_;
+         }
+
+         vector_holder_ptr temp_;
+         vector_node_ptr   temp_vec_node_;
+      };
+
+      template <typename T>
+      inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder,
+                                                     vec_data_store<T>& vds)
+      {
+         memory_context_t<T> result_ctxt;
+         result_ctxt.temp_  = (vec_holder.rebaseable()) ?
+                              new vector_holder<T>(vec_holder,vds) :
+                              new vector_holder<T>(vds) ;
+         result_ctxt.temp_vec_node_ = new vector_node  <T>(vds,result_ctxt.temp_);
+         return result_ctxt;
+      }
+
+      template <typename T>
+      inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0,
+                                                     vector_holder<T>& vec_holder1,
+                                                     vec_data_store<T>& vds)
+      {
+         memory_context_t<T> result_ctxt;
+
+         if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable())
+            result_ctxt.temp_ = new vector_holder<T>(vds);
+         else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable())
+            result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds);
+         else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable())
+            result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds);
+         else
+         {
+            result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ?
+                                new vector_holder<T>(vec_holder0, vds) :
+                                new vector_holder<T>(vec_holder1, vds) ;
+         }
+
+         result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_);
+         return result_ctxt;
+      }
+
       template <typename T, typename Operation>
-      class vec_binop_vecvec_node : public binary_node     <T>,
-                                    public vector_interface<T>
+      class vec_binop_vecvec_node exprtk_final
+                                  : public binary_node     <T>
+                                  , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-         typedef vec_data_store<T>               vds_t;
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_holder_t*    vector_holder_ptr;
+         typedef vec_data_store<T>   vds_t;
+         typedef memory_context_t<T> memory_context;
+
+         using binary_node<T>::branch;
 
          vec_binop_vecvec_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec0_node_ptr_(0),
-           vec1_node_ptr_(0),
-           temp_         (0),
-           temp_vec_node_(0),
-           initialised_(false)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec0_node_ptr_(0)
+         , vec1_node_ptr_(0)
+         , initialised_(false)
          {
             bool v0_is_ivec = false;
             bool v1_is_ivec = false;
 
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            else if (is_ivector_node(branch(0)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
                {
                   vec0_node_ptr_ = vi->vec();
                   v0_is_ivec     = true;
                }
             }
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
                   v1_is_ivec     = true;
@@ -11077,164 +13595,180 @@ namespace exprtk
                vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
                vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
 
-               if (v0_is_ivec && (vec0.size() <= vec1.size()))
+               if (v0_is_ivec && (vec0.base_size() <= vec1.base_size()))
+               {
                   vds_ = vds_t(vec0_node_ptr_->vds());
-               else if (v1_is_ivec && (vec1.size() <= vec0.size()))
+               }
+               else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size()))
+               {
                   vds_ = vds_t(vec1_node_ptr_->vds());
+               }
                else
-                  vds_ = vds_t(std::min(vec0.size(),vec1.size()));
+               {
+                  vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size()));
+               }
 
-               temp_          = new vector_holder<T>(vds().data(),vds().size());
-               temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+               memory_context_ = make_memory_context(vec0, vec1, vds());
 
-               initialised_ = true;
+               initialised_ =
+                  (size() <= base_size()) &&
+                  binary_node<T>::valid();
             }
+
+            assert(valid());
          }
 
         ~vec_binop_vecvec_node()
          {
-            delete temp_;
-            delete temp_vec_node_;
+            memory_context_.clear();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (initialised_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+            branch(0)->value();
+            branch(1)->value();
 
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+            const T* vec0 = vec0_node_ptr_->vds().data();
+            const T* vec1 = vec1_node_ptr_->vds().data();
+                  T* vec2 = vds().data();
 
-               const T* vec0 = vec0_node_ptr_->vds().data();
-               const T* vec1 = vec1_node_ptr_->vds().data();
-                     T* vec2 = vds().data();
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec2 + lud.upper_bound;
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec2 + lud.upper_bound;
-
-               while (vec2 < upper_bound)
-               {
-                  #define exprtk_loop(N)                          \
-                  vec2[N] = Operation::process(vec0[N], vec1[N]); \
+            while (vec2 < upper_bound)
+            {
+               #define exprtk_loop(N)                          \
+               vec2[N] = Operation::process(vec0[N], vec1[N]); \
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-                  vec0 += lud.batch_size;
-                  vec1 += lud.batch_size;
-                  vec2 += lud.batch_size;
-               }
+               vec0 += lud.batch_size;
+               vec1 += lud.batch_size;
+               vec2 += lud.batch_size;
+            }
 
-               int i = 0;
+            int i = 0;
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N)                                              \
-                  case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
+            switch (lud.remainder)
+            {
+               #define case_stmt(N)                                              \
+               case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
+               exprtk_fallthrough                                                \
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15) case_stmt(14)
+               case_stmt(13) case_stmt(12)
+               case_stmt(11) case_stmt(10)
+               case_stmt( 9) case_stmt( 8)
+               case_stmt( 7) case_stmt( 6)
+               case_stmt( 5) case_stmt( 4)
+               #endif
+               case_stmt( 3) case_stmt( 2)
+               case_stmt( 1)
+               default: break;
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            #undef exprtk_loop
+            #undef case_stmt
 
-               return (vds().data())[0];
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return (vds().data())[0];
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecvecarith;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return initialised_;
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return std::min(
+               vec0_node_ptr_->vec_holder().size(),
+               vec1_node_ptr_->vec_holder().size());
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds_.size();
+            return std::min(
+               vec0_node_ptr_->vec_holder().base_size(),
+               vec1_node_ptr_->vec_holder().base_size());
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
 
       private:
 
-         vector_node_ptr   vec0_node_ptr_;
-         vector_node_ptr   vec1_node_ptr_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
-         bool              initialised_;
-         vds_t             vds_;
+         vector_node_ptr vec0_node_ptr_;
+         vector_node_ptr vec1_node_ptr_;
+         bool            initialised_;
+         vds_t           vds_;
+         memory_context  memory_context_;
       };
 
       template <typename T, typename Operation>
-      class vec_binop_vecval_node : public binary_node     <T>,
-                                    public vector_interface<T>
+      class vec_binop_vecval_node exprtk_final
+                                  : public binary_node     <T>
+                                  , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-         typedef vec_data_store<T>               vds_t;
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_holder_t*    vector_holder_ptr;
+         typedef vec_data_store<T>   vds_t;
+         typedef memory_context_t<T> memory_context;
+
+         using binary_node<T>::branch;
 
          vec_binop_vecval_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec0_node_ptr_(0),
-           temp_         (0),
-           temp_vec_node_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec0_node_ptr_(0)
          {
             bool v0_is_ivec = false;
 
-            if (is_vector_node(binary_node<T>::branch_[0].first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            else if (is_ivector_node(branch(0)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
                {
                   vec0_node_ptr_ = vi->vec();
                   v0_is_ivec     = true;
@@ -11246,111 +13780,115 @@ namespace exprtk
                if (v0_is_ivec)
                   vds() = vec0_node_ptr_->vds();
                else
-                  vds() = vds_t(vec0_node_ptr_->size());
+                  vds() = vds_t(vec0_node_ptr_->base_size());
 
-               temp_          = new vector_holder<T>(vds());
-               temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+               memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
             }
+
+            assert(valid());
          }
 
         ~vec_binop_vecval_node()
          {
-            delete temp_;
-            delete temp_vec_node_;
+            memory_context_.clear();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (vec0_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
+                        branch(0)->value();
+            const T v = branch(1)->value();
 
-                           binary_node<T>::branch_[0].first->value();
-               const T v = binary_node<T>::branch_[1].first->value();
+            const T* vec0 = vec0_node_ptr_->vds().data();
+                  T* vec1 = vds().data();
 
-               const T* vec0 = vec0_node_ptr_->vds().data();
-                     T* vec1 = vds().data();
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec0 + lud.upper_bound;
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec0 + lud.upper_bound;
-
-               while (vec0 < upper_bound)
-               {
-                  #define exprtk_loop(N)                    \
-                  vec1[N] = Operation::process(vec0[N], v); \
+            while (vec0 < upper_bound)
+            {
+               #define exprtk_loop(N)                    \
+               vec1[N] = Operation::process(vec0[N], v); \
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-                  vec0 += lud.batch_size;
-                  vec1 += lud.batch_size;
-               }
+               vec0 += lud.batch_size;
+               vec1 += lud.batch_size;
+            }
 
-               int i = 0;
+            int i = 0;
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N)                                        \
-                  case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
+            switch (lud.remainder)
+            {
+               #define case_stmt(N,fall_through)                           \
+               case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
+               fall_through                                                \
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
+               #endif
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            #undef exprtk_loop
+            #undef case_stmt
 
-               return (vds().data())[0];
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return (vds().data())[0];
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecvalarith;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return
+               vec0_node_ptr_          &&
+               (size() <= base_size()) &&
+               binary_node<T>::valid();
+         }
+
+         std::size_t size() const exprtk_override
          {
-            return vds().size();
+            return vec0_node_ptr_->size();
          }
 
-         vds_t& vds()
+         std::size_t base_size() const exprtk_override
+         {
+            return vec0_node_ptr_->vec_holder().base_size();
+         }
+
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
@@ -11358,41 +13896,43 @@ namespace exprtk
       private:
 
          vector_node_ptr   vec0_node_ptr_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
          vds_t             vds_;
+         memory_context    memory_context_;
       };
 
       template <typename T, typename Operation>
-      class vec_binop_valvec_node : public binary_node     <T>,
-                                    public vector_interface<T>
+      class vec_binop_valvec_node exprtk_final
+                                  : public binary_node     <T>
+                                  , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-         typedef vec_data_store<T>               vds_t;
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_holder_t*    vector_holder_ptr;
+         typedef vec_data_store<T>   vds_t;
+         typedef memory_context_t<T> memory_context;
+
+         using binary_node<T>::branch;
 
          vec_binop_valvec_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           vec1_node_ptr_(0),
-           temp_         (0),
-           temp_vec_node_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , vec1_node_ptr_(0)
          {
             bool v1_is_ivec = false;
 
-            if (is_vector_node(binary_node<T>::branch_[1].first))
+            if (is_vector_node(branch(1)))
             {
-               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
             }
-            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            else if (is_ivector_node(branch(1)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
                {
                   vec1_node_ptr_ = vi->vec();
                   v1_is_ivec     = true;
@@ -11404,111 +13944,116 @@ namespace exprtk
                if (v1_is_ivec)
                   vds() = vec1_node_ptr_->vds();
                else
-                  vds() = vds_t(vec1_node_ptr_->size());
+                  vds() = vds_t(vec1_node_ptr_->base_size());
 
-               temp_          = new vector_holder<T>(vds());
-               temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+               memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds());
             }
+
+            assert(valid());
          }
 
         ~vec_binop_valvec_node()
          {
-            delete temp_;
-            delete temp_vec_node_;
+            memory_context_.clear();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (vec1_node_ptr_)
-            {
-               assert(binary_node<T>::branch_[0].first);
-               assert(binary_node<T>::branch_[1].first);
-
-               const T v = binary_node<T>::branch_[0].first->value();
-                           binary_node<T>::branch_[1].first->value();
+            const T v = branch(0)->value();
+                        branch(1)->value();
 
-                     T* vec0 = vds().data();
-               const T* vec1 = vec1_node_ptr_->vds().data();
+                  T* vec0 = vds().data();
+            const T* vec1 = vec1_node_ptr_->vds().data();
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec0 + lud.upper_bound;
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec0 + lud.upper_bound;
 
-               while (vec0 < upper_bound)
-               {
-                  #define exprtk_loop(N)                    \
-                  vec0[N] = Operation::process(v, vec1[N]); \
+            while (vec0 < upper_bound)
+            {
+               #define exprtk_loop(N)                    \
+               vec0[N] = Operation::process(v, vec1[N]); \
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-                  vec0 += lud.batch_size;
-                  vec1 += lud.batch_size;
-               }
+               vec0 += lud.batch_size;
+               vec1 += lud.batch_size;
+            }
 
-               int i = 0;
+            int i = 0;
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
-               {
-                  #define case_stmt(N)                                        \
-                  case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
+            switch (lud.remainder)
+            {
+               #define case_stmt(N,fall_through)                           \
+               case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
+               fall_through                                                \
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
-               }
-               exprtk_disable_fallthrough_end
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
+               #endif
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            #undef exprtk_loop
+            #undef case_stmt
 
-               return (vds().data())[0];
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return (vds().data())[0];
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vecvalarith;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return
+               vec1_node_ptr_               &&
+               (size() <= base_size())      &&
+               (vds_.size() <= base_size()) &&
+               binary_node<T>::valid();
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return vec1_node_ptr_->vec_holder().size();
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds().size();
+            return vec1_node_ptr_->vec_holder().base_size();
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
@@ -11516,39 +14061,41 @@ namespace exprtk
       private:
 
          vector_node_ptr   vec1_node_ptr_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
          vds_t             vds_;
+         memory_context    memory_context_;
       };
 
       template <typename T, typename Operation>
-      class unary_vector_node : public unary_node      <T>,
-                                public vector_interface<T>
+      class unary_vector_node exprtk_final
+                              : public unary_node      <T>
+                              , public vector_interface<T>
       {
       public:
 
-         typedef expression_node<T>*    expression_ptr;
-         typedef vector_node<T>*       vector_node_ptr;
-         typedef vector_holder<T>*   vector_holder_ptr;
-         typedef vec_data_store<T>               vds_t;
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_holder_t*    vector_holder_ptr;
+         typedef vec_data_store<T>   vds_t;
+         typedef memory_context_t<T> memory_context;
+
+         using expression_node<T>::branch;
 
          unary_vector_node(const operator_type& opr, expression_ptr branch0)
-         : unary_node<T>(opr, branch0),
-           vec0_node_ptr_(0),
-           temp_         (0),
-           temp_vec_node_(0)
+         : unary_node<T>(opr, branch0)
+         , vec0_node_ptr_(0)
          {
             bool vec0_is_ivec = false;
 
-            if (is_vector_node(unary_node<T>::branch_.first))
+            if (is_vector_node(branch(0)))
             {
-               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first);
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
             }
-            else if (is_ivector_node(unary_node<T>::branch_.first))
+            else if (is_ivector_node(branch(0)))
             {
                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
 
-               if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first)))
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
                {
                   vec0_node_ptr_ = vi->vec();
                   vec0_is_ivec   = true;
@@ -11560,188 +14107,366 @@ namespace exprtk
                if (vec0_is_ivec)
                   vds_ = vec0_node_ptr_->vds();
                else
-                  vds_ = vds_t(vec0_node_ptr_->size());
+                  vds_ = vds_t(vec0_node_ptr_->base_size());
 
-               temp_          = new vector_holder<T>(vds());
-               temp_vec_node_ = new vector_node<T>  (vds(),temp_);
+               memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
             }
+
+            assert(valid());
          }
 
         ~unary_vector_node()
          {
-            delete temp_;
-            delete temp_vec_node_;
+            memory_context_.clear();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(unary_node<T>::branch_.first);
+            branch()->value();
 
-            unary_node<T>::branch_.first->value();
+            const T* vec0 = vec0_node_ptr_->vds().data();
+                  T* vec1 = vds().data();
 
-            if (vec0_node_ptr_)
+            loop_unroll::details lud(size());
+            const T* upper_bound = vec0 + lud.upper_bound;
+
+            while (vec0 < upper_bound)
             {
-               const T* vec0 = vec0_node_ptr_->vds().data();
-                     T* vec1 = vds().data();
+               #define exprtk_loop(N)                 \
+               vec1[N] = Operation::process(vec0[N]); \
 
-               loop_unroll::details lud(size());
-               const T* upper_bound = vec0 + lud.upper_bound;
+               exprtk_loop( 0) exprtk_loop( 1)
+               exprtk_loop( 2) exprtk_loop( 3)
+               #ifndef exprtk_disable_superscalar_unroll
+               exprtk_loop( 4) exprtk_loop( 5)
+               exprtk_loop( 6) exprtk_loop( 7)
+               exprtk_loop( 8) exprtk_loop( 9)
+               exprtk_loop(10) exprtk_loop(11)
+               exprtk_loop(12) exprtk_loop(13)
+               exprtk_loop(14) exprtk_loop(15)
+               #endif
 
-               while (vec0 < upper_bound)
-               {
-                  #define exprtk_loop(N)                 \
-                  vec1[N] = Operation::process(vec0[N]); \
+               vec0 += lud.batch_size;
+               vec1 += lud.batch_size;
+            }
 
-                  exprtk_loop( 0) exprtk_loop( 1)
-                  exprtk_loop( 2) exprtk_loop( 3)
-                  #ifndef exprtk_disable_superscalar_unroll
-                  exprtk_loop( 4) exprtk_loop( 5)
-                  exprtk_loop( 6) exprtk_loop( 7)
-                  exprtk_loop( 8) exprtk_loop( 9)
-                  exprtk_loop(10) exprtk_loop(11)
-                  exprtk_loop(12) exprtk_loop(13)
-                  exprtk_loop(14) exprtk_loop(15)
-                  #endif
+            int i = 0;
 
-                  vec0 += lud.batch_size;
-                  vec1 += lud.batch_size;
-               }
+            switch (lud.remainder)
+            {
+               #define case_stmt(N)                                     \
+               case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
+               exprtk_fallthrough                                       \
 
-               int i = 0;
+               #ifndef exprtk_disable_superscalar_unroll
+               case_stmt(15) case_stmt(14)
+               case_stmt(13) case_stmt(12)
+               case_stmt(11) case_stmt(10)
+               case_stmt( 9) case_stmt( 8)
+               case_stmt( 7) case_stmt( 6)
+               case_stmt( 5) case_stmt( 4)
+               #endif
+               case_stmt( 3) case_stmt( 2)
+               case_stmt( 1)
+               default: break;
+            }
 
-               exprtk_disable_fallthrough_begin
-               switch (lud.remainder)
+            #undef exprtk_loop
+            #undef case_stmt
+
+            return (vds().data())[0];
+         }
+
+         vector_node_ptr vec() const exprtk_override
+         {
+            return memory_context_.temp_vec_node_;
+         }
+
+         vector_node_ptr vec() exprtk_override
+         {
+            return memory_context_.temp_vec_node_;
+         }
+
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_vecunaryop;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return vec0_node_ptr_ && unary_node<T>::valid();
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return vec0_node_ptr_->vec_holder().size();
+         }
+
+         std::size_t base_size() const exprtk_override
+         {
+            return vec0_node_ptr_->vec_holder().base_size();
+         }
+
+         vds_t& vds() exprtk_override
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const exprtk_override
+         {
+            return vds_;
+         }
+
+      private:
+
+         vector_node_ptr vec0_node_ptr_;
+         vds_t           vds_;
+         memory_context  memory_context_;
+      };
+
+      template <typename T>
+      class conditional_vector_node exprtk_final
+                                    : public expression_node <T>
+                                    , public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node <T>* expression_ptr;
+         typedef vector_interface<T>* vec_interface_ptr;
+         typedef vector_node     <T>* vector_node_ptr;
+         typedef vector_holder   <T>  vector_holder_t;
+         typedef vector_holder_t*     vector_holder_ptr;
+         typedef vec_data_store  <T>  vds_t;
+         typedef memory_context_t<T> memory_context;
+         typedef std::pair<expression_ptr,bool> branch_t;
+
+         conditional_vector_node(expression_ptr condition,
+                                 expression_ptr consequent,
+                                 expression_ptr alternative)
+         : consequent_node_ptr_ (0)
+         , alternative_node_ptr_(0)
+         , temp_vec_node_       (0)
+         , temp_                (0)
+         , result_vec_size_     (0)
+         , initialised_         (false)
+         {
+            construct_branch_pair(condition_  , condition  );
+            construct_branch_pair(consequent_ , consequent );
+            construct_branch_pair(alternative_, alternative);
+
+            if (details::is_ivector_node(consequent_.first))
+            {
+               vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first);
+
+               if (0 != ivec_ptr)
                {
-                  #define case_stmt(N)                                     \
-                  case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
+                  consequent_node_ptr_ = ivec_ptr->vec();
+               }
+            }
 
-                  #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(15) case_stmt(14)
-                  case_stmt(13) case_stmt(12)
-                  case_stmt(11) case_stmt(10)
-                  case_stmt( 9) case_stmt( 8)
-                  case_stmt( 7) case_stmt( 6)
-                  case_stmt( 5) case_stmt( 4)
-                  #endif
-                  case_stmt( 3) case_stmt( 2)
-                  case_stmt( 1)
+            if (details::is_ivector_node(alternative_.first))
+            {
+               vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first);
+
+               if (0 != ivec_ptr)
+               {
+                  alternative_node_ptr_ = ivec_ptr->vec();
                }
-               exprtk_disable_fallthrough_end
+            }
 
-               #undef exprtk_loop
-               #undef case_stmt
+            if (consequent_node_ptr_ && alternative_node_ptr_)
+            {
+               const std::size_t vec_size =
+                  std::max(consequent_node_ptr_ ->vec_holder().base_size(),
+                           alternative_node_ptr_->vec_holder().base_size());
+
+               vds_            = vds_t(vec_size);
+               memory_context_ = make_memory_context(
+                  consequent_node_ptr_ ->vec_holder(),
+                  alternative_node_ptr_->vec_holder(),
+                  vds());
+
+               initialised_ = (vec_size > 0);
+            }
+
+            assert(initialised_);
+         }
+
+        ~conditional_vector_node()
+         {
+            memory_context_.clear();
+         }
 
-               return (vds().data())[0];
+         inline T value() const exprtk_override
+         {
+            T result = T(0);
+            T* source_vector = 0;
+            T* result_vector = vds().data();
+
+            if (is_true(condition_))
+            {
+               result           = consequent_.first->value();
+               source_vector    = consequent_node_ptr_->vds().data();
+               result_vec_size_ = consequent_node_ptr_->size();
             }
             else
-               return std::numeric_limits<T>::quiet_NaN();
+            {
+               result           = alternative_.first->value();
+               source_vector    = alternative_node_ptr_->vds().data();
+               result_vec_size_ = alternative_node_ptr_->size();
+            }
+
+            for (std::size_t i = 0; i < result_vec_size_; ++i)
+            {
+               result_vector[i] = source_vector[i];
+            }
+
+            return result;
          }
 
-         vector_node_ptr vec() const
+         vector_node_ptr vec() const exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         vector_node_ptr vec()
+         vector_node_ptr vec() exprtk_override
          {
-            return temp_vec_node_;
+            return memory_context_.temp_vec_node_;
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
-            return expression_node<T>::e_vecunaryop;
+            return expression_node<T>::e_vecondition;
          }
 
-         std::size_t size() const
+         inline bool valid() const exprtk_override
+         {
+            return
+               initialised_                                      &&
+               condition_  .first && condition_  .first->valid() &&
+               consequent_ .first && consequent_ .first->valid() &&
+               alternative_.first && alternative_.first->valid() &&
+               size() <= base_size();
+         }
+
+         std::size_t size() const exprtk_override
+         {
+            return result_vec_size_;
+         }
+
+         std::size_t base_size() const exprtk_override
          {
-            return vds().size();
+            return std::min(
+               consequent_node_ptr_ ->vec_holder().base_size(),
+               alternative_node_ptr_->vec_holder().base_size());
          }
 
-         vds_t& vds()
+         vds_t& vds() exprtk_override
          {
             return vds_;
          }
 
-         const vds_t& vds() const
+         const vds_t& vds() const exprtk_override
          {
             return vds_;
          }
 
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(condition_   , node_delete_list);
+            expression_node<T>::ndb_t::collect(consequent_  , node_delete_list);
+            expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::compute_node_depth
+               (condition_, consequent_, alternative_);
+         }
+
       private:
 
-         vector_node_ptr   vec0_node_ptr_;
-         vector_holder_ptr temp_;
-         vector_node_ptr   temp_vec_node_;
-         vds_t             vds_;
+         branch_t            condition_;
+         branch_t            consequent_;
+         branch_t            alternative_;
+         vector_node_ptr     consequent_node_ptr_;
+         vector_node_ptr     alternative_node_ptr_;
+         vector_node_ptr     temp_vec_node_;
+         vector_holder_ptr   temp_;
+         vds_t               vds_;
+         mutable std::size_t result_vec_size_;
+         bool                initialised_;
+         memory_context      memory_context_;
       };
 
       template <typename T>
-      class scand_node : public binary_node<T>
+      class scand_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          scand_node(const operator_type& opr,
                     expression_ptr branch0,
                     expression_ptr branch1)
          : binary_node<T>(opr, branch0, branch1)
-         {}
-
-         inline T value() const
          {
-            assert(binary_node<T>::branch_[0].first);
-            assert(binary_node<T>::branch_[1].first);
+            assert(binary_node<T>::valid());
+         }
 
+         inline T value() const exprtk_override
+         {
             return (
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[0].first->value()) &&
+                        (T(0),branch(0)->value()) &&
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[1].first->value())
+                        (T(0),branch(1)->value())
                    ) ? T(1) : T(0);
          }
       };
 
       template <typename T>
-      class scor_node : public binary_node<T>
+      class scor_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
+         using binary_node<T>::branch;
 
          scor_node(const operator_type& opr,
                    expression_ptr branch0,
                    expression_ptr branch1)
          : binary_node<T>(opr, branch0, branch1)
-         {}
-
-         inline T value() const
          {
-            assert(binary_node<T>::branch_[0].first);
-            assert(binary_node<T>::branch_[1].first);
+            assert(binary_node<T>::valid());
+         }
 
+         inline T value() const exprtk_override
+         {
             return (
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[0].first->value()) ||
+                        (T(0),branch(0)->value()) ||
                      std::not_equal_to<T>()
-                        (T(0),binary_node<T>::branch_[1].first->value())
+                        (T(0),branch(1)->value())
                    ) ? T(1) : T(0);
          }
       };
 
       template <typename T, typename IFunction, std::size_t N>
-      class function_N_node : public expression_node<T>
+      class function_N_node exprtk_final : public expression_node<T>
       {
       public:
 
-         // Function of N paramters.
+         // Function of N parameters.
          typedef expression_node<T>* expression_ptr;
          typedef std::pair<expression_ptr,bool> branch_t;
          typedef IFunction ifunction;
 
          explicit function_N_node(ifunction* func)
-         : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
-           parameter_count_(func->param_count)
+         : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
+         , parameter_count_(func->param_count)
+         , initialised_(false)
          {}
 
          template <std::size_t NumBranches>
@@ -11752,19 +14477,24 @@ namespace exprtk
              #pragma warning(push)
              #pragma warning(disable: 4127)
             #endif
+
             if (N != NumBranches)
+            {
                return false;
-            else
+            }
+
+            for (std::size_t i = 0; i < NumBranches; ++i)
             {
-               for (std::size_t i = 0; i < NumBranches; ++i)
-               {
-                  if (b[i])
-                     branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
-                  else
-                     return false;
-               }
-               return true;
+               if (b[i] && b[i]->valid())
+                  branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
+               else
+                  return false;
             }
+
+            initialised_ = function_;
+            assert(valid());
+            return initialised_;
+
             #ifdef _MSC_VER
              #pragma warning(pop)
             #endif
@@ -11775,26 +14505,43 @@ namespace exprtk
             return this < (&fn);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             // Needed for incompetent and broken msvc compiler versions
             #ifdef _MSC_VER
              #pragma warning(push)
              #pragma warning(disable: 4127)
             #endif
-            if ((0 == function_) || (0 == N))
-               return std::numeric_limits<T>::quiet_NaN();
-            else
-            {
-               T v[N];
-               evaluate_branches<T,N>::execute(v,branch_);
-               return invoke<T,N>::execute(*function_,v);
-            }
+
+            T v[N];
+            evaluate_branches<T,N>::execute(v,branch_);
+            return invoke<T,N>::execute(*function_,v);
+
             #ifdef _MSC_VER
              #pragma warning(pop)
             #endif
          }
 
+         inline typename expression_node<T>::node_type type() const exprtk_override
+         {
+            return expression_node<T>::e_function;
+         }
+
+         inline bool valid() const exprtk_override
+         {
+            return initialised_;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
+         {
+            return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
+         }
+
          template <typename T_, std::size_t BranchCount>
          struct evaluate_branches
          {
@@ -11807,6 +14554,20 @@ namespace exprtk
             }
          };
 
+         template <typename T_>
+         struct evaluate_branches <T_,6>
+         {
+            static inline void execute(T_ (&v)[6], const branch_t (&b)[6])
+            {
+               v[0] = b[0].first->value();
+               v[1] = b[1].first->value();
+               v[2] = b[2].first->value();
+               v[3] = b[3].first->value();
+               v[4] = b[4].first->value();
+               v[5] = b[5].first->value();
+            }
+         };
+
          template <typename T_>
          struct evaluate_branches <T_,5>
          {
@@ -11883,119 +14644,119 @@ namespace exprtk
          struct invoke<T_,18>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[18])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,17>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[17])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,16>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[16])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,15>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[15])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,14>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[14])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,13>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[13])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,12>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[12])
-            { 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]); }
+            { 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]); }
          };
 
          template <typename T_>
          struct invoke<T_,11>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[11])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
+            { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); }
          };
 
          template <typename T_>
          struct invoke<T_,10>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[10])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
+            { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); }
          };
 
          template <typename T_>
          struct invoke<T_,9>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[9])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
+            { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); }
          };
 
          template <typename T_>
          struct invoke<T_,8>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[8])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
+            { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); }
          };
 
          template <typename T_>
          struct invoke<T_,7>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[7])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
+            { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); }
          };
 
          template <typename T_>
          struct invoke<T_,6>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[6])
-            { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
+            { return f(v[0], v[1], v[2], v[3], v[4], v[5]); }
          };
 
          template <typename T_>
          struct invoke<T_,5>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[5])
-            { return f(v[0],v[1],v[2],v[3],v[4]); }
+            { return f(v[0], v[1], v[2], v[3], v[4]); }
          };
 
          template <typename T_>
          struct invoke<T_,4>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[4])
-            { return f(v[0],v[1],v[2],v[3]); }
+            { return f(v[0], v[1], v[2], v[3]); }
          };
 
          template <typename T_>
          struct invoke<T_,3>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[3])
-            { return f(v[0],v[1],v[2]); }
+            { return f(v[0], v[1], v[2]); }
          };
 
          template <typename T_>
          struct invoke<T_,2>
          {
             static inline T_ execute(ifunction& f, T_ (&v)[2])
-            { return f(v[0],v[1]); }
+            { return f(v[0], v[1]); }
          };
 
          template <typename T_>
@@ -12005,30 +14766,16 @@ namespace exprtk
             { return f(v[0]); }
          };
 
-         inline typename expression_node<T>::node_type type() const
-         {
-            return expression_node<T>::e_function;
-         }
-
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
-         {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
-         }
-
-         std::size_t node_depth() const
-         {
-            return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
-         }
-
       private:
 
          ifunction*  function_;
          std::size_t parameter_count_;
          branch_t    branch_[N];
+         bool        initialised_;
       };
 
       template <typename T, typename IFunction>
-      class function_N_node<T,IFunction,0> : public expression_node<T>
+      class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T>
       {
       public:
 
@@ -12037,33 +14784,37 @@ namespace exprtk
 
          explicit function_N_node(ifunction* func)
          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
-         {}
+         {
+            assert(valid());
+         }
 
          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
          {
             return this < (&fn);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (function_)
-               return (*function_)();
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            return (*function_)();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_function;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return function_;
+         }
+
       private:
 
          ifunction* function_;
       };
 
       template <typename T, typename VarArgFunction>
-      class vararg_function_node : public expression_node<T>
+      class vararg_function_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -12071,10 +14822,11 @@ namespace exprtk
 
          vararg_function_node(VarArgFunction*  func,
                               const std::vector<expression_ptr>& arg_list)
-         : function_(func),
-           arg_list_(arg_list)
+         : function_(func)
+         , arg_list_(arg_list)
          {
             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
+            assert(valid());
          }
 
          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
@@ -12082,23 +14834,23 @@ namespace exprtk
             return this < (&fn);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (function_)
-            {
-               populate_value_list();
-               return (*function_)(value_list_);
-            }
-            else
-               return std::numeric_limits<T>::quiet_NaN();
+            populate_value_list();
+            return (*function_)(value_list_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_vafunction;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return function_;
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             for (std::size_t i = 0; i < arg_list_.size(); ++i)
             {
@@ -12109,7 +14861,7 @@ namespace exprtk
             }
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
          }
@@ -12134,46 +14886,60 @@ namespace exprtk
       {
       public:
 
-         typedef type_store<T>                         type_store_t;
-         typedef expression_node<T>*                 expression_ptr;
-         typedef variable_node<T>                   variable_node_t;
-         typedef vector_node<T>                       vector_node_t;
-         typedef variable_node_t*               variable_node_ptr_t;
-         typedef vector_node_t*                   vector_node_ptr_t;
-         typedef range_interface<T>               range_interface_t;
-         typedef range_data_type<T>               range_data_type_t;
-         typedef range_pack<T>                              range_t;
-         typedef std::pair<expression_ptr,bool>            branch_t;
-         typedef std::pair<void*,std::size_t>                void_t;
-         typedef std::vector<T>                            tmp_vs_t;
-         typedef std::vector<type_store_t>         typestore_list_t;
-         typedef std::vector<range_data_type_t>        range_list_t;
+         typedef type_store<T>       type_store_t;
+         typedef expression_node<T>* expression_ptr;
+         typedef variable_node<T>    variable_node_t;
+         typedef vector_node<T>      vector_node_t;
+         typedef variable_node_t*    variable_node_ptr_t;
+         typedef vector_node_t*      vector_node_ptr_t;
+         typedef range_interface<T>  range_interface_t;
+         typedef range_data_type<T>  range_data_type_t;
+         typedef typename range_interface<T>::range_t range_t;
+
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef vector_holder<T>* vh_t;
+         typedef vector_view<T>*   vecview_t;
+
+         typedef std::vector<T>                 tmp_vs_t;
+         typedef std::vector<type_store_t>      typestore_list_t;
+         typedef std::vector<range_data_type_t> range_list_t;
 
          explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
                                         GenericFunction* func = reinterpret_cast<GenericFunction*>(0))
-         : function_(func),
-           arg_list_(arg_list)
+         : function_(func)
+         , arg_list_(arg_list)
          {}
 
          virtual ~generic_function_node()
-         {}
+         {
+            for (std::size_t i = 0; i < vv_list_.size(); ++i)
+            {
+               vecview_t& vv = vv_list_[i];
+               if (vv && typestore_list_[i].vec_data)
+               {
+                  vv->remove_ref(&typestore_list_[i].vec_data);
+                  typestore_list_[i].vec_data = 0;
+               }
+            }
+         }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override exprtk_final
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
          virtual bool init_branches()
          {
-            expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );
-            typestore_list_    .resize(arg_list_.size(),type_store_t()     );
-            range_list_        .resize(arg_list_.size(),range_data_type_t());
-            branch_            .resize(arg_list_.size(),branch_t(reinterpret_cast<expression_ptr>(0),false));
+            expr_as_vec1_store_.resize(arg_list_.size(), T(0)               );
+            typestore_list_    .resize(arg_list_.size(), type_store_t()     );
+            range_list_        .resize(arg_list_.size(), range_data_type_t());
+            branch_            .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false));
+            vv_list_           .resize(arg_list_.size(), vecview_t(0));
 
             for (std::size_t i = 0; i < arg_list_.size(); ++i)
             {
@@ -12191,7 +14957,15 @@ namespace exprtk
                   ts.size = vi->size();
                   ts.data = vi->vds().data();
                   ts.type = type_store_t::e_vector;
-                  vi->vec()->vec_holder().set_ref(&ts.vec_data);
+
+                  if (
+                       vi->vec()->vec_holder().rebaseable() &&
+                       vi->vec()->vec_holder().rebaseable_instance()
+                     )
+                  {
+                     vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance();
+                     vv_list_[i]->set_ref(&ts.vec_data);
+                  }
                }
                #ifndef exprtk_disable_string_capabilities
                else if (is_generally_string_node(arg_list_[i]))
@@ -12227,7 +15001,10 @@ namespace exprtk
                      range_list_[i].range = reinterpret_cast<range_t*>(0);
                   }
                   else
+                  {
                      range_list_[i].range = &(ri->range_ref());
+                     range_param_list_.push_back(i);
+                  }
                }
                #endif
                else if (is_variable_node(arg_list_[i]))
@@ -12259,26 +15036,28 @@ namespace exprtk
             return this < (&fn);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (function_)
+            if (populate_value_list())
             {
-               if (populate_value_list())
-               {
-                  typedef typename GenericFunction::parameter_list_t parameter_list_t;
+               typedef typename GenericFunction::parameter_list_t parameter_list_t;
 
-                  return (*function_)(parameter_list_t(typestore_list_));
-               }
+               return (*function_)(parameter_list_t(typestore_list_));
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_genfunction;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return function_;
+         }
+
       protected:
 
          inline virtual bool populate_value_list() const
@@ -12288,30 +15067,40 @@ namespace exprtk
                expr_as_vec1_store_[i] = branch_[i].first->value();
             }
 
-            for (std::size_t i = 0; i < branch_.size(); ++i)
+            if (!range_param_list_.empty())
             {
-               range_data_type_t& rdt = range_list_[i];
+               assert(range_param_list_.size() <= branch_.size());
 
-               if (rdt.range)
+               for (std::size_t i = 0; i < range_param_list_.size(); ++i)
                {
+                  const std::size_t  index = range_param_list_[i];
+                  range_data_type_t& rdt   = range_list_[index];
+
                   const range_t& rp = (*rdt.range);
                   std::size_t r0    = 0;
                   std::size_t r1    = 0;
 
-                  if (rp(r0, r1, rdt.size))
-                  {
-                     type_store_t& ts = typestore_list_[i];
+                  const std::size_t data_size =
+                  #ifndef exprtk_disable_string_capabilities
+                     rdt.str_node ? rdt.str_node->size() : rdt.size;
+                  #else
+                     rdt.size;
+                  #endif
 
-                     ts.size = rp.cache_size();
-                     #ifndef exprtk_disable_string_capabilities
-                     if (ts.type == type_store_t::e_string)
-                        ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
-                     else
-                     #endif
-                        ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
+                  if (!rp(r0, r1, data_size))
+                  {
+                     return false;
                   }
+
+                  type_store_t& ts = typestore_list_[index];
+
+                  ts.size = rp.cache_size();
+                  #ifndef exprtk_disable_string_capabilities
+                  if (ts.type == type_store_t::e_string)
+                     ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
                   else
-                     return false;
+                  #endif
+                     ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
                }
             }
 
@@ -12324,21 +15113,23 @@ namespace exprtk
       private:
 
          std::vector<expression_ptr> arg_list_;
-         std::vector<branch_t>         branch_;
-         mutable tmp_vs_t  expr_as_vec1_store_;
-         mutable range_list_t      range_list_;
+         std::vector<branch_t>       branch_;
+         std::vector<vecview_t>      vv_list_;
+         mutable tmp_vs_t            expr_as_vec1_store_;
+         mutable range_list_t        range_list_;
+         std::vector<std::size_t>    range_param_list_;
       };
 
       #ifndef exprtk_disable_string_capabilities
       template <typename T, typename StringFunction>
-      class string_function_node : public generic_function_node<T,StringFunction>,
-                                   public string_base_node<T>,
-                                   public range_interface <T>
+      class string_function_node : public generic_function_node<T,StringFunction>
+                                 , public string_base_node<T>
+                                 , public range_interface <T>
       {
       public:
 
          typedef generic_function_node<T,StringFunction> gen_function_t;
-         typedef range_pack<T> range_t;
+         typedef typename range_interface<T>::range_t range_t;
 
          string_function_node(StringFunction* func,
                               const std::vector<typename gen_function_t::expression_ptr>& arg_list)
@@ -12348,6 +15139,7 @@ namespace exprtk
             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
             range_.cache.first  = range_.n0_c.second;
             range_.cache.second = range_.n1_c.second;
+            assert(valid());
          }
 
          inline bool operator <(const string_function_node<T,StringFunction>& fn) const
@@ -12355,56 +15147,59 @@ namespace exprtk
             return this < (&fn);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (gen_function_t::function_)
+            if (gen_function_t::populate_value_list())
             {
-               if (gen_function_t::populate_value_list())
-               {
-                  typedef typename StringFunction::parameter_list_t parameter_list_t;
+               typedef typename StringFunction::parameter_list_t parameter_list_t;
 
-                  const T result = (*gen_function_t::function_)
-                                      (
-                                        ret_string_,
-                                        parameter_list_t(gen_function_t::typestore_list_)
-                                      );
+               const T result =
+                  (*gen_function_t::function_)
+                  (
+                     ret_string_,
+                     parameter_list_t(gen_function_t::typestore_list_)
+                  );
 
-                  range_.n1_c.second  = ret_string_.size() - 1;
-                  range_.cache.second = range_.n1_c.second;
+               range_.n1_c.second  = ret_string_.size();
+               range_.cache.second = range_.n1_c.second;
 
-                  return result;
-               }
+               return result;
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strfunction;
          }
 
-         std::string str() const
+         inline bool valid() const exprtk_override
+         {
+            return gen_function_t::function_;
+         }
+
+         std::string str() const exprtk_override
          {
             return ret_string_;
          }
 
-         char_cptr base() const
+         char_cptr base() const exprtk_override
          {
            return &ret_string_[0];
          }
 
-         std::size_t size() const
+         std::size_t size() const exprtk_override
          {
             return ret_string_.size();
          }
 
-         range_t& range_ref()
+         range_t& range_ref() exprtk_override
          {
             return range_;
          }
 
-         const range_t& range_ref() const
+         const range_t& range_ref() const exprtk_override
          {
             return range_;
          }
@@ -12422,35 +15217,35 @@ namespace exprtk
       public:
 
          typedef generic_function_node<T,GenericFunction> gen_function_t;
-         typedef range_pack<T> range_t;
+         typedef typename gen_function_t::range_t         range_t;
 
          multimode_genfunction_node(GenericFunction* func,
                                     const std::size_t& param_seq_index,
                                     const std::vector<typename gen_function_t::expression_ptr>& arg_list)
-         : gen_function_t(arg_list,func),
-           param_seq_index_(param_seq_index)
+         : gen_function_t(arg_list,func)
+         , param_seq_index_(param_seq_index)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (gen_function_t::function_)
+            assert(gen_function_t::valid());
+
+            if (gen_function_t::populate_value_list())
             {
-               if (gen_function_t::populate_value_list())
-               {
-                  typedef typename GenericFunction::parameter_list_t parameter_list_t;
+               typedef typename GenericFunction::parameter_list_t parameter_list_t;
 
-                  return (*gen_function_t::function_)
-                            (
-                              param_seq_index_,
-                              parameter_list_t(gen_function_t::typestore_list_)
-                            );
-               }
+               return
+                  (*gen_function_t::function_)
+                  (
+                     param_seq_index_,
+                     parameter_list_t(gen_function_t::typestore_list_)
+                  );
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
          {
             return expression_node<T>::e_genfunction;
          }
@@ -12462,46 +15257,44 @@ namespace exprtk
 
       #ifndef exprtk_disable_string_capabilities
       template <typename T, typename StringFunction>
-      class multimode_strfunction_node : public string_function_node<T,StringFunction>
+      class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction>
       {
       public:
 
          typedef string_function_node<T,StringFunction> str_function_t;
-         typedef range_pack<T> range_t;
+         typedef typename str_function_t::range_t range_t;
 
          multimode_strfunction_node(StringFunction* func,
                                     const std::size_t& param_seq_index,
                                     const std::vector<typename str_function_t::expression_ptr>& arg_list)
-         : str_function_t(func,arg_list),
-           param_seq_index_(param_seq_index)
+         : str_function_t(func,arg_list)
+         , param_seq_index_(param_seq_index)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (str_function_t::function_)
+            if (str_function_t::populate_value_list())
             {
-               if (str_function_t::populate_value_list())
-               {
-                  typedef typename StringFunction::parameter_list_t parameter_list_t;
+               typedef typename StringFunction::parameter_list_t parameter_list_t;
 
-                  const T result = (*str_function_t::function_)
-                                      (
-                                        param_seq_index_,
-                                        str_function_t::ret_string_,
-                                        parameter_list_t(str_function_t::typestore_list_)
-                                      );
+               const T result =
+                  (*str_function_t::function_)
+                  (
+                     param_seq_index_,
+                     str_function_t::ret_string_,
+                     parameter_list_t(str_function_t::typestore_list_)
+                  );
 
-                  str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size() - 1;
-                  str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
+               str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size();
+               str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
 
-                  return result;
-               }
+               return result;
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_strfunction;
          }
@@ -12512,8 +15305,7 @@ namespace exprtk
       };
       #endif
 
-      class return_exception
-      {};
+      class return_exception {};
 
       template <typename T>
       class null_igenfunc
@@ -12534,27 +15326,26 @@ namespace exprtk
 
       #ifndef exprtk_disable_return_statement
       template <typename T>
-      class return_node : public generic_function_node<T,null_igenfunc<T> >
+      class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> >
       {
       public:
 
-         typedef null_igenfunc<T> igeneric_function_t;
+         typedef results_context<T>   results_context_t;
+         typedef null_igenfunc<T>     igeneric_function_t;
          typedef igeneric_function_t* igeneric_function_ptr;
          typedef generic_function_node<T,igeneric_function_t> gen_function_t;
-         typedef results_context<T> results_context_t;
 
          return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
                      results_context_t& rc)
-         : gen_function_t  (arg_list),
-           results_context_(&rc)
-         {}
+         : gen_function_t  (arg_list)
+         , results_context_(&rc)
+         {
+            assert(valid());
+         }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (
-                 (0 != results_context_) &&
-                 gen_function_t::populate_value_list()
-               )
+            if (gen_function_t::populate_value_list())
             {
                typedef typename type_store<T>::parameter_list parameter_list_t;
 
@@ -12567,18 +15358,23 @@ namespace exprtk
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_return;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return results_context_;
+         }
+
       private:
 
          results_context_t* results_context_;
       };
 
       template <typename T>
-      class return_envelope_node : public expression_node<T>
+      class return_envelope_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -12587,16 +15383,15 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
 
          return_envelope_node(expression_ptr body, results_context_t& rc)
-         : results_context_(&rc  ),
-           return_invoked_ (false)
+         : results_context_(&rc  )
+         , return_invoked_ (false)
          {
             construct_branch_pair(body_, body);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(body_.first);
-
             try
             {
                return_invoked_ = false;
@@ -12607,26 +15402,32 @@ namespace exprtk
             catch(const return_exception&)
             {
                return_invoked_ = true;
+
                return std::numeric_limits<T>::quiet_NaN();
             }
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_retenv;
          }
 
+         inline bool valid() const exprtk_override
+         {
+            return results_context_ && body_.first;
+         }
+
          inline bool* retinvk_ptr()
          {
             return &return_invoked_;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(body_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(body_);
          }
@@ -12709,11 +15510,11 @@ namespace exprtk
       {
          typedef typename details::functor_t<T>::Type    Type;
          typedef typename details::functor_t<T>::RefType RefType;
-         typedef typename details::functor_t<T>          functor_t;
-         typedef typename functor_t::qfunc_t  quaternary_functor_t;
-         typedef typename functor_t::tfunc_t     trinary_functor_t;
-         typedef typename functor_t::bfunc_t      binary_functor_t;
-         typedef typename functor_t::ufunc_t       unary_functor_t;
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::qfunc_t    quaternary_functor_t;
+         typedef typename functor_t::tfunc_t    trinary_functor_t;
+         typedef typename functor_t::bfunc_t    binary_functor_t;
+         typedef typename functor_t::ufunc_t    unary_functor_t;
       };
 
       template <typename T>
@@ -13000,7 +15801,7 @@ namespace exprtk
       }
 
       template <typename T>
-      struct vararg_add_op : public opr_base<T>
+      struct vararg_add_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13023,7 +15824,7 @@ namespace exprtk
 
                             for (std::size_t i = 0; i < arg_list.size(); ++i)
                             {
-                              result += value(arg_list[i]);
+                               result += value(arg_list[i]);
                             }
 
                             return result;
@@ -13067,7 +15868,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_mul_op : public opr_base<T>
+      struct vararg_mul_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13134,7 +15935,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_avg_op : public opr_base<T>
+      struct vararg_avg_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13151,7 +15952,7 @@ namespace exprtk
                case 3  : return process_3(arg_list);
                case 4  : return process_4(arg_list);
                case 5  : return process_5(arg_list);
-               default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
+               default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size());
             }
          }
 
@@ -13190,7 +15991,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_min_op : public opr_base<T>
+      struct vararg_min_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13261,7 +16062,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_max_op : public opr_base<T>
+      struct vararg_max_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13332,7 +16133,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_mand_op : public opr_base<T>
+      struct vararg_mand_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13412,7 +16213,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_mor_op : public opr_base<T>
+      struct vararg_mor_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13492,7 +16293,7 @@ namespace exprtk
       };
 
       template <typename T>
-      struct vararg_multi_op : public opr_base<T>
+      struct vararg_multi_op exprtk_final : public opr_base<T>
       {
          typedef typename opr_base<T>::Type Type;
 
@@ -13513,14 +16314,13 @@ namespace exprtk
                case 7  : return process_7(arg_list);
                case 8  : return process_8(arg_list);
                default :
-                         {
-                            for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
-                            {
-                               value(arg_list[i]);
-                            }
-
-                            return value(arg_list.back());
-                         }
+                        {
+                           for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
+                           {
+                              value(arg_list[i]);
+                           }
+                           return value(arg_list.back());
+                        }
             }
          }
 
@@ -13609,7 +16409,7 @@ namespace exprtk
          static inline T process(const ivector_ptr v)
          {
             const T* vec = v->vec()->vds().data();
-            const std::size_t vec_size = v->vec()->vds().size();
+            const std::size_t vec_size = v->size();
 
             loop_unroll::details lud(vec_size);
 
@@ -13618,24 +16418,24 @@ namespace exprtk
                T result = T(0);
                int i    = 0;
 
-               exprtk_disable_fallthrough_begin
                switch (vec_size)
                {
-                  #define case_stmt(N)         \
-                  case N : result += vec[i++]; \
+                  #define case_stmt(N,fall_through) \
+                  case N : result += vec[i++];      \
+                  fall_through                      \
 
                   #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(16) case_stmt(15)
-                  case_stmt(14) case_stmt(13)
-                  case_stmt(12) case_stmt(11)
-                  case_stmt(10) case_stmt( 9)
-                  case_stmt( 8) case_stmt( 7)
-                  case_stmt( 6) case_stmt( 5)
+                  case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
+                  case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
+                  case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
+                  case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
+                  case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
+                  case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
+
                   #endif
-                  case_stmt( 4) case_stmt( 3)
-                  case_stmt( 2) case_stmt( 1)
+                  case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
+                  case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
                }
-               exprtk_disable_fallthrough_end
 
                #undef case_stmt
 
@@ -13670,24 +16470,23 @@ namespace exprtk
 
             int i = 0;
 
-            exprtk_disable_fallthrough_begin
             switch (lud.remainder)
             {
-               #define case_stmt(N)       \
-               case N : r[0] += vec[i++]; \
+               #define case_stmt(N,fall_through) \
+               case N : r[0] += vec[i++];        \
+               fall_through                      \
 
                #ifndef exprtk_disable_superscalar_unroll
-               case_stmt(15) case_stmt(14)
-               case_stmt(13) case_stmt(12)
-               case_stmt(11) case_stmt(10)
-               case_stmt( 9) case_stmt( 8)
-               case_stmt( 7) case_stmt( 6)
-               case_stmt( 5) case_stmt( 4)
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
                #endif
-               case_stmt( 3) case_stmt( 2)
-               case_stmt( 1)
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
             }
-            exprtk_disable_fallthrough_end
 
             #undef exprtk_loop
             #undef case_stmt
@@ -13710,7 +16509,7 @@ namespace exprtk
          static inline T process(const ivector_ptr v)
          {
             const T* vec = v->vec()->vds().data();
-            const std::size_t vec_size = v->vec()->vds().size();
+            const std::size_t vec_size = v->vec()->size();
 
             loop_unroll::details lud(vec_size);
 
@@ -13719,24 +16518,23 @@ namespace exprtk
                T result = T(1);
                int i    = 0;
 
-               exprtk_disable_fallthrough_begin
                switch (vec_size)
                {
-                  #define case_stmt(N)         \
-                  case N : result *= vec[i++]; \
+                  #define case_stmt(N,fall_through) \
+                  case N : result *= vec[i++];      \
+                  fall_through                      \
 
                   #ifndef exprtk_disable_superscalar_unroll
-                  case_stmt(16) case_stmt(15)
-                  case_stmt(14) case_stmt(13)
-                  case_stmt(12) case_stmt(11)
-                  case_stmt(10) case_stmt( 9)
-                  case_stmt( 8) case_stmt( 7)
-                  case_stmt( 6) case_stmt( 5)
+                  case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
+                  case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
+                  case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
+                  case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
+                  case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
+                  case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
                   #endif
-                  case_stmt( 4) case_stmt( 3)
-                  case_stmt( 2) case_stmt( 1)
+                  case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
+                  case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
                }
-               exprtk_disable_fallthrough_end
 
                #undef case_stmt
 
@@ -13771,33 +16569,32 @@ namespace exprtk
 
             int i = 0;
 
-            exprtk_disable_fallthrough_begin
             switch (lud.remainder)
             {
-               #define case_stmt(N)       \
-               case N : r[0] *= vec[i++]; \
+               #define case_stmt(N,fall_through) \
+               case N : r[0] *= vec[i++];        \
+               fall_through                      \
 
                #ifndef exprtk_disable_superscalar_unroll
-               case_stmt(15) case_stmt(14)
-               case_stmt(13) case_stmt(12)
-               case_stmt(11) case_stmt(10)
-               case_stmt( 9) case_stmt( 8)
-               case_stmt( 7) case_stmt( 6)
-               case_stmt( 5) case_stmt( 4)
+               case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
+               case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
+               case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
+               case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
+               case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
+               case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
                #endif
-               case_stmt( 3) case_stmt( 2)
-               case_stmt( 1)
+               case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
+               case_stmt( 1, (void)0;)
             }
-            exprtk_disable_fallthrough_end
 
             #undef exprtk_loop
             #undef case_stmt
 
             return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
                    #ifndef exprtk_disable_superscalar_unroll
-                 + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
-                 + (r[ 8] * r[ 9] * r[10] * r[11])
-                 + (r[12] * r[13] * r[14] * r[15])
+                 * (r[ 4] * r[ 5] * r[ 6] * r[ 7])
+                 * (r[ 8] * r[ 9] * r[10] * r[11])
+                 * (r[12] * r[13] * r[14] * r[15])
                    #endif
                    ;
          }
@@ -13810,8 +16607,7 @@ namespace exprtk
 
          static inline T process(const ivector_ptr v)
          {
-            const std::size_t vec_size = v->vec()->vds().size();
-
+            const T vec_size = T(v->vec()->size());
             return vec_add_op<T>::process(v) / vec_size;
          }
       };
@@ -13824,7 +16620,7 @@ namespace exprtk
          static inline T process(const ivector_ptr v)
          {
             const T* vec = v->vec()->vds().data();
-            const std::size_t vec_size = v->vec()->vds().size();
+            const std::size_t vec_size = v->vec()->size();
 
             T result = vec[0];
 
@@ -13848,7 +16644,7 @@ namespace exprtk
          static inline T process(const ivector_ptr v)
          {
             const T* vec = v->vec()->vds().data();
-            const std::size_t vec_size = v->vec()->vds().size();
+            const std::size_t vec_size = v->vec()->size();
 
             T result = vec[0];
 
@@ -13887,8 +16683,8 @@ namespace exprtk
       {
       public:
 
-       virtual ~cov_base_node()
-          {}
+         virtual ~cov_base_node()
+         {}
 
          inline virtual operator_type operation() const
          {
@@ -14047,7 +16843,7 @@ namespace exprtk
       };
 
       template <typename T, typename Operation>
-      class unary_variable_node : public uv_base_node<T>
+      class unary_variable_node exprtk_final : public uv_base_node<T>
       {
       public:
 
@@ -14058,70 +16854,64 @@ namespace exprtk
          : v_(var)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Operation::process(v_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
 
-         inline const T& v() const
+         inline const T& v() const exprtk_override
          {
             return v_;
          }
 
       private:
 
-         unary_variable_node(unary_variable_node<T,Operation>&);
-         unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
+         unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete;
+         unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete;
 
          const T& v_;
       };
 
       template <typename T>
-      class uvouv_node : public expression_node<T>
+      class uvouv_node exprtk_final : public expression_node<T>
       {
       public:
 
          // UOpr1(v0) Op UOpr2(v1)
-
-         typedef expression_node<T>* expression_ptr;
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
-         typedef typename functor_t::ufunc_t      ufunc_t;
+         typedef typename functor_t::bfunc_t    bfunc_t;
+         typedef typename functor_t::ufunc_t    ufunc_t;
+         typedef expression_node<T>*            expression_ptr;
 
          explicit uvouv_node(const T& var0,const T& var1,
                              ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
-         : v0_(var0),
-           v1_(var1),
-           u0_(uf0 ),
-           u1_(uf1 ),
-           f_ (bf  )
+         : v0_(var0)
+         , v1_(var1)
+         , u0_(uf0 )
+         , u1_(uf1 )
+         , f_ (bf  )
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return f_(u0_(v0_),u1_(v1_));
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_uvouv;
          }
 
-         inline operator_type operation() const
-         {
-            return details::e_default;
-         }
-
          inline const T& v0()
          {
             return v0_;
@@ -14149,8 +16939,8 @@ namespace exprtk
 
       private:
 
-         uvouv_node(uvouv_node<T>&);
-         uvouv_node<T>& operator=(uvouv_node<T>&);
+         uvouv_node(const uvouv_node<T>&) exprtk_delete;
+         uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete;
 
          const T& v0_;
          const T& v1_;
@@ -14160,35 +16950,40 @@ namespace exprtk
       };
 
       template <typename T, typename Operation>
-      class unary_branch_node : public expression_node<T>
+      class unary_branch_node exprtk_final : public expression_node<T>
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
+         typedef Operation                      operation_t;
+         typedef expression_node<T>*            expression_ptr;
          typedef std::pair<expression_ptr,bool> branch_t;
-         typedef Operation operation_t;
 
          explicit unary_branch_node(expression_ptr branch)
          {
             construct_branch_pair(branch_, branch);
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Operation::process(branch_.first->value());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline bool valid() const exprtk_override
+         {
+            return branch_.first && branch_.first->valid();
+         }
+
+         inline operator_type operation()
          {
             return Operation::operation();
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return branch_.first;
          }
@@ -14198,20 +16993,20 @@ namespace exprtk
             branch_.second = false;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         unary_branch_node(unary_branch_node<T,Operation>&);
-         unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
+         unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete;
+         unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete;
 
          branch_t branch_;
       };
@@ -14237,7 +17032,7 @@ namespace exprtk
       struct T0oT1oT2process
       {
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef typename functor_t::bfunc_t    bfunc_t;
 
          struct mode0
          {
@@ -14280,7 +17075,7 @@ namespace exprtk
       struct T0oT1oT20T3process
       {
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef typename functor_t::bfunc_t    bfunc_t;
 
          struct mode0
          {
@@ -14394,7 +17189,7 @@ namespace exprtk
       template <typename T, typename T0, typename T1>
       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
 
-      #define synthesis_node_type_define(T0_,T1_,v_)                                                            \
+      #define synthesis_node_type_define(T0_, T1_, v_)                                                          \
       template <typename T, typename T0, typename T1>                                                           \
       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
       template <typename T, typename T0, typename T1>                                                           \
@@ -14416,7 +17211,7 @@ namespace exprtk
       template <typename T, typename T0, typename T1, typename T2>
       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
 
-      #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
+      #define synthesis_node_type_define(T0_, T1_, T2_, v_)                                                            \
       template <typename T, typename T0, typename T1, typename T2>                                                     \
       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
       template <typename T, typename T0, typename T1, typename T2>                                                     \
@@ -14438,7 +17233,7 @@ namespace exprtk
       template <typename T, typename T0, typename T1, typename T2, typename T3>
       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
 
-      #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
+      #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_)                                                              \
       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
@@ -14463,33 +17258,33 @@ namespace exprtk
       #undef synthesis_node_type_define
 
       template <typename T, typename T0, typename T1>
-      class T0oT1 : public expression_node<T>
+      class T0oT1 exprtk_final : public expression_node<T>
       {
       public:
 
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef typename functor_t::bfunc_t    bfunc_t;
          typedef T value_type;
          typedef T0oT1<T,T0,T1> node_type;
 
          T0oT1(T0 p0, T1 p1, const bfunc_t p2)
-         : t0_(p0),
-           t1_(p1),
-           f_ (p2)
+         : t0_(p0)
+         , t1_(p1)
+         , f_ (p2)
          {}
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
             return result;
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return e_default;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return f_(t0_,t1_);
          }
@@ -14521,8 +17316,8 @@ namespace exprtk
 
       private:
 
-         T0oT1(T0oT1<T,T0,T1>&) {}
-         T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
+         T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete;
+         T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); }
 
          T0 t0_;
          T1 t1_;
@@ -14530,36 +17325,36 @@ namespace exprtk
       };
 
       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
-      class T0oT1oT2 : public T0oT1oT2_base_node<T>
+      class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T>
       {
       public:
 
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef typename functor_t::bfunc_t    bfunc_t;
          typedef T value_type;
          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
          typedef ProcessMode process_mode_t;
 
          T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           f0_(p3),
-           f1_(p4)
+         : t0_(p0)
+         , t1_(p1)
+         , t2_(p2)
+         , f0_(p3)
+         , f1_(p4)
          {}
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
             return result;
          }
 
-         inline operator_type operation() const
+         inline operator_type operation()
          {
             return e_default;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
          }
@@ -14589,7 +17384,7 @@ namespace exprtk
             return f1_;
          }
 
-         std::string type_id() const
+         std::string type_id() const exprtk_override
          {
             return id();
          }
@@ -14609,8 +17404,8 @@ namespace exprtk
 
       private:
 
-         T0oT1oT2(node_type&) {}
-         node_type& operator=(node_type&) { return (*this); }
+         T0oT1oT2(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
 
          T0 t0_;
          T1 t1_;
@@ -14620,12 +17415,12 @@ namespace exprtk
       };
 
       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
-      class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
+      class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T>
       {
       public:
 
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef typename functor_t::bfunc_t    bfunc_t;
          typedef T value_type;
          typedef T0_ T0;
          typedef T1_ T1;
@@ -14635,16 +17430,16 @@ namespace exprtk
          typedef ProcessMode process_mode_t;
 
          T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           t3_(p3),
-           f0_(p4),
-           f1_(p5),
-           f2_(p6)
+         : t0_(p0)
+         , t1_(p1)
+         , t2_(p2)
+         , t3_(p3)
+         , f0_(p4)
+         , f1_(p5)
+         , f2_(p6)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
          }
@@ -14684,7 +17479,7 @@ namespace exprtk
             return f2_;
          }
 
-         inline std::string type_id() const
+         inline std::string type_id() const exprtk_override
          {
             return id();
          }
@@ -14706,8 +17501,8 @@ namespace exprtk
 
       private:
 
-         T0oT1oT2oT3(node_type&) {}
-         node_type& operator=(node_type&) { return (*this); }
+         T0oT1oT2oT3(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
 
          T0 t0_;
          T1 t1_;
@@ -14719,34 +17514,34 @@ namespace exprtk
       };
 
       template <typename T, typename T0, typename T1, typename T2>
-      class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
+      class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T>
       {
       public:
 
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::tfunc_t      tfunc_t;
+         typedef typename functor_t::tfunc_t    tfunc_t;
          typedef T value_type;
          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
 
          T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           f_ (p3)
+         : t0_(p0)
+         , t1_(p1)
+         , t2_(p2)
+         , f_ (p3)
          {}
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
             return result;
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return e_default;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return f_(t0_, t1_, t2_);
          }
@@ -14791,8 +17586,8 @@ namespace exprtk
 
       private:
 
-         T0oT1oT2_sf3(node_type&) {}
-         node_type& operator=(node_type&) { return (*this); }
+         T0oT1oT2_sf3(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
 
          T0 t0_;
          T1 t1_;
@@ -14816,53 +17611,51 @@ namespace exprtk
       };
 
       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
-      class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
+      class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2>
       {
       public:
 
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::tfunc_t      tfunc_t;
          typedef T value_type;
-         typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
+         typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type;
 
          T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2)
+         : t0_(p0)
+         , t1_(p1)
+         , t2_(p2)
          {}
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
             return result;
          }
 
-         inline operator_type operation() const
+         inline operator_type operation()
          {
             return e_default;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return SF3Operation::process(t0_, t1_, t2_);
          }
 
-         T0 t0() const
+         T0 t0() const exprtk_override
          {
             return t0_;
          }
 
-         T1 t1() const
+         T1 t1() const exprtk_override
          {
             return t1_;
          }
 
-         T2 t2() const
+         T2 t2() const exprtk_override
          {
             return t2_;
          }
 
-         std::string type_id() const
+         std::string type_id() const exprtk_override
          {
             return id();
          }
@@ -14882,8 +17675,8 @@ namespace exprtk
 
       private:
 
-         T0oT1oT2_sf3ext(node_type&) {}
-         node_type& operator=(node_type&) { return (*this); }
+         T0oT1oT2_sf3ext(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
 
          T0 t0_;
          T1 t1_;
@@ -14905,35 +17698,35 @@ namespace exprtk
       }
 
       template <typename T, typename T0, typename T1, typename T2, typename T3>
-      class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
+      class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T>
       {
       public:
 
          typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::qfunc_t      qfunc_t;
+         typedef typename functor_t::qfunc_t    qfunc_t;
          typedef T value_type;
-         typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
+         typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type;
 
          T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           t3_(p3),
-           f_ (p4)
+         : t0_(p0)
+         , t1_(p1)
+         , t2_(p2)
+         , t3_(p3)
+         , f_ (p4)
          {}
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
             return result;
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return e_default;
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return f_(t0_, t1_, t2_, t3_);
          }
@@ -14983,8 +17776,8 @@ namespace exprtk
 
       private:
 
-         T0oT1oT2oT3_sf4(node_type&) {}
-         node_type& operator=(node_type&) { return (*this); }
+         T0oT1oT2oT3_sf4(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
 
          T0 t0_;
          T1 t1_;
@@ -14994,34 +17787,27 @@ namespace exprtk
       };
 
       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
-      class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
+      class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T>
       {
       public:
 
-         typedef typename details::functor_t<T> functor_t;
-         typedef typename functor_t::tfunc_t      tfunc_t;
          typedef T value_type;
-         typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
+         typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type;
 
          T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
-         : t0_(p0),
-           t1_(p1),
-           t2_(p2),
-           t3_(p3)
+         : t0_(p0)
+         , t1_(p1)
+         , t2_(p2)
+         , t3_(p3)
          {}
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
             return result;
          }
 
-         inline operator_type operation() const
-         {
-            return e_default;
-         }
-
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return SF4Operation::process(t0_, t1_, t2_, t3_);
          }
@@ -15046,7 +17832,7 @@ namespace exprtk
             return t3_;
          }
 
-         std::string type_id() const
+         std::string type_id() const exprtk_override
          {
             return id();
          }
@@ -15066,8 +17852,8 @@ namespace exprtk
 
       private:
 
-         T0oT1oT2oT3_sf4ext(node_type&) {}
-         node_type& operator=(node_type&) { return (*this); }
+         T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
 
          T0 t0_;
          T1 t1_;
@@ -15120,7 +17906,7 @@ namespace exprtk
       };
 
       template <typename T, typename Operation>
-      class vov_node : public vov_base_node<T>
+      class vov_node exprtk_final : public vov_base_node<T>
       {
       public:
 
@@ -15129,31 +17915,31 @@ namespace exprtk
 
          // variable op variable node
          explicit vov_node(const T& var0, const T& var1)
-         : v0_(var0),
-           v1_(var1)
+         : v0_(var0)
+         , v1_(var1)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Operation::process(v0_,v1_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
 
-         inline const T& v0() const
+         inline const T& v0() const exprtk_override
          {
             return v0_;
          }
 
-         inline const T& v1() const
+         inline const T& v1() const exprtk_override
          {
             return v1_;
          }
@@ -15165,12 +17951,12 @@ namespace exprtk
 
       private:
 
-         vov_node(vov_node<T,Operation>&);
-         vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
+         vov_node(const vov_node<T,Operation>&) exprtk_delete;
+         vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete;
       };
 
       template <typename T, typename Operation>
-      class cov_node : public cov_base_node<T>
+      class cov_node exprtk_final : public cov_base_node<T>
       {
       public:
 
@@ -15179,31 +17965,31 @@ namespace exprtk
 
          // constant op variable node
          explicit cov_node(const T& const_var, const T& var)
-         : c_(const_var),
-           v_(var)
+         : c_(const_var)
+         , v_(var)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Operation::process(c_,v_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
 
-         inline const T c() const
+         inline const T c() const exprtk_override
          {
             return c_;
          }
 
-         inline const T& v() const
+         inline const T& v() const exprtk_override
          {
             return v_;
          }
@@ -15215,12 +18001,12 @@ namespace exprtk
 
       private:
 
-         cov_node(const cov_node<T,Operation>&);
-         cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
+         cov_node(const cov_node<T,Operation>&) exprtk_delete;
+         cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete;
       };
 
       template <typename T, typename Operation>
-      class voc_node : public voc_base_node<T>
+      class voc_node exprtk_final : public voc_base_node<T>
       {
       public:
 
@@ -15229,26 +18015,26 @@ namespace exprtk
 
          // variable op constant node
          explicit voc_node(const T& var, const T& const_var)
-         : v_(var),
-           c_(const_var)
+         : v_(var)
+         , c_(const_var)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Operation::process(v_,c_);
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
 
-         inline const T c() const
+         inline const T c() const exprtk_override
          {
             return c_;
          }
 
-         inline const T& v() const
+         inline const T& v() const exprtk_override
          {
             return v_;
          }
@@ -15260,12 +18046,12 @@ namespace exprtk
 
       private:
 
-         voc_node(const voc_node<T,Operation>&);
-         voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
+         voc_node(const voc_node<T,Operation>&) exprtk_delete;
+         voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete;
       };
 
       template <typename T, typename Operation>
-      class vob_node : public vob_base_node<T>
+      class vob_node exprtk_final : public vob_base_node<T>
       {
       public:
 
@@ -15273,55 +18059,55 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
          typedef Operation operation_t;
 
-         // variable op constant node
+         // variable op binary node
          explicit vob_node(const T& var, const expression_ptr branch)
          : v_(var)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
             return Operation::process(v_,branch_.first->value());
          }
 
-         inline operator_type operation() const
+         inline const T& v() const exprtk_override
          {
-            return Operation::operation();
+            return v_;
          }
 
-         inline const T& v() const
+         inline bool valid() const exprtk_override
          {
-            return v_;
+            return branch_.first && branch_.first->valid();
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return branch_.first;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         vob_node(const vob_node<T,Operation>&);
-         vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
+         vob_node(const vob_node<T,Operation>&) exprtk_delete;
+         vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete;
 
          const T& v_;
          branch_t branch_;
       };
 
       template <typename T, typename Operation>
-      class bov_node : public bov_base_node<T>
+      class bov_node exprtk_final : public bov_base_node<T>
       {
       public:
 
@@ -15329,55 +18115,55 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
          typedef Operation operation_t;
 
-         // variable op constant node
+         // binary node op variable node
          explicit bov_node(const expression_ptr branch, const T& var)
          : v_(var)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
             return Operation::process(branch_.first->value(),v_);
          }
 
-         inline operator_type operation() const
+         inline const T& v() const exprtk_override
          {
-            return Operation::operation();
+            return v_;
          }
 
-         inline const T& v() const
+         inline bool valid() const exprtk_override
          {
-            return v_;
+            return branch_.first && branch_.first->valid();
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return branch_.first;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         bov_node(const bov_node<T,Operation>&);
-         bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
+         bov_node(const bov_node<T,Operation>&) exprtk_delete;
+         bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete;
 
          const T& v_;
          branch_t branch_;
       };
 
       template <typename T, typename Operation>
-      class cob_node : public cob_base_node<T>
+      class cob_node exprtk_final : public cob_base_node<T>
       {
       public:
 
@@ -15385,66 +18171,71 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
          typedef Operation operation_t;
 
-         // variable op constant node
+         // constant op variable node
          explicit cob_node(const T const_var, const expression_ptr branch)
          : c_(const_var)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
             return Operation::process(c_,branch_.first->value());
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
 
-         inline const T c() const
+         inline const T c() const exprtk_override
          {
             return c_;
          }
 
-         inline void set_c(const T new_c)
+         inline void set_c(const T new_c) exprtk_override
          {
             (*const_cast<T*>(&c_)) = new_c;
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline bool valid() const exprtk_override
+         {
+            return branch_.first && branch_.first->valid();
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return branch_.first;
          }
 
-         inline expression_node<T>* move_branch(const std::size_t&)
+         inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
          {
             branch_.second = false;
             return branch_.first;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         cob_node(const cob_node<T,Operation>&);
-         cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
+         cob_node(const cob_node<T,Operation>&) exprtk_delete;
+         cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete;
 
          const T  c_;
          branch_t branch_;
       };
 
       template <typename T, typename Operation>
-      class boc_node : public boc_base_node<T>
+      class boc_node exprtk_final : public boc_base_node<T>
       {
       public:
 
@@ -15452,59 +18243,64 @@ namespace exprtk
          typedef std::pair<expression_ptr,bool> branch_t;
          typedef Operation operation_t;
 
-         // variable op constant node
+         // binary node op constant node
          explicit boc_node(const expression_ptr branch, const T const_var)
          : c_(const_var)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
             return Operation::process(branch_.first->value(),c_);
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
 
-         inline const T c() const
+         inline const T c() const exprtk_override
          {
             return c_;
          }
 
-         inline void set_c(const T new_c)
+         inline void set_c(const T new_c) exprtk_override
          {
             (*const_cast<T*>(&c_)) = new_c;
          }
 
-         inline expression_node<T>* branch(const std::size_t&) const
+         inline bool valid() const exprtk_override
+         {
+            return branch_.first && branch_.first->valid();
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const exprtk_override
          {
             return branch_.first;
          }
 
-         inline expression_node<T>* move_branch(const std::size_t&)
+         inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
          {
             branch_.second = false;
             return branch_.first;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         boc_node(const boc_node<T,Operation>&);
-         boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
+         boc_node(const boc_node<T,Operation>&) exprtk_delete;
+         boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete;
 
          const T  c_;
          branch_t branch_;
@@ -15512,7 +18308,7 @@ namespace exprtk
 
       #ifndef exprtk_disable_string_capabilities
       template <typename T, typename SType0, typename SType1, typename Operation>
-      class sos_node : public sos_base_node<T>
+      class sos_node exprtk_final : public sos_base_node<T>
       {
       public:
 
@@ -15521,21 +18317,21 @@ namespace exprtk
 
          // string op string node
          explicit sos_node(SType0 p0, SType1 p1)
-         : s0_(p0),
-           s1_(p1)
+         : s0_(p0)
+         , s1_(p1)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return Operation::process(s0_,s1_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
@@ -15557,23 +18353,24 @@ namespace exprtk
 
       private:
 
-         sos_node(sos_node<T,SType0,SType1,Operation>&);
-         sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
+         sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
+         sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
       };
 
       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
-      class str_xrox_node : public sos_base_node<T>
+      class str_xrox_node exprtk_final : public sos_base_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
          typedef Operation operation_t;
+         typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type;
 
          // string-range op string node
          explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
-         : s0_ (p0 ),
-           s1_ (p1 ),
-           rp0_(rp0)
+         : s0_ (p0 )
+         , s1_ (p1 )
+         , rp0_(rp0)
          {}
 
         ~str_xrox_node()
@@ -15581,7 +18378,7 @@ namespace exprtk
             rp0_.free();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             std::size_t r0 = 0;
             std::size_t r1 = 0;
@@ -15592,12 +18389,12 @@ namespace exprtk
                return T(0);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
@@ -15620,23 +18417,24 @@ namespace exprtk
 
       private:
 
-         str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
-         str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
+         str_xrox_node(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
       };
 
       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
-      class str_xoxr_node : public sos_base_node<T>
+      class str_xoxr_node exprtk_final : public sos_base_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
          typedef Operation operation_t;
+         typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type;
 
          // string op string range node
          explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
-         : s0_ (p0 ),
-           s1_ (p1 ),
-           rp1_(rp1)
+         : s0_ (p0 )
+         , s1_ (p1 )
+         , rp1_(rp1)
          {}
 
         ~str_xoxr_node()
@@ -15644,23 +18442,29 @@ namespace exprtk
             rp1_.free();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             std::size_t r0 = 0;
             std::size_t r1 = 0;
 
             if (rp1_(r0, r1, s1_.size()))
-               return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
+            {
+               return Operation::process
+                      (
+                         s0_,
+                         s1_.substr(r0, (r1 - r0) + 1)
+                      );
+            }
             else
                return T(0);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
@@ -15683,24 +18487,25 @@ namespace exprtk
 
       private:
 
-         str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
-         str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
+         str_xoxr_node(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
       };
 
       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
-      class str_xroxr_node : public sos_base_node<T>
+      class str_xroxr_node exprtk_final : public sos_base_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
          typedef Operation operation_t;
+         typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type;
 
          // string-range op string-range node
          explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
-         : s0_ (p0 ),
-           s1_ (p1 ),
-           rp0_(rp0),
-           rp1_(rp1)
+         : s0_ (p0 )
+         , s1_ (p1 )
+         , rp0_(rp0)
+         , rp1_(rp1)
          {}
 
         ~str_xroxr_node()
@@ -15709,7 +18514,7 @@ namespace exprtk
             rp1_.free();
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             std::size_t r0_0 = 0;
             std::size_t r0_1 = 0;
@@ -15721,21 +18526,22 @@ namespace exprtk
                  rp1_(r0_1, r1_1, s1_.size())
                )
             {
-               return Operation::process(
-                                          s0_.substr(r0_0, (r1_0 - r0_0) + 1),
-                                          s1_.substr(r0_1, (r1_1 - r0_1) + 1)
-                                        );
+               return Operation::process
+                      (
+                         s0_.substr(r0_0, (r1_0 - r0_0) + 1),
+                         s1_.substr(r0_1, (r1_1 - r0_1) + 1)
+                      );
             }
             else
                return T(0);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
@@ -15759,39 +18565,42 @@ namespace exprtk
 
       private:
 
-         str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
-         str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
+         str_xroxr_node(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
       };
 
       template <typename T, typename Operation>
-      class str_sogens_node : public binary_node<T>
+      class str_sogens_node exprtk_final : public binary_node<T>
       {
       public:
 
          typedef expression_node <T>* expression_ptr;
-         typedef string_base_node<T>*   str_base_ptr;
-         typedef range_pack      <T>         range_t;
-         typedef range_t*                  range_ptr;
-         typedef range_interface<T>         irange_t;
-         typedef irange_t*                irange_ptr;
+         typedef string_base_node<T>* str_base_ptr;
+         typedef range_pack      <T>  range_t;
+         typedef range_t*             range_ptr;
+         typedef range_interface <T>  irange_t;
+         typedef irange_t*            irange_ptr;
+
+         using binary_node<T>::branch;
 
          str_sogens_node(const operator_type& opr,
                          expression_ptr branch0,
                          expression_ptr branch1)
-         : binary_node<T>(opr, branch0, branch1),
-           str0_base_ptr_ (0),
-           str1_base_ptr_ (0),
-           str0_range_ptr_(0),
-           str1_range_ptr_(0)
+         : binary_node<T>(opr, branch0, branch1)
+         , str0_base_ptr_ (0)
+         , str1_base_ptr_ (0)
+         , str0_range_ptr_(0)
+         , str1_range_ptr_(0)
+         , initialised_   (false)
          {
-            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            if (is_generally_string_node(branch(0)))
             {
-               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
 
                if (0 == str0_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
 
                if (0 == range)
                   return;
@@ -15799,105 +18608,108 @@ namespace exprtk
                str0_range_ptr_ = &(range->range_ref());
             }
 
-            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            if (is_generally_string_node(branch(1)))
             {
-               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
 
                if (0 == str1_base_ptr_)
                   return;
 
-               irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+               irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
 
                if (0 == range)
                   return;
 
                str1_range_ptr_ = &(range->range_ref());
             }
+
+            initialised_ =
+               str0_base_ptr_  &&
+               str1_base_ptr_  &&
+               str0_range_ptr_ &&
+               str1_range_ptr_;
+
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            if (
-                 str0_base_ptr_  &&
-                 str1_base_ptr_  &&
-                 str0_range_ptr_ &&
-                 str1_range_ptr_
-               )
-            {
-               binary_node<T>::branch_[0].first->value();
-               binary_node<T>::branch_[1].first->value();
+            branch(0)->value();
+            branch(1)->value();
 
-               std::size_t str0_r0 = 0;
-               std::size_t str0_r1 = 0;
+            std::size_t str0_r0 = 0;
+            std::size_t str0_r1 = 0;
 
-               std::size_t str1_r0 = 0;
-               std::size_t str1_r1 = 0;
+            std::size_t str1_r0 = 0;
+            std::size_t str1_r1 = 0;
 
-               const range_t& range0 = (*str0_range_ptr_);
-               const range_t& range1 = (*str1_range_ptr_);
+            const range_t& range0 = (*str0_range_ptr_);
+            const range_t& range1 = (*str1_range_ptr_);
 
-               if (
-                    range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
-                    range1(str1_r0, str1_r1, str1_base_ptr_->size())
-                  )
-               {
-                  return Operation::process(
-                                             str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
-                                             str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
-                                           );
-               }
+            if (
+                 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
+                 range1(str1_r0, str1_r1, str1_base_ptr_->size())
+               )
+            {
+               return Operation::process
+                      (
+                         str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)),
+                         str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0))
+                      );
             }
 
             return std::numeric_limits<T>::quiet_NaN();
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline bool valid() const exprtk_override
          {
-            return Operation::operation();
+            return initialised_;
          }
 
       private:
 
-         str_sogens_node(str_sogens_node<T,Operation>&);
-         str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
+         str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete;
+         str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete;
 
          str_base_ptr str0_base_ptr_;
          str_base_ptr str1_base_ptr_;
          range_ptr    str0_range_ptr_;
          range_ptr    str1_range_ptr_;
+         bool         initialised_;
       };
 
       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
-      class sosos_node : public sosos_base_node<T>
+      class sosos_node exprtk_final : public sosos_base_node<T>
       {
       public:
 
          typedef expression_node<T>* expression_ptr;
          typedef Operation operation_t;
+         typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type;
 
-         // variable op variable node
+         // string op string op string node
          explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
-         : s0_(p0),
-           s1_(p1),
-           s2_(p2)
+         : s0_(p0)
+         , s1_(p1)
+         , s2_(p2)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            return Operation::process(s0_,s1_,s2_);
+            return Operation::process(s0_, s1_, s2_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return Operation::type();
          }
 
-         inline operator_type operation() const
+         inline operator_type operation() const exprtk_override
          {
             return Operation::operation();
          }
@@ -15925,13 +18737,13 @@ namespace exprtk
 
       private:
 
-         sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
-         sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
+         sosos_node(const node_type&) exprtk_delete;
+         node_type& operator=(const node_type&) exprtk_delete;
       };
       #endif
 
       template <typename T, typename PowOp>
-      class ipow_node : public expression_node<T>
+      class ipow_node exprtk_final: public expression_node<T>
       {
       public:
 
@@ -15942,26 +18754,26 @@ namespace exprtk
          : v_(v)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return PowOp::result(v_);
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_ipow;
          }
 
       private:
 
-         ipow_node(const ipow_node<T,PowOp>&);
-         ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
+         ipow_node(const ipow_node<T,PowOp>&) exprtk_delete;
+         ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete;
 
          const T& v_;
       };
 
       template <typename T, typename PowOp>
-      class bipow_node : public expression_node<T>
+      class bipow_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -15972,39 +18784,44 @@ namespace exprtk
          explicit bipow_node(expression_ptr branch)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
             return PowOp::result(branch_.first->value());
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_ipow;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
+         {
+            return branch_.first && branch_.first->valid();
+         }
+
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
          {
             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
          }
 
-         std::size_t node_depth() const
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         bipow_node(const bipow_node<T,PowOp>&);
-         bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
+         bipow_node(const bipow_node<T,PowOp>&) exprtk_delete;
+         bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete;
 
          branch_t branch_;
       };
 
       template <typename T, typename PowOp>
-      class ipowinv_node : public expression_node<T>
+      class ipowinv_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -16015,26 +18832,26 @@ namespace exprtk
          : v_(v)
          {}
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
             return (T(1) / PowOp::result(v_));
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_ipowinv;
          }
 
       private:
 
-         ipowinv_node(const ipowinv_node<T,PowOp>&);
-         ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
+         ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete;
+         ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete;
 
          const T& v_;
       };
 
       template <typename T, typename PowOp>
-      class bipowninv_node : public expression_node<T>
+      class bipowinv_node exprtk_final : public expression_node<T>
       {
       public:
 
@@ -16042,36 +18859,41 @@ namespace exprtk
          typedef std::pair<expression_ptr, bool> branch_t;
          typedef PowOp operation_t;
 
-         explicit bipowninv_node(expression_ptr branch)
+         explicit bipowinv_node(expression_ptr branch)
          {
             construct_branch_pair(branch_, branch);
+            assert(valid());
          }
 
-         inline T value() const
+         inline T value() const exprtk_override
          {
-            assert(branch_.first);
             return (T(1) / PowOp::result(branch_.first->value()));
          }
 
-         inline typename expression_node<T>::node_type type() const
+         inline typename expression_node<T>::node_type type() const exprtk_override
          {
             return expression_node<T>::e_ipowinv;
          }
 
-         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
+         inline bool valid() const exprtk_override
          {
-            expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
+            return branch_.first && branch_.first->valid();
          }
 
-         std::size_t node_depth() const
+         void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
+         {
+            expression_node<T>::ndb_t::collect(branch_, node_delete_list);
+         }
+
+         std::size_t node_depth() const exprtk_override
          {
             return expression_node<T>::ndb_t::compute_node_depth(branch_);
          }
 
       private:
 
-         bipowninv_node(const bipowninv_node<T,PowOp>&);
-         bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
+         bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete;
+         bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete;
 
          branch_t branch_;
       };
@@ -16215,6 +19037,46 @@ namespace exprtk
          return false;
       }
 
+      template <typename T>
+      inline bool is_loop_node(const expression_node<T>* node)
+      {
+         if (node)
+         {
+            switch (node->type())
+            {
+               case expression_node<T>::e_for    :
+               case expression_node<T>::e_repeat :
+               case expression_node<T>::e_while  : return true;
+               default                           : return false;
+            }
+         }
+
+         return false;
+      }
+
+      template <typename T>
+      inline bool is_block_node(const expression_node<T>* node)
+      {
+         if (node)
+         {
+            if (is_loop_node(node))
+            {
+               return true;
+            }
+
+            switch (node->type())
+            {
+               case expression_node<T>::e_conditional :
+               case expression_node<T>::e_mswitch     :
+               case expression_node<T>::e_switch      :
+               case expression_node<T>::e_vararg      : return true;
+               default                                : return false;
+            }
+         }
+
+         return false;
+      }
+
       class node_allocator
       {
       public:
@@ -16603,61 +19465,61 @@ namespace exprtk
 
       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
       {
-         #define register_op(Symbol,Type,Args)                                               \
+         #define register_op(Symbol, Type, Args)                                             \
          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
 
-         register_op(      "abs", e_abs     , 1)
-         register_op(     "acos", e_acos    , 1)
-         register_op(    "acosh", e_acosh   , 1)
-         register_op(     "asin", e_asin    , 1)
-         register_op(    "asinh", e_asinh   , 1)
-         register_op(     "atan", e_atan    , 1)
-         register_op(    "atanh", e_atanh   , 1)
-         register_op(     "ceil", e_ceil    , 1)
-         register_op(      "cos", e_cos     , 1)
-         register_op(     "cosh", e_cosh    , 1)
-         register_op(      "exp", e_exp     , 1)
-         register_op(    "expm1", e_expm1   , 1)
-         register_op(    "floor", e_floor   , 1)
-         register_op(      "log", e_log     , 1)
-         register_op(    "log10", e_log10   , 1)
-         register_op(     "log2", e_log2    , 1)
-         register_op(    "log1p", e_log1p   , 1)
-         register_op(    "round", e_round   , 1)
-         register_op(      "sin", e_sin     , 1)
-         register_op(     "sinc", e_sinc    , 1)
-         register_op(     "sinh", e_sinh    , 1)
-         register_op(      "sec", e_sec     , 1)
-         register_op(      "csc", e_csc     , 1)
-         register_op(     "sqrt", e_sqrt    , 1)
-         register_op(      "tan", e_tan     , 1)
-         register_op(     "tanh", e_tanh    , 1)
-         register_op(      "cot", e_cot     , 1)
-         register_op(  "rad2deg", e_r2d     , 1)
-         register_op(  "deg2rad", e_d2r     , 1)
-         register_op( "deg2grad", e_d2g     , 1)
-         register_op( "grad2deg", e_g2d     , 1)
-         register_op(      "sgn", e_sgn     , 1)
-         register_op(      "not", e_notl    , 1)
-         register_op(      "erf", e_erf     , 1)
-         register_op(     "erfc", e_erfc    , 1)
-         register_op(     "ncdf", e_ncdf    , 1)
-         register_op(     "frac", e_frac    , 1)
-         register_op(    "trunc", e_trunc   , 1)
-         register_op(    "atan2", e_atan2   , 2)
-         register_op(      "mod", e_mod     , 2)
-         register_op(     "logn", e_logn    , 2)
-         register_op(      "pow", e_pow     , 2)
-         register_op(     "root", e_root    , 2)
-         register_op(   "roundn", e_roundn  , 2)
-         register_op(    "equal", e_equal   , 2)
-         register_op("not_equal", e_nequal  , 2)
-         register_op(    "hypot", e_hypot   , 2)
-         register_op(      "shr", e_shr     , 2)
-         register_op(      "shl", e_shl     , 2)
-         register_op(    "clamp", e_clamp   , 3)
-         register_op(   "iclamp", e_iclamp  , 3)
-         register_op(  "inrange", e_inrange , 3)
+         register_op("abs"       , e_abs     , 1)
+         register_op("acos"      , e_acos    , 1)
+         register_op("acosh"     , e_acosh   , 1)
+         register_op("asin"      , e_asin    , 1)
+         register_op("asinh"     , e_asinh   , 1)
+         register_op("atan"      , e_atan    , 1)
+         register_op("atanh"     , e_atanh   , 1)
+         register_op("ceil"      , e_ceil    , 1)
+         register_op("cos"       , e_cos     , 1)
+         register_op("cosh"      , e_cosh    , 1)
+         register_op("exp"       , e_exp     , 1)
+         register_op("expm1"     , e_expm1   , 1)
+         register_op("floor"     , e_floor   , 1)
+         register_op("log"       , e_log     , 1)
+         register_op("log10"     , e_log10   , 1)
+         register_op("log2"      , e_log2    , 1)
+         register_op("log1p"     , e_log1p   , 1)
+         register_op("round"     , e_round   , 1)
+         register_op("sin"       , e_sin     , 1)
+         register_op("sinc"      , e_sinc    , 1)
+         register_op("sinh"      , e_sinh    , 1)
+         register_op("sec"       , e_sec     , 1)
+         register_op("csc"       , e_csc     , 1)
+         register_op("sqrt"      , e_sqrt    , 1)
+         register_op("tan"       , e_tan     , 1)
+         register_op("tanh"      , e_tanh    , 1)
+         register_op("cot"       , e_cot     , 1)
+         register_op("rad2deg"   , e_r2d     , 1)
+         register_op("deg2rad"   , e_d2r     , 1)
+         register_op("deg2grad"  , e_d2g     , 1)
+         register_op("grad2deg"  , e_g2d     , 1)
+         register_op("sgn"       , e_sgn     , 1)
+         register_op("not"       , e_notl    , 1)
+         register_op("erf"       , e_erf     , 1)
+         register_op("erfc"      , e_erfc    , 1)
+         register_op("ncdf"      , e_ncdf    , 1)
+         register_op("frac"      , e_frac    , 1)
+         register_op("trunc"     , e_trunc   , 1)
+         register_op("atan2"     , e_atan2   , 2)
+         register_op("mod"       , e_mod     , 2)
+         register_op("logn"      , e_logn    , 2)
+         register_op("pow"       , e_pow     , 2)
+         register_op("root"      , e_root    , 2)
+         register_op("roundn"    , e_roundn  , 2)
+         register_op("equal"     , e_equal   , 2)
+         register_op("not_equal" , e_nequal  , 2)
+         register_op("hypot"     , e_hypot   , 2)
+         register_op("shr"       , e_shr     , 2)
+         register_op("shl"       , e_shl     , 2)
+         register_op("clamp"     , e_clamp   , 3)
+         register_op("iclamp"    , e_iclamp  , 3)
+         register_op("inrange"   , e_inrange , 3)
          #undef register_op
       }
 
@@ -16668,10 +19530,10 @@ namespace exprtk
    public:
 
       function_traits()
-      : allow_zero_parameters_(false),
-        has_side_effects_(true),
-        min_num_args_(0),
-        max_num_args_(std::numeric_limits<std::size_t>::max())
+      : allow_zero_parameters_(false)
+      , has_side_effects_(true)
+      , min_num_args_(0)
+      , max_num_args_(std::numeric_limits<std::size_t>::max())
       {}
 
       inline bool& allow_zero_parameters()
@@ -16873,9 +19735,9 @@ namespace exprtk
       typedef type_store<T> generic_type;
       typedef typename generic_type::parameter_list parameter_list_t;
 
-      igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
-      : parameter_sequence(param_seq),
-        rtrn_type(rtr_type)
+      explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
+      : parameter_sequence(param_seq)
+      , rtrn_type(rtr_type)
       {}
 
       virtual ~igeneric_function()
@@ -16903,10 +19765,49 @@ namespace exprtk
       inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
       igeneric_function_empty_body(4)
 
+      #undef igeneric_function_empty_body
+
       std::string parameter_sequence;
       return_type rtrn_type;
    };
 
+   #ifndef exprtk_disable_string_capabilities
+   template <typename T>
+   class stringvar_base
+   {
+   public:
+
+      typedef typename details::stringvar_node<T> stringvar_node_t;
+
+      stringvar_base(const std::string& name, stringvar_node_t* svn)
+      : name_(name)
+      , string_varnode_(svn)
+      {}
+
+      bool valid() const
+      {
+         return !name_.empty() && (0 != string_varnode_);
+      }
+
+      std::string name() const
+      {
+         assert(string_varnode_);
+         return name_;
+      }
+
+      void rebase(std::string& s)
+      {
+         assert(string_varnode_);
+         string_varnode_->rebase(s);
+      }
+
+   private:
+
+      std::string name_;
+      stringvar_node_t* string_varnode_;
+   };
+   #endif
+
    template <typename T> class parser;
    template <typename T> class expression_helper;
 
@@ -16915,71 +19816,78 @@ namespace exprtk
    {
    public:
 
-      typedef T (*ff00_functor)();
-      typedef T (*ff01_functor)(T);
-      typedef T (*ff02_functor)(T, T);
-      typedef T (*ff03_functor)(T, T, T);
-      typedef T (*ff04_functor)(T, T, T, T);
-      typedef T (*ff05_functor)(T, T, T, T, T);
-      typedef T (*ff06_functor)(T, T, T, T, T, T);
-      typedef T (*ff07_functor)(T, T, T, T, T, T, T);
-      typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
-      typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
-      typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
-      typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
+     enum symtab_mutability_type
+     {
+       e_unknown   = 0,
+       e_mutable   = 1,
+       e_immutable = 2
+     };
+
+     typedef T (*ff00_functor)();
+     typedef T (*ff01_functor)(T);
+     typedef T (*ff02_functor)(T, T);
+     typedef T (*ff03_functor)(T, T, T);
+     typedef T (*ff04_functor)(T, T, T, T);
+     typedef T (*ff05_functor)(T, T, T, T, T);
+     typedef T (*ff06_functor)(T, T, T, T, T, T);
+     typedef T (*ff07_functor)(T, T, T, T, T, T, T);
+     typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
+     typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
+     typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
+     typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
 
    protected:
 
-       struct freefunc00 : public exprtk::ifunction<T>
+       struct freefunc00 exprtk_final : public exprtk::ifunction<T>
        {
           using exprtk::ifunction<T>::operator();
 
           explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
-          inline T operator() ()
+          inline T operator() () exprtk_override
           { return f(); }
           ff00_functor f;
        };
 
-      struct freefunc01 : public exprtk::ifunction<T>
+      struct freefunc01 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
-         inline T operator() (const T& v0)
+         inline T operator() (const T& v0) exprtk_override
          { return f(v0); }
          ff01_functor f;
       };
 
-      struct freefunc02 : public exprtk::ifunction<T>
+      struct freefunc02 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
-         inline T operator() (const T& v0, const T& v1)
+         inline T operator() (const T& v0, const T& v1) exprtk_override
          { return f(v0, v1); }
          ff02_functor f;
       };
 
-      struct freefunc03 : public exprtk::ifunction<T>
+      struct freefunc03 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
-         inline T operator() (const T& v0, const T& v1, const T& v2)
+         inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override
          { return f(v0, v1, v2); }
          ff03_functor f;
       };
 
-      struct freefunc04 : public exprtk::ifunction<T>
+      struct freefunc04 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
-         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
+         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override
          { return f(v0, v1, v2, v3); }
          ff04_functor f;
       };
@@ -16989,120 +19897,120 @@ namespace exprtk
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
-         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
+         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override
          { return f(v0, v1, v2, v3, v4); }
          ff05_functor f;
       };
 
-      struct freefunc06 : public exprtk::ifunction<T>
+      struct freefunc06 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
-         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
+         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override
          { return f(v0, v1, v2, v3, v4, v5); }
          ff06_functor f;
       };
 
-      struct freefunc07 : public exprtk::ifunction<T>
+      struct freefunc07 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
-                              const T& v5, const T& v6)
+                              const T& v5, const T& v6) exprtk_override
          { return f(v0, v1, v2, v3, v4, v5, v6); }
          ff07_functor f;
       };
 
-      struct freefunc08 : public exprtk::ifunction<T>
+      struct freefunc08 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
-                              const T& v5, const T& v6, const T& v7)
+                              const T& v5, const T& v6, const T& v7) exprtk_override
          { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
          ff08_functor f;
       };
 
-      struct freefunc09 : public exprtk::ifunction<T>
+      struct freefunc09 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
-                              const T& v5, const T& v6, const T& v7, const T& v8)
+                              const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override
          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
          ff09_functor f;
       };
 
-      struct freefunc10 : public exprtk::ifunction<T>
+      struct freefunc10 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
-                              const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
+                              const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override
          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
          ff10_functor f;
       };
 
-      struct freefunc11 : public exprtk::ifunction<T>
+      struct freefunc11 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
-                              const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
+                              const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override
          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
          ff11_functor f;
       };
 
-      struct freefunc12 : public exprtk::ifunction<T>
+      struct freefunc12 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
-                              const T& v10, const T& v11)
+                              const T& v10, const T& v11) exprtk_override
          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
          ff12_functor f;
       };
 
-      struct freefunc13 : public exprtk::ifunction<T>
+      struct freefunc13 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
-                              const T& v10, const T& v11, const T& v12)
+                              const T& v10, const T& v11, const T& v12) exprtk_override
          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
          ff13_functor f;
       };
 
-      struct freefunc14 : public exprtk::ifunction<T>
+      struct freefunc14 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
-                              const T& v10, const T& v11, const T& v12, const T& v13)
+                              const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override
          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
          ff14_functor f;
       };
 
-      struct freefunc15 : public exprtk::ifunction<T>
+      struct freefunc15 exprtk_final : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
 
          explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
-                              const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
+                              const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override
          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
          ff15_functor f;
       };
@@ -17295,19 +20203,19 @@ namespace exprtk
                       (symbol_name, v, is_const);
          }
 
-         inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
+         inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false)
          {
             struct tie
             {
-               static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
+               static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false)
                {
-                  return std::make_pair(is_const, new variable_node_t(t));
+                  return std::make_pair(is_constant, new variable_node_t(t));
                }
 
                #ifndef exprtk_disable_string_capabilities
-               static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
+               static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false)
                {
-                  return std::make_pair(is_const, new stringvar_node_t(t));
+                  return std::make_pair(is_constant, new stringvar_node_t(t));
                }
                #endif
 
@@ -17316,9 +20224,9 @@ namespace exprtk
                   return std::make_pair(is_constant,&t);
                }
 
-               static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
+               static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
                {
-                  return std::make_pair(is_const,&t);
+                  return std::make_pair(is_constant,&t);
                }
 
                static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
@@ -17331,7 +20239,7 @@ namespace exprtk
 
             if (map.end() == itr)
             {
-               map[symbol_name] = tie::make(t,is_const);
+               map[symbol_name] = tie::make(t_,is_const);
                ++size;
             }
 
@@ -17362,7 +20270,7 @@ namespace exprtk
          {
             static inline bool test(const variable_node_t* p, const void* ptr)
             {
-               exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
+               exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr));
                return (&(p->ref()) == ptr);
             }
          };
@@ -17570,13 +20478,15 @@ namespace exprtk
          };
 
          control_block()
-         : ref_count(1),
-           data_(st_data::create())
+         : ref_count(1)
+         , data_(st_data::create())
+         , mutability_(e_mutable)
          {}
 
          explicit control_block(st_data* data)
-         : ref_count(1),
-           data_(data)
+         : ref_count(1)
+         , data_(data)
+         , mutability_(e_mutable)
          {}
 
         ~control_block()
@@ -17612,21 +20522,29 @@ namespace exprtk
             }
          }
 
+         void set_mutability(const symtab_mutability_type mutability)
+         {
+            mutability_ = mutability;
+         }
+
          std::size_t ref_count;
          st_data* data_;
+         symtab_mutability_type mutability_;
       };
 
    public:
 
-      symbol_table()
+      explicit symbol_table(const symtab_mutability_type mutability = e_mutable)
       : control_block_(control_block::create())
       {
+         control_block_->set_mutability(mutability);
          clear();
       }
 
      ~symbol_table()
       {
-         control_block::destroy(control_block_,this);
+         exprtk::details::dump_ptr("~symbol_table", this);
+         control_block::destroy(control_block_, this);
       }
 
       symbol_table(const symbol_table<T>& st)
@@ -17653,6 +20571,11 @@ namespace exprtk
          return (this == &st) || (control_block_ == st.control_block_);
       }
 
+      inline symtab_mutability_type mutability() const
+      {
+         return valid() ? control_block_->mutability_ : e_unknown;
+      }
+
       inline void clear_variables(const bool delete_node = true)
       {
          local_data().variable_store.clear(delete_node);
@@ -17753,6 +20676,24 @@ namespace exprtk
          else
             return local_data().stringvar_store.get(string_name);
       }
+
+      inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const
+      {
+         static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0));
+         if (!valid())
+            return null_stringvar_base;
+         else if (!valid_symbol(string_name))
+            return null_stringvar_base;
+
+         stringvar_ptr stringvar = local_data().stringvar_store.get(string_name);
+
+         if (0 == stringvar)
+         {
+            return null_stringvar_base;
+         }
+
+         return stringvar_base<T>(string_name,stringvar);
+      }
       #endif
 
       inline function_ptr get_function(const std::string& function_name) const
@@ -18072,6 +21013,34 @@ namespace exprtk
          return false;
       }
 
+      #define exprtk_define_reserved_function(NN)                                                    \
+      inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \
+      {                                                                                              \
+         if (!valid())                                                                               \
+         { return false; }                                                                           \
+         if (!valid_symbol(function_name,false))                                                     \
+         { return false; }                                                                           \
+         if (symbol_exists(function_name,false))                                                     \
+         { return false; }                                                                           \
+                                                                                                     \
+         exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                                   \
+                                                                                                     \
+         local_data().free_function_list_.push_back(ifunc);                                          \
+                                                                                                     \
+         return add_reserved_function(function_name,(*local_data().free_function_list_.back()));     \
+      }                                                                                              \
+
+      exprtk_define_reserved_function(00) exprtk_define_reserved_function(01)
+      exprtk_define_reserved_function(02) exprtk_define_reserved_function(03)
+      exprtk_define_reserved_function(04) exprtk_define_reserved_function(05)
+      exprtk_define_reserved_function(06) exprtk_define_reserved_function(07)
+      exprtk_define_reserved_function(08) exprtk_define_reserved_function(09)
+      exprtk_define_reserved_function(10) exprtk_define_reserved_function(11)
+      exprtk_define_reserved_function(12) exprtk_define_reserved_function(13)
+      exprtk_define_reserved_function(14) exprtk_define_reserved_function(15)
+
+      #undef exprtk_define_reserved_function
+
       template <std::size_t N>
       inline bool add_vector(const std::string& vector_name, T (&v)[N])
       {
@@ -18246,12 +21215,48 @@ namespace exprtk
 
       template <typename Allocator,
                 template <typename, typename> class Sequence>
-      inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
+      inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const
       {
          if (!valid())
             return 0;
          else
-            return local_data().vector_store.get_list(vlist);
+            return local_data().vector_store.get_list(vec_list);
+      }
+
+      template <typename Allocator,
+                template <typename, typename> class Sequence>
+      inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const
+      {
+         if (!valid())
+            return 0;
+
+         std::vector<std::string> function_names;
+         std::size_t count = 0;
+
+         count += local_data().function_store         .get_list(function_names);
+         count += local_data().vararg_function_store  .get_list(function_names);
+         count += local_data().generic_function_store .get_list(function_names);
+         count += local_data().string_function_store  .get_list(function_names);
+         count += local_data().overload_function_store.get_list(function_names);
+
+         std::set<std::string> function_set;
+
+         for (std::size_t i = 0; i < function_names.size(); ++i)
+         {
+            function_set.insert(function_names[i]);
+         }
+
+         std::copy(function_set.begin(), function_set.end(),
+                   std::back_inserter(function_list));
+
+         return count;
+      }
+
+      inline std::vector<std::string> get_function_list() const
+      {
+         std::vector<std::string> result;
+         get_function_list(result);
+         return result;
       }
 
       inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
@@ -18442,6 +21447,38 @@ namespace exprtk
          }
       }
 
+      inline void load_variables_from(const symbol_table<T>& st)
+      {
+         std::vector<std::string> name_list;
+
+         st.local_data().variable_store.get_list(name_list);
+
+         if (!name_list.empty())
+         {
+            for (std::size_t i = 0; i < name_list.size(); ++i)
+            {
+               T& variable = st.get_variable(name_list[i])->ref();
+               add_variable(name_list[i], variable);
+            }
+         }
+      }
+
+      inline void load_vectors_from(const symbol_table<T>& st)
+      {
+         std::vector<std::string> name_list;
+
+         st.local_data().vector_store.get_list(name_list);
+
+         if (!name_list.empty())
+         {
+            for (std::size_t i = 0; i < name_list.size(); ++i)
+            {
+               vector_holder_t& vecholder = *st.get_vector(name_list[i]);
+               add_vector(name_list[i], vecholder.data(), vecholder.size());
+            }
+         }
+      }
+
    private:
 
       inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
@@ -18511,7 +21548,7 @@ namespace exprtk
       control_block* control_block_;
 
       friend class parser<T>;
-   };
+   }; // class symbol_table
 
    template <typename T>
    class function_compositor;
@@ -18522,8 +21559,8 @@ namespace exprtk
    private:
 
       typedef details::expression_node<T>*  expression_ptr;
-      typedef details::vector_holder<T>* vector_holder_ptr;
-      typedef std::vector<symbol_table<T> >  symtab_list_t;
+      typedef details::vector_holder<T>*    vector_holder_ptr;
+      typedef std::vector<symbol_table<T> > symtab_list_t;
 
       struct control_block
       {
@@ -18537,18 +21574,33 @@ namespace exprtk
             e_string
          };
 
+         static std::string to_str(data_type dt)
+         {
+            switch(dt)
+            {
+               case e_unknown   : return "e_unknown  ";
+               case e_expr      : return "e_expr"     ;
+               case e_vecholder : return "e_vecholder";
+               case e_data      : return "e_data"     ;
+               case e_vecdata   : return "e_vecdata"  ;
+               case e_string    : return "e_string"   ;
+            }
+
+            return "";
+         }
+
          struct data_pack
          {
             data_pack()
-            : pointer(0),
-              type(e_unknown),
-              size(0)
+            : pointer(0)
+            , type(e_unknown)
+            , size(0)
             {}
 
             data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
-            : pointer(ptr),
-              type(dt),
-              size(sz)
+            : pointer(ptr)
+            , type(dt)
+            , size(sz)
             {}
 
             void*       pointer;
@@ -18558,21 +21610,22 @@ namespace exprtk
 
          typedef std::vector<data_pack> local_data_list_t;
          typedef results_context<T>     results_context_t;
+         typedef control_block*         cntrl_blck_ptr_t;
 
          control_block()
-         : ref_count(0),
-           expr     (0),
-           results  (0),
-           retinv_null(false),
-           return_invoked(&retinv_null)
+         : ref_count(0)
+         , expr     (0)
+         , results  (0)
+         , retinv_null(false)
+         , return_invoked(&retinv_null)
          {}
 
          explicit control_block(expression_ptr e)
-         : ref_count(1),
-           expr     (e),
-           results  (0),
-           retinv_null(false),
-           return_invoked(&retinv_null)
+         : ref_count(1)
+         , expr     (e)
+         , results  (0)
+         , retinv_null(false)
+         , return_invoked(&retinv_null)
          {}
 
         ~control_block()
@@ -18614,12 +21667,12 @@ namespace exprtk
             }
          }
 
-         static inline control_block* create(expression_ptr e)
+         static inline cntrl_blck_ptr_t create(expression_ptr e)
          {
             return new control_block(e);
          }
 
-         static inline void destroy(control_block*& cntrl_blck)
+         static inline void destroy(cntrl_blck_ptr_t& cntrl_blck)
          {
             if (cntrl_blck)
             {
@@ -18654,8 +21707,8 @@ namespace exprtk
       }
 
       expression(const expression<T>& e)
-      : control_block_    (e.control_block_    ),
-        symbol_table_list_(e.symbol_table_list_)
+      : control_block_    (e.control_block_    )
+      , symbol_table_list_(e.symbol_table_list_)
       {
          control_block_->ref_count++;
       }
@@ -18707,6 +21760,7 @@ namespace exprtk
 
       inline expression<T>& release()
       {
+         exprtk::details::dump_ptr("expression::release", this);
          control_block::destroy(control_block_);
 
          return (*this);
@@ -18740,9 +21794,18 @@ namespace exprtk
          return details::is_true(value());
       }
 
-      inline void register_symbol_table(symbol_table<T>& st)
+      inline bool register_symbol_table(symbol_table<T>& st)
       {
+         for (std::size_t i = 0; i < symbol_table_list_.size(); ++i)
+         {
+            if (st == symbol_table_list_[i])
+            {
+               return false;
+            }
+         }
+
          symbol_table_list_.push_back(st);
+         return true;
       }
 
       inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
@@ -18755,6 +21818,11 @@ namespace exprtk
          return symbol_table_list_[index];
       }
 
+      std::size_t num_symbol_tables() const
+      {
+         return symbol_table_list_.size();
+      }
+
       typedef results_context<T> results_context_t;
 
       inline const results_context_t& results() const
@@ -18884,70 +21952,182 @@ namespace exprtk
       friend class parser<T>;
       friend class expression_helper<T>;
       friend class function_compositor<T>;
-   };
+      template <typename TT>
+      friend bool is_valid(const expression<TT>& expr);
+   }; // class expression
 
    template <typename T>
    class expression_helper
    {
    public:
 
-      static inline bool is_constant(const expression<T>& expr)
+      enum node_types
+      {
+         e_literal,
+         e_variable,
+         e_string,
+         e_unary,
+         e_binary,
+         e_function,
+         e_vararg,
+         e_null,
+         e_assert,
+         e_sf3ext,
+         e_sf4ext
+      };
+
+      static inline bool is_literal(const expression<T>& expr)
       {
-         return details::is_constant_node(expr.control_block_->expr);
+         return expr.control_block_ && details::is_literal_node(expr.control_block_->expr);
       }
 
       static inline bool is_variable(const expression<T>& expr)
       {
-         return details::is_variable_node(expr.control_block_->expr);
+         return expr.control_block_ && details::is_variable_node(expr.control_block_->expr);
+      }
+
+      static inline bool is_string(const expression<T>& expr)
+      {
+         return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr);
       }
 
       static inline bool is_unary(const expression<T>& expr)
       {
-         return details::is_unary_node(expr.control_block_->expr);
+         return expr.control_block_ && details::is_unary_node(expr.control_block_->expr);
       }
 
       static inline bool is_binary(const expression<T>& expr)
       {
-         return details::is_binary_node(expr.control_block_->expr);
+         return expr.control_block_ && details::is_binary_node(expr.control_block_->expr);
       }
 
       static inline bool is_function(const expression<T>& expr)
       {
-         return details::is_function(expr.control_block_->expr);
+         return expr.control_block_ && details::is_function(expr.control_block_->expr);
+      }
+
+      static inline bool is_vararg(const expression<T>& expr)
+      {
+         return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr);
       }
 
       static inline bool is_null(const expression<T>& expr)
       {
-         return details::is_null_node(expr.control_block_->expr);
+         return expr.control_block_ && details::is_null_node(expr.control_block_->expr);
+      }
+
+      static inline bool is_assert(const expression<T>& expr)
+      {
+         return expr.control_block_ && details::is_assert_node(expr.control_block_->expr);
+      }
+
+      static inline bool is_sf3ext(const expression<T>& expr)
+      {
+         return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr);
+      }
+
+      static inline bool is_sf4ext(const expression<T>& expr)
+      {
+         return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr);
+      }
+
+      static inline bool is_type(const expression<T>& expr, const node_types node_type)
+      {
+         if (0 == expr.control_block_)
+         {
+            return false;
+         }
+
+         switch (node_type)
+         {
+            case e_literal  : return is_literal_node(expr);
+            case e_variable : return is_variable    (expr);
+            case e_string   : return is_string      (expr);
+            case e_unary    : return is_unary       (expr);
+            case e_binary   : return is_binary      (expr);
+            case e_function : return is_function    (expr);
+            case e_null     : return is_null        (expr);
+            case e_assert   : return is_assert      (expr);
+            case e_sf3ext   : return is_sf3ext      (expr);
+            case e_sf4ext   : return is_sf4ext      (expr);
+         };
+
+         return false;
+      }
+
+      static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq)
+      {
+         if ((0 == expr.control_block_) || !is_vararg(expr))
+         {
+            return false;
+         }
+
+         typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t;
+
+         mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr);
+
+         if (
+              (0 == vnode) ||
+              type_seq.empty() ||
+              (vnode->size() < type_seq.size())
+            )
+         {
+            return false;
+         }
+
+         for (std::size_t i = 0; i < type_seq.size(); ++i)
+         {
+            assert((*vnode)[i]);
+
+            switch(type_seq[i])
+            {
+               case e_literal  : { if (details::is_literal_node         ((*vnode)[i])) continue; } break;
+               case e_variable : { if (details::is_variable_node        ((*vnode)[i])) continue; } break;
+               case e_string   : { if (details::is_generally_string_node((*vnode)[i])) continue; } break;
+               case e_unary    : { if (details::is_unary_node           ((*vnode)[i])) continue; } break;
+               case e_binary   : { if (details::is_binary_node          ((*vnode)[i])) continue; } break;
+               case e_function : { if (details::is_function             ((*vnode)[i])) continue; } break;
+               case e_null     : { if (details::is_null_node            ((*vnode)[i])) continue; } break;
+               case e_assert   : { if (details::is_assert_node          ((*vnode)[i])) continue; } break;
+               case e_sf3ext   : { if (details::is_sf3ext_node          ((*vnode)[i])) continue; } break;
+               case e_sf4ext   : { if (details::is_sf4ext_node          ((*vnode)[i])) continue; } break;
+               case e_vararg   : break;
+            }
+
+            return false;
+         }
+
+         return true;
       }
    };
 
    template <typename T>
    inline bool is_valid(const expression<T>& expr)
    {
-      return !expression_helper<T>::is_null(expr);
+      return expr.control_block_ && !expression_helper<T>::is_null(expr);
    }
 
    namespace parser_error
    {
       enum error_mode
       {
-         e_unknown = 0,
-         e_syntax  = 1,
-         e_token   = 2,
-         e_numeric = 4,
-         e_symtab  = 5,
-         e_lexer   = 6,
-         e_helper  = 7,
-         e_parser  = 8
+         e_unknown   = 0,
+         e_syntax    = 1,
+         e_token     = 2,
+         e_numeric   = 4,
+         e_symtab    = 5,
+         e_lexer     = 6,
+         e_synthesis = 7,
+         e_helper    = 8,
+         e_parser    = 9
       };
 
       struct type
       {
          type()
-         : mode(parser_error::e_unknown),
-           line_no  (0),
-           column_no(0)
+         : mode(parser_error::e_unknown)
+         , line_no  (0)
+         , column_no(0)
          {}
 
          lexer::token token;
@@ -18968,7 +22148,7 @@ namespace exprtk
          t.token.type   = lexer::token::e_error;
          t.diagnostic   = diagnostic;
          t.src_location = src_location;
-         exprtk_debug(("%s\n",diagnostic .c_str()));
+         exprtk_debug(("%s\n", diagnostic .c_str()));
          return t;
       }
 
@@ -18978,11 +22158,11 @@ namespace exprtk
                              const std::string& src_location = "")
       {
          type t;
-         t.mode       = mode;
-         t.token      = tk;
-         t.diagnostic = diagnostic;
+         t.mode         = mode;
+         t.token        = tk;
+         t.diagnostic   = diagnostic;
          t.src_location = src_location;
-         exprtk_debug(("%s\n",diagnostic .c_str()));
+         exprtk_debug(("%s\n", diagnostic .c_str()));
          return t;
       }
 
@@ -19069,92 +22249,96 @@ namespace exprtk
 
       enum precedence_level
       {
-         e_level00,
-         e_level01,
-         e_level02,
-         e_level03,
-         e_level04,
-         e_level05,
-         e_level06,
-         e_level07,
-         e_level08,
-         e_level09,
-         e_level10,
-         e_level11,
-         e_level12,
-         e_level13,
-         e_level14
-      };
-
-      typedef const T&                                               cref_t;
-      typedef const T                                               const_t;
-      typedef ifunction                <T>                                F;
-      typedef ivararg_function         <T>                              VAF;
-      typedef igeneric_function        <T>                               GF;
-      typedef ifunction                <T>                      ifunction_t;
-      typedef ivararg_function         <T>               ivararg_function_t;
-      typedef igeneric_function        <T>              igeneric_function_t;
-      typedef details::expression_node <T>                expression_node_t;
-      typedef details::literal_node    <T>                   literal_node_t;
-      typedef details::unary_node      <T>                     unary_node_t;
-      typedef details::binary_node     <T>                    binary_node_t;
-      typedef details::trinary_node    <T>                   trinary_node_t;
-      typedef details::quaternary_node <T>                quaternary_node_t;
-      typedef details::conditional_node<T>               conditional_node_t;
-      typedef details::cons_conditional_node<T>     cons_conditional_node_t;
-      typedef details::while_loop_node <T>                while_loop_node_t;
-      typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
-      typedef details::for_loop_node   <T>                  for_loop_node_t;
+         e_level00, e_level01, e_level02, e_level03, e_level04,
+         e_level05, e_level06, e_level07, e_level08, e_level09,
+         e_level10, e_level11, e_level12, e_level13, e_level14
+      };
+
+      typedef const T&                                       cref_t;
+      typedef const T                                        const_t;
+      typedef ifunction<T>                                   F;
+      typedef ivararg_function<T>                            VAF;
+      typedef igeneric_function<T>                           GF;
+      typedef ifunction<T>                                   ifunction_t;
+      typedef ivararg_function<T>                            ivararg_function_t;
+      typedef igeneric_function<T>                           igeneric_function_t;
+      typedef details::expression_node<T>                    expression_node_t;
+      typedef details::literal_node<T>                       literal_node_t;
+      typedef details::unary_node<T>                         unary_node_t;
+      typedef details::binary_node<T>                        binary_node_t;
+      typedef details::trinary_node<T>                       trinary_node_t;
+      typedef details::quaternary_node<T>                    quaternary_node_t;
+      typedef details::conditional_node<T>                   conditional_node_t;
+      typedef details::cons_conditional_node<T>              cons_conditional_node_t;
+      typedef details::while_loop_node<T>                    while_loop_node_t;
+      typedef details::repeat_until_loop_node<T>             repeat_until_loop_node_t;
+      typedef details::for_loop_node<T>                      for_loop_node_t;
+      typedef details::while_loop_rtc_node<T>                while_loop_rtc_node_t;
+      typedef details::repeat_until_loop_rtc_node<T>         repeat_until_loop_rtc_node_t;
+      typedef details::for_loop_rtc_node<T>                  for_loop_rtc_node_t;
       #ifndef exprtk_disable_break_continue
-      typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
-      typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
-      typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
+      typedef details::while_loop_bc_node<T>                 while_loop_bc_node_t;
+      typedef details::repeat_until_loop_bc_node<T>          repeat_until_loop_bc_node_t;
+      typedef details::for_loop_bc_node<T>                   for_loop_bc_node_t;
+      typedef details::while_loop_bc_rtc_node<T>             while_loop_bc_rtc_node_t;
+      typedef details::repeat_until_loop_bc_rtc_node<T>      repeat_until_loop_bc_rtc_node_t;
+      typedef details::for_loop_bc_rtc_node<T>               for_loop_bc_rtc_node_t;
       #endif
-      typedef details::switch_node     <T>                    switch_node_t;
-      typedef details::variable_node   <T>                  variable_node_t;
-      typedef details::vector_elem_node<T>               vector_elem_node_t;
-      typedef details::rebasevector_elem_node<T>   rebasevector_elem_node_t;
-      typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
-      typedef details::vector_node     <T>                    vector_node_t;
-      typedef details::range_pack      <T>                          range_t;
+      typedef details::switch_node<T>                        switch_node_t;
+      typedef details::variable_node<T>                      variable_node_t;
+      typedef details::vector_elem_node<T>                   vector_elem_node_t;
+      typedef details::vector_celem_node<T>                  vector_celem_node_t;
+      typedef details::vector_elem_rtc_node<T>               vector_elem_rtc_node_t;
+      typedef details::vector_celem_rtc_node<T>              vector_celem_rtc_node_t;
+      typedef details::rebasevector_elem_node<T>             rebasevector_elem_node_t;
+      typedef details::rebasevector_celem_node<T>            rebasevector_celem_node_t;
+      typedef details::rebasevector_elem_rtc_node<T>         rebasevector_elem_rtc_node_t;
+      typedef details::rebasevector_celem_rtc_node<T>        rebasevector_celem_rtc_node_t;
+      typedef details::vector_node<T>                        vector_node_t;
+      typedef details::vector_size_node<T>                   vector_size_node_t;
+      typedef details::range_pack<T>                         range_t;
       #ifndef exprtk_disable_string_capabilities
-      typedef details::stringvar_node     <T>              stringvar_node_t;
-      typedef details::string_literal_node<T>         string_literal_node_t;
-      typedef details::string_range_node  <T>           string_range_node_t;
-      typedef details::const_string_range_node<T> const_string_range_node_t;
-      typedef details::generic_string_range_node<T> generic_string_range_node_t;
-      typedef details::string_concat_node <T>          string_concat_node_t;
-      typedef details::assignment_string_node<T>   assignment_string_node_t;
-      typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
-      typedef details::conditional_string_node<T>  conditional_string_node_t;
-      typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
+      typedef details::stringvar_node<T>                     stringvar_node_t;
+      typedef details::string_literal_node<T>                string_literal_node_t;
+      typedef details::string_range_node<T>                  string_range_node_t;
+      typedef details::const_string_range_node<T>            const_string_range_node_t;
+      typedef details::generic_string_range_node<T>          generic_string_range_node_t;
+      typedef details::string_concat_node<T>                 string_concat_node_t;
+      typedef details::assignment_string_node<T>             assignment_string_node_t;
+      typedef details::assignment_string_range_node<T>       assignment_string_range_node_t;
+      typedef details::conditional_string_node<T>            conditional_string_node_t;
+      typedef details::cons_conditional_str_node<T>          cons_conditional_str_node_t;
       #endif
-      typedef details::assignment_node<T>                 assignment_node_t;
-      typedef details::assignment_vec_elem_node       <T> assignment_vec_elem_node_t;
-      typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
-      typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
-      typedef details::assignment_vec_node     <T>    assignment_vec_node_t;
-      typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;
-      typedef details::scand_node<T>                           scand_node_t;
-      typedef details::scor_node<T>                             scor_node_t;
-      typedef lexer::token                                          token_t;
-      typedef expression_node_t*                        expression_node_ptr;
-      typedef expression<T>                                    expression_t;
+      typedef details::assignment_node<T>                    assignment_node_t;
+      typedef details::assignment_vec_elem_node<T>           assignment_vec_elem_node_t;
+      typedef details::assignment_vec_elem_rtc_node<T>       assignment_vec_elem_rtc_node_t;
+      typedef details::assignment_rebasevec_elem_node<T>     assignment_rebasevec_elem_node_t;
+      typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t;
+      typedef details::assignment_rebasevec_celem_node<T>    assignment_rebasevec_celem_node_t;
+      typedef details::assignment_vec_node<T>                assignment_vec_node_t;
+      typedef details::assignment_vecvec_node<T>             assignment_vecvec_node_t;
+      typedef details::conditional_vector_node<T>            conditional_vector_node_t;
+      typedef details::scand_node<T>                         scand_node_t;
+      typedef details::scor_node<T>                          scor_node_t;
+      typedef lexer::token                                   token_t;
+      typedef expression_node_t*                             expression_node_ptr;
+      typedef expression<T>                                  expression_t;
       typedef symbol_table<T>                                symbol_table_t;
-      typedef typename expression<T>::symtab_list_t     symbol_table_list_t;
-      typedef details::vector_holder<T>*                  vector_holder_ptr;
+      typedef typename expression<T>::symtab_list_t          symbol_table_list_t;
+      typedef details::vector_holder<T>                      vector_holder_t;
+      typedef vector_holder_t*                               vector_holder_ptr;
 
-      typedef typename details::functor_t<T>            functor_t;
+      typedef typename details::functor_t<T> functor_t;
       typedef typename functor_t::qfunc_t    quaternary_functor_t;
-      typedef typename functor_t::tfunc_t       trinary_functor_t;
-      typedef typename functor_t::bfunc_t        binary_functor_t;
-      typedef typename functor_t::ufunc_t         unary_functor_t;
+      typedef typename functor_t::tfunc_t    trinary_functor_t;
+      typedef typename functor_t::bfunc_t    binary_functor_t;
+      typedef typename functor_t::ufunc_t    unary_functor_t;
 
       typedef details::operator_type operator_t;
 
-      typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;
-      typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;
-      typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
+      typedef std::map<operator_t, unary_functor_t  > unary_op_map_t;
+      typedef std::map<operator_t, binary_functor_t > binary_op_map_t;
+      typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t;
 
       typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
       typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
@@ -19163,28 +22347,28 @@ namespace exprtk
       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
       typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
 
-      typedef details::T0oT1_define<T,  cref_t,  cref_t> vov_t;
-      typedef details::T0oT1_define<T, const_t,  cref_t> cov_t;
-      typedef details::T0oT1_define<T,  cref_t, const_t> voc_t;
-
-      typedef details::T0oT1oT2_define<T,  cref_t,  cref_t,  cref_t> vovov_t;
-      typedef details::T0oT1oT2_define<T,  cref_t,  cref_t, const_t> vovoc_t;
-      typedef details::T0oT1oT2_define<T,  cref_t, const_t,  cref_t> vocov_t;
-      typedef details::T0oT1oT2_define<T, const_t,  cref_t,  cref_t> covov_t;
-      typedef details::T0oT1oT2_define<T, const_t,  cref_t, const_t> covoc_t;
-      typedef details::T0oT1oT2_define<T, const_t, const_t,  cref_t> cocov_t;
-      typedef details::T0oT1oT2_define<T,  cref_t, const_t, const_t> vococ_t;
-
-      typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t,  cref_t> vovovov_t;
-      typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t, const_t> vovovoc_t;
-      typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t, const_t,  cref_t> vovocov_t;
-      typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t,  cref_t> vocovov_t;
-      typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t,  cref_t> covovov_t;
-
-      typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t, const_t,  cref_t> covocov_t;
-      typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t, const_t> vocovoc_t;
-      typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t, const_t> covovoc_t;
-      typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t, const_t,  cref_t> vococov_t;
+      typedef details::T0oT1_define<T, cref_t , cref_t > vov_t;
+      typedef details::T0oT1_define<T, const_t, cref_t > cov_t;
+      typedef details::T0oT1_define<T, cref_t , const_t> voc_t;
+
+      typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t;
+      typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t;
+      typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t;
+      typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t;
+      typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t;
+      typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t;
+      typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t;
+
+      typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t;
+      typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t;
+
+      typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t;
+      typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t;
 
       typedef results_context<T> results_context_t;
 
@@ -19195,6 +22379,7 @@ namespace exprtk
          enum element_type
          {
             e_none    ,
+            e_literal ,
             e_variable,
             e_vector  ,
             e_vecelem ,
@@ -19202,28 +22387,29 @@ namespace exprtk
          };
 
          typedef details::vector_holder<T> vector_holder_t;
-         typedef variable_node_t*        variable_node_ptr;
-         typedef vector_holder_t*        vector_holder_ptr;
-         typedef expression_node_t*    expression_node_ptr;
+         typedef literal_node_t*           literal_node_ptr;
+         typedef variable_node_t*          variable_node_ptr;
+         typedef vector_holder_t*          vector_holder_ptr;
+         typedef expression_node_t*        expression_node_ptr;
          #ifndef exprtk_disable_string_capabilities
-         typedef stringvar_node_t*      stringvar_node_ptr;
+         typedef stringvar_node_t*         stringvar_node_ptr;
          #endif
 
          scope_element()
-         : name("???"),
-           size (std::numeric_limits<std::size_t>::max()),
-           index(std::numeric_limits<std::size_t>::max()),
-           depth(std::numeric_limits<std::size_t>::max()),
-           ref_count(0),
-           ip_index (0),
-           type (e_none),
-           active(false),
-           data    (0),
-           var_node(0),
-           vec_node(0)
-           #ifndef exprtk_disable_string_capabilities
-           ,str_node(0)
-           #endif
+         : name("???")
+         , size (std::numeric_limits<std::size_t>::max())
+         , index(std::numeric_limits<std::size_t>::max())
+         , depth(std::numeric_limits<std::size_t>::max())
+         , ref_count(0)
+         , ip_index (0)
+         , type     (e_none)
+         , active   (false)
+         , data     (0)
+         , var_node (0)
+         , vec_node (0)
+         #ifndef exprtk_disable_string_capabilities
+         , str_node(0)
+         #endif
          {}
 
          bool operator < (const scope_element& se) const
@@ -19283,12 +22469,12 @@ namespace exprtk
       public:
 
          typedef expression_node_t* expression_node_ptr;
-         typedef variable_node_t*     variable_node_ptr;
-         typedef parser<T>                     parser_t;
+         typedef variable_node_t*   variable_node_ptr;
+         typedef parser<T>          parser_t;
 
          explicit scope_element_manager(parser<T>& p)
-         : parser_(p),
-           input_param_cnt_(0)
+         : parser_(p)
+         , input_param_cnt_(0)
          {}
 
          inline std::size_t size() const
@@ -19401,6 +22587,10 @@ namespace exprtk
 
             switch (se.type)
             {
+               case scope_element::e_literal    : delete reinterpret_cast<T*>(se.data);
+                                                  delete se.var_node;
+                                                  break;
+
                case scope_element::e_variable   : delete reinterpret_cast<T*>(se.data);
                                                   delete se.var_node;
                                                   break;
@@ -19465,9 +22655,29 @@ namespace exprtk
             return expression_node_ptr(0);
          }
 
+         inline std::string get_vector_name(const T* data)
+         {
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               scope_element& se = element_[i];
+
+               if (
+                    se.active   &&
+                    se.vec_node &&
+                    (se.vec_node->data() == data)
+                  )
+               {
+                  return se.name;
+               }
+            }
+
+            return "neo-vector";
+         }
+
       private:
 
-         scope_element_manager& operator=(const scope_element_manager&);
+         scope_element_manager(const scope_element_manager&) exprtk_delete;
+         scope_element_manager& operator=(const scope_element_manager&) exprtk_delete;
 
          parser_t& parser_;
          std::vector<scope_element> element_;
@@ -19507,11 +22717,136 @@ namespace exprtk
 
       private:
 
-         scope_handler& operator=(const scope_handler&);
+         scope_handler(const scope_handler&) exprtk_delete;
+         scope_handler& operator=(const scope_handler&) exprtk_delete;
 
          parser_t& parser_;
       };
 
+      template <typename T_>
+      struct halfopen_range_policy
+      {
+         static inline bool is_within(const T_& v, const T_& begin, const T_& end)
+         {
+            assert(begin <= end);
+            return (begin <= v) && (v < end);
+         }
+
+         static inline bool is_less(const T_& v, const T_& begin)
+         {
+            return (v < begin);
+         }
+
+         static inline bool is_greater(const T_& v, const T_& end)
+         {
+            return (end <= v);
+         }
+
+         static inline bool end_inclusive()
+         {
+            return false;
+         }
+      };
+
+      template <typename T_>
+      struct closed_range_policy
+      {
+         static inline bool is_within(const T_& v, const T_& begin, const T_& end)
+         {
+            assert(begin <= end);
+            return (begin <= v) && (v <= end);
+         }
+
+         static inline bool is_less(const T_& v, const T_& begin)
+         {
+            return (v < begin);
+         }
+
+         static inline bool is_greater(const T_& v, const T_& end)
+         {
+            return (end < v);
+         }
+
+         static inline bool end_inclusive()
+         {
+            return true;
+         }
+      };
+
+      template <typename IntervalPointType,
+                typename RangePolicy = halfopen_range_policy<IntervalPointType> >
+      class interval_container_t
+      {
+      public:
+
+         typedef IntervalPointType interval_point_t;
+         typedef std::pair<interval_point_t, interval_point_t> interval_t;
+         typedef std::map<interval_point_t, interval_t> interval_map_t;
+         typedef typename interval_map_t::const_iterator interval_map_citr_t;
+
+         std::size_t size() const
+         {
+            return interval_map_.size();
+         }
+
+         void reset()
+         {
+            interval_map_.clear();
+         }
+
+         bool in_interval(const interval_point_t point, interval_t& interval) const
+         {
+            interval_map_citr_t itr = RangePolicy::end_inclusive() ?
+                                      interval_map_.lower_bound(point):
+                                      interval_map_.upper_bound(point);
+
+            for (; itr != interval_map_.end(); ++itr)
+            {
+               const interval_point_t& begin = itr->second.first;
+               const interval_point_t& end   = itr->second.second;
+
+               if (RangePolicy::is_within(point, begin, end))
+               {
+                  interval = interval_t(begin,end);
+                  return true;
+               }
+               else if (RangePolicy::is_greater(point, end))
+               {
+                  break;
+               }
+            }
+
+            return false;
+         }
+
+         bool in_interval(const interval_point_t point) const
+         {
+            interval_t interval;
+            return in_interval(point,interval);
+         }
+
+         bool add_interval(const interval_point_t begin, const interval_point_t end)
+         {
+            if ((end <= begin) || in_interval(begin) || in_interval(end))
+            {
+               return false;
+            }
+
+            interval_map_[end] = std::make_pair(begin, end);
+
+            return true;
+         }
+
+         bool add_interval(const interval_t interval)
+         {
+            return add_interval(interval.first, interval.second);
+         }
+
+      private:
+
+         interval_map_t interval_map_;
+      };
+
       class stack_limit_handler
       {
       public:
@@ -19519,22 +22854,23 @@ namespace exprtk
          typedef parser<T> parser_t;
 
          explicit stack_limit_handler(parser<T>& p)
-            : parser_(p),
-              limit_exceeded_(false)
+         : parser_(p)
+         , limit_exceeded_(false)
          {
             if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
             {
                limit_exceeded_ = true;
-               parser_.set_error(
-                  make_error(parser_error::e_parser,
-                     "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
-                     " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
-                     exprtk_error_location));
+               parser_.set_error(make_error(
+                  parser_error::e_parser,
+                  "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
+                  " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
+                  exprtk_error_location));
             }
          }
 
         ~stack_limit_handler()
          {
+            assert(parser_.state_.stack_depth > 0);
             parser_.state_.stack_depth--;
          }
 
@@ -19545,7 +22881,8 @@ namespace exprtk
 
       private:
 
-         stack_limit_handler& operator=(const stack_limit_handler&);
+         stack_limit_handler(const stack_limit_handler&) exprtk_delete;
+         stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete;
 
          parser_t& parser_;
          bool limit_exceeded_;
@@ -19555,16 +22892,51 @@ namespace exprtk
       {
          symbol_table_list_t symtab_list_;
 
-         typedef typename symbol_table_t::local_data_t   local_data_t;
-         typedef typename symbol_table_t::variable_ptr   variable_ptr;
-         typedef typename symbol_table_t::function_ptr   function_ptr;
+         typedef typename symbol_table_t::local_data_t local_data_t;
+         typedef typename symbol_table_t::variable_ptr variable_ptr;
+         typedef typename symbol_table_t::function_ptr function_ptr;
          #ifndef exprtk_disable_string_capabilities
          typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
          #endif
-         typedef typename symbol_table_t::vector_holder_ptr       vector_holder_ptr;
-         typedef typename symbol_table_t::vararg_function_ptr   vararg_function_ptr;
+         typedef typename symbol_table_t::vector_holder_ptr    vector_holder_ptr;
+         typedef typename symbol_table_t::vararg_function_ptr  vararg_function_ptr;
          typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
 
+         struct variable_context
+         {
+            variable_context()
+            : symbol_table(0)
+            , variable(0)
+            {}
+
+            const symbol_table_t* symbol_table;
+            variable_ptr variable;
+         };
+
+         struct vector_context
+         {
+            vector_context()
+            : symbol_table(0)
+            , vector_holder(0)
+            {}
+
+            const symbol_table_t* symbol_table;
+            vector_holder_ptr vector_holder;
+         };
+
+         #ifndef exprtk_disable_string_capabilities
+         struct string_context
+         {
+            string_context()
+            : symbol_table(0)
+            , str_var(0)
+            {}
+
+            const symbol_table_t* symbol_table;
+            stringvar_ptr str_var;
+         };
+         #endif
+
          inline bool empty() const
          {
             return symtab_list_.empty();
@@ -19605,6 +22977,32 @@ namespace exprtk
                return false;
          }
 
+         inline variable_context get_variable_context(const std::string& variable_name) const
+         {
+            variable_context result;
+
+            if (valid_symbol(variable_name))
+            {
+               for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+               {
+                  if (!symtab_list_[i].valid())
+                  {
+                     continue;
+                  }
+
+                  result.variable = local_data(i)
+                                       .variable_store.get(variable_name);
+                  if (result.variable)
+                  {
+                     result.symbol_table = &symtab_list_[i];
+                     break;
+                  }
+               }
+            }
+
+            return result;
+         }
+
          inline variable_ptr get_variable(const std::string& variable_name) const
          {
             if (!valid_symbol(variable_name))
@@ -19645,6 +23043,32 @@ namespace exprtk
          }
 
          #ifndef exprtk_disable_string_capabilities
+         inline string_context get_string_context(const std::string& string_name) const
+         {
+            string_context result;
+
+            if (!valid_symbol(string_name))
+               return result;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+               {
+                  continue;
+               }
+
+               result.str_var = local_data(i).stringvar_store.get(string_name);
+
+               if (result.str_var)
+               {
+                  result.symbol_table = &symtab_list_[i];
+                  break;
+               }
+            }
+
+            return result;
+         }
+
          inline stringvar_ptr get_stringvar(const std::string& string_name) const
          {
             if (!valid_symbol(string_name))
@@ -19772,6 +23196,31 @@ namespace exprtk
             return result;
          }
 
+         inline vector_context get_vector_context(const std::string& vector_name) const
+         {
+            vector_context result;
+            if (!valid_symbol(vector_name))
+               return result;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+               {
+                  continue;
+               }
+
+               result.vector_holder = local_data(i).vector_store.get(vector_name);
+
+               if (result.vector_holder)
+               {
+                  result.symbol_table = &symtab_list_[i];
+                  break;
+               }
+            }
+
+            return result;
+         }
+
          inline vector_holder_ptr get_vector(const std::string& vector_name) const
          {
             if (!valid_symbol(vector_name))
@@ -19782,12 +23231,16 @@ namespace exprtk
             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
             {
                if (!symtab_list_[i].valid())
+               {
                   continue;
-               else
-                  result =
-                     local_data(i).vector_store.get(vector_name);
+               }
 
-               if (result) break;
+               result = local_data(i).vector_store.get(vector_name);
+
+               if (result)
+               {
+                  break;
+               }
             }
 
             return result;
@@ -19801,9 +23254,14 @@ namespace exprtk
             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
             {
                if (!symtab_list_[i].valid())
+               {
                   continue;
-               else if (local_data(i).variable_store.is_constant(symbol_name))
+               }
+
+               if (local_data(i).variable_store.is_constant(symbol_name))
+               {
                   return true;
+               }
             }
 
             return false;
@@ -19821,7 +23279,7 @@ namespace exprtk
                   continue;
                else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
                   continue;
-               else if ( local_data(i).stringvar_store.is_constant(symbol_name))
+               else if (local_data(i).stringvar_store.is_constant(symbol_name))
                   return true;
             }
 
@@ -19834,9 +23292,14 @@ namespace exprtk
             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
             {
                if (!symtab_list_[i].valid())
+               {
                   continue;
-               else if (symtab_list_[i].symbol_exists(symbol))
+               }
+
+               if (symtab_list_[i].symbol_exists(symbol))
+               {
                   return true;
+               }
             }
 
             return false;
@@ -19996,6 +23459,7 @@ namespace exprtk
          {
             parsing_return_stmt     = false;
             parsing_break_stmt      = false;
+            parsing_assert_stmt     = false;
             return_stmt_present     = false;
             side_effect_present     = false;
             scope_depth             = 0;
@@ -20013,12 +23477,13 @@ namespace exprtk
             {
                side_effect_present = true;
 
-               exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
+               exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str()));
             }
          }
 
          bool parsing_return_stmt;
          bool parsing_break_stmt;
+         bool parsing_assert_stmt;
          bool return_stmt_present;
          bool side_effect_present;
          bool type_check_enabled;
@@ -20106,12 +23571,12 @@ namespace exprtk
          typedef std::vector<symbol_t> symbol_list_t;
 
          dependent_entity_collector(const std::size_t options = e_ct_none)
-         : options_(options),
-           collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),
-           collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),
-           collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
-           return_present_   (false),
-           final_stmt_return_(false)
+         : options_(options)
+         , collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  )
+         , collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  )
+         , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments)
+         , return_present_   (false)
+         , final_stmt_return_(false)
          {}
 
          template <typename Allocator,
@@ -20128,11 +23593,14 @@ namespace exprtk
                details::case_normalise(symbol_name_list_[i].first);
             }
 
-            std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
+            std::sort(symbol_name_list_.begin(), symbol_name_list_.end());
 
-            std::unique_copy(symbol_name_list_.begin(),
-                             symbol_name_list_.end  (),
-                             std::back_inserter(symbols_list));
+            std::unique_copy
+            (
+               symbol_name_list_.begin(),
+               symbol_name_list_.end  (),
+               std::back_inserter(symbols_list)
+            );
 
             return symbols_list.size();
          }
@@ -20153,9 +23621,12 @@ namespace exprtk
 
             std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
 
-            std::unique_copy(assignment_name_list_.begin(),
-                             assignment_name_list_.end  (),
-                             std::back_inserter(assignment_list));
+            std::unique_copy
+            (
+               assignment_name_list_.begin(),
+               assignment_name_list_.end  (),
+               std::back_inserter(assignment_list)
+            );
 
             return assignment_list.size();
          }
@@ -20284,20 +23755,20 @@ namespace exprtk
          enum settings_base_funcs
          {
             e_bf_unknown = 0,
-            e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin   ,
-            e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh  ,
-            e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos    ,
-            e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal  ,
-            e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1  ,
-            e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp ,
-            e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p  ,
-            e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max    ,
-            e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul    ,
-            e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round  ,
-            e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin    ,
-            e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum    ,
-            e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc  ,
-            e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad,
+            e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin    ,
+            e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh   ,
+            e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos     ,
+            e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal   ,
+            e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1   ,
+            e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp  ,
+            e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p   ,
+            e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max     ,
+            e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul     ,
+            e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round   ,
+            e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin     ,
+            e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum     ,
+            e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc   ,
+            e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad ,
             e_bf_rad2deg   , e_bf_grad2deg
          };
 
@@ -20315,8 +23786,8 @@ namespace exprtk
          enum settings_logic_opr
          {
             e_logic_unknown = 0,
-            e_logic_and, e_logic_nand,  e_logic_nor,
-            e_logic_not, e_logic_or,    e_logic_xnor,
+            e_logic_and, e_logic_nand , e_logic_nor ,
+            e_logic_not, e_logic_or   , e_logic_xnor,
             e_logic_xor, e_logic_scand, e_logic_scor
          };
 
@@ -20337,22 +23808,24 @@ namespace exprtk
          enum settings_inequality_opr
          {
             e_ineq_unknown = 0,
-            e_ineq_lt,    e_ineq_lte, e_ineq_eq,
-            e_ineq_equal, e_ineq_ne,  e_ineq_nequal,
-            e_ineq_gte,   e_ineq_gt
+            e_ineq_lt   , e_ineq_lte, e_ineq_eq    ,
+            e_ineq_equal, e_ineq_ne , e_ineq_nequal,
+            e_ineq_gte  , e_ineq_gt
          };
 
-         static const std::size_t compile_all_opts = e_replacer          +
-                                                     e_joiner            +
-                                                     e_numeric_check     +
-                                                     e_bracket_check     +
-                                                     e_sequence_check    +
-                                                     e_commutative_check +
-                                                     e_strength_reduction;
+         static const std::size_t default_compile_all_opts =
+                                     e_replacer          +
+                                     e_joiner            +
+                                     e_numeric_check     +
+                                     e_bracket_check     +
+                                     e_sequence_check    +
+                                     e_commutative_check +
+                                     e_strength_reduction;
 
-         settings_store(const std::size_t compile_options = compile_all_opts)
-         : max_stack_depth_(400),
-           max_node_depth_(10000)
+         settings_store(const std::size_t compile_options = default_compile_all_opts)
+         : max_stack_depth_(400)
+         , max_node_depth_(10000)
+         , max_local_vector_size_(2000000000)
          {
            load_compile_options(compile_options);
          }
@@ -20399,12 +23872,24 @@ namespace exprtk
             return (*this);
          }
 
+         settings_store& enable_commutative_check()
+         {
+            enable_commutative_check_ = true;
+            return (*this);
+         }
+
+         settings_store& enable_strength_reduction()
+         {
+            enable_strength_reduction_ = true;
+            return (*this);
+         }
+
          settings_store& disable_all_base_functions()
          {
             std::copy(details::base_function_list,
                       details::base_function_list + details::base_function_list_size,
                       std::insert_iterator<disabled_entity_set_t>
-                        (disabled_func_set_, disabled_func_set_.begin()));
+                         (disabled_func_set_, disabled_func_set_.begin()));
             return (*this);
          }
 
@@ -20413,7 +23898,7 @@ namespace exprtk
             std::copy(details::cntrl_struct_list,
                       details::cntrl_struct_list + details::cntrl_struct_list_size,
                       std::insert_iterator<disabled_entity_set_t>
-                        (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
+                         (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
             return (*this);
          }
 
@@ -20431,7 +23916,7 @@ namespace exprtk
             std::copy(details::arithmetic_ops_list,
                       details::arithmetic_ops_list + details::arithmetic_ops_list_size,
                       std::insert_iterator<disabled_entity_set_t>
-                        (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
+                         (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
             return (*this);
          }
 
@@ -20440,7 +23925,7 @@ namespace exprtk
             std::copy(details::assignment_ops_list,
                       details::assignment_ops_list + details::assignment_ops_list_size,
                       std::insert_iterator<disabled_entity_set_t>
-                        (disabled_assignment_set_, disabled_assignment_set_.begin()));
+                         (disabled_assignment_set_, disabled_assignment_set_.begin()));
             return (*this);
          }
 
@@ -20449,7 +23934,7 @@ namespace exprtk
             std::copy(details::inequality_ops_list,
                       details::inequality_ops_list + details::inequality_ops_list_size,
                       std::insert_iterator<disabled_entity_set_t>
-                        (disabled_inequality_set_, disabled_inequality_set_.begin()));
+                         (disabled_inequality_set_, disabled_inequality_set_.begin()));
             return (*this);
          }
 
@@ -20459,6 +23944,18 @@ namespace exprtk
             return (*this);
          }
 
+         settings_store& disable_commutative_check()
+         {
+            enable_commutative_check_ = false;
+            return (*this);
+         }
+
+         settings_store& disable_strength_reduction()
+         {
+            enable_strength_reduction_ = false;
+            return (*this);
+         }
+
          bool replacer_enabled           () const { return enable_replacer_;           }
          bool commutative_check_enabled  () const { return enable_commutative_check_;  }
          bool joiner_enabled             () const { return enable_joiner_;             }
@@ -20584,7 +24081,7 @@ namespace exprtk
                                                            .find(inequality_opr_to_string(inequality));
          }
 
-         settings_store& disable_base_function(settings_base_funcs bf)
+         settings_store& disable_base_function(const settings_base_funcs bf)
          {
             if (
                  (e_bf_unknown != bf) &&
@@ -20597,7 +24094,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& disable_control_structure(settings_control_structs ctrl_struct)
+         settings_store& disable_control_structure(const settings_control_structs ctrl_struct)
          {
             if (
                  (e_ctrl_unknown != ctrl_struct) &&
@@ -20610,7 +24107,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& disable_logic_operation(settings_logic_opr logic)
+         settings_store& disable_logic_operation(const settings_logic_opr logic)
          {
             if (
                  (e_logic_unknown != logic) &&
@@ -20623,7 +24120,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
+         settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
          {
             if (
                  (e_arith_unknown != arithmetic) &&
@@ -20636,7 +24133,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& disable_assignment_operation(settings_assignment_opr assignment)
+         settings_store& disable_assignment_operation(const settings_assignment_opr assignment)
          {
             if (
                  (e_assign_unknown != assignment) &&
@@ -20649,7 +24146,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& disable_inequality_operation(settings_inequality_opr inequality)
+         settings_store& disable_inequality_operation(const settings_inequality_opr inequality)
          {
             if (
                  (e_ineq_unknown != inequality) &&
@@ -20662,7 +24159,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& enable_base_function(settings_base_funcs bf)
+         settings_store& enable_base_function(const settings_base_funcs bf)
          {
             if (
                  (e_bf_unknown != bf) &&
@@ -20680,7 +24177,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& enable_control_structure(settings_control_structs ctrl_struct)
+         settings_store& enable_control_structure(const settings_control_structs ctrl_struct)
          {
             if (
                  (e_ctrl_unknown != ctrl_struct) &&
@@ -20698,7 +24195,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& enable_logic_operation(settings_logic_opr logic)
+         settings_store& enable_logic_operation(const settings_logic_opr logic)
          {
             if (
                  (e_logic_unknown != logic) &&
@@ -20716,7 +24213,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
+         settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
          {
             if (
                  (e_arith_unknown != arithmetic) &&
@@ -20734,7 +24231,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& enable_assignment_operation(settings_assignment_opr assignment)
+         settings_store& enable_assignment_operation(const settings_assignment_opr assignment)
          {
             if (
                  (e_assign_unknown != assignment) &&
@@ -20752,7 +24249,7 @@ namespace exprtk
             return (*this);
          }
 
-         settings_store& enable_inequality_operation(settings_inequality_opr inequality)
+         settings_store& enable_inequality_operation(const settings_inequality_opr inequality)
          {
             if (
                  (e_ineq_unknown != inequality) &&
@@ -20770,9 +24267,9 @@ namespace exprtk
             return (*this);
          }
 
-         void set_max_stack_depth(const std::size_t mx_stack_depth)
+         void set_max_stack_depth(const std::size_t max_stack_depth)
          {
-            max_stack_depth_ = mx_stack_depth;
+            max_stack_depth_ = max_stack_depth;
          }
 
          void set_max_node_depth(const std::size_t max_node_depth)
@@ -20780,6 +24277,26 @@ namespace exprtk
             max_node_depth_ = max_node_depth;
          }
 
+         void set_max_local_vector_size(const std::size_t max_local_vector_size)
+         {
+            max_local_vector_size_ = max_local_vector_size;
+         }
+
+         std::size_t max_stack_depth() const
+         {
+            return max_stack_depth_;
+         }
+
+         std::size_t max_node_depth() const
+         {
+            return max_node_depth_;
+         }
+
+         std::size_t max_local_vector_size() const
+         {
+            return max_local_vector_size_;
+         }
+
       private:
 
          void load_compile_options(const std::size_t compile_options)
@@ -20809,7 +24326,7 @@ namespace exprtk
                case details::e_mulass : return "*=";
                case details::e_divass : return "/=";
                case details::e_modass : return "%=";
-               default                : return   "";
+               default                : return ""  ;
             }
          }
 
@@ -20822,7 +24339,8 @@ namespace exprtk
                case details::e_mul : return "*";
                case details::e_div : return "/";
                case details::e_mod : return "%";
-               default             : return  "";
+               case details::e_pow : return "^";
+               default             : return "" ;
             }
          }
 
@@ -20830,15 +24348,15 @@ namespace exprtk
          {
             switch (opr)
             {
-               case details::e_lt    : return  "<";
+               case details::e_lt    : return "<" ;
                case details::e_lte   : return "<=";
                case details::e_eq    : return "==";
-               case details::e_equal : return  "=";
+               case details::e_equal : return "=" ;
                case details::e_ne    : return "!=";
                case details::e_nequal: return "<>";
                case details::e_gte   : return ">=";
-               case details::e_gt    : return  ">";
-               default               : return   "";
+               case details::e_gt    : return ">" ;
+               default               : return ""  ;
             }
          }
 
@@ -20880,28 +24398,32 @@ namespace exprtk
 
          std::size_t max_stack_depth_;
          std::size_t max_node_depth_;
+         std::size_t max_local_vector_size_;
 
          friend class parser<T>;
       };
 
       typedef settings_store settings_t;
 
-      parser(const settings_t& settings = settings_t())
-      : settings_(settings),
-        resolve_unknown_symbol_(false),
-        results_context_(0),
-        unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
+      explicit parser(const settings_t& settings = settings_t())
+      : settings_(settings)
+      , resolve_unknown_symbol_(false)
+      , results_context_(0)
+      , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0))
         #ifdef _MSC_VER
         #pragma warning(push)
         #pragma warning (disable:4355)
         #endif
-        sem_(*this),
+      , sem_(*this)
         #ifdef _MSC_VER
         #pragma warning(pop)
         #endif
-        operator_joiner_2_(2),
-        operator_joiner_3_(3),
-        loop_runtime_check_(0)
+      , operator_joiner_2_(2)
+      , operator_joiner_3_(3)
+      , loop_runtime_check_(0)
+      , vector_access_runtime_check_(0)
+      , compilation_check_ptr_(0)
+      , assert_check_(0)
       {
          init_precompilation();
 
@@ -20914,11 +24436,11 @@ namespace exprtk
 
          expression_generator_.init_synthesize_map();
          expression_generator_.set_parser(*this);
-         expression_generator_.set_uom(unary_op_map_);
-         expression_generator_.set_bom(binary_op_map_);
+         expression_generator_.set_uom (unary_op_map_     );
+         expression_generator_.set_bom (binary_op_map_    );
          expression_generator_.set_ibom(inv_binary_op_map_);
-         expression_generator_.set_sf3m(sf3_map_);
-         expression_generator_.set_sf4m(sf4_map_);
+         expression_generator_.set_sf3m(sf3_map_          );
+         expression_generator_.set_sf4m(sf4_map_          );
          expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
       }
 
@@ -20927,14 +24449,14 @@ namespace exprtk
 
       inline void init_precompilation()
       {
-         if (settings_.collect_variables_enabled())
-            dec_.collect_variables() = true;
+         dec_.collect_variables() =
+            settings_.collect_variables_enabled();
 
-         if (settings_.collect_functions_enabled())
-            dec_.collect_functions() = true;
+         dec_.collect_functions() =
+            settings_.collect_functions_enabled();
 
-         if (settings_.collect_assignments_enabled())
-            dec_.collect_assignments() = true;
+         dec_.collect_assignments() =
+            settings_.collect_assignments_enabled();
 
          if (settings_.replacer_enabled())
          {
@@ -20991,11 +24513,15 @@ namespace exprtk
 
       inline bool compile(const std::string& expression_string, expression<T>& expr)
       {
-         state_          .reset();
-         error_list_     .clear();
-         brkcnt_list_    .clear();
-         synthesis_error_.clear();
-         sem_            .cleanup();
+         state_               .reset();
+         error_list_          .clear();
+         brkcnt_list_         .clear();
+         synthesis_error_     .clear();
+         immutable_memory_map_.reset();
+         immutable_symtok_map_.clear();
+         current_state_stack_ .clear();
+         assert_ids_          .clear();
+         sem_                 .cleanup();
 
          return_cleanup();
 
@@ -21003,10 +24529,10 @@ namespace exprtk
 
          if (expression_string.empty())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          "ERR001 - Empty expression!",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               "ERR001 - Empty expression!",
+               exprtk_error_location));
 
             return false;
          }
@@ -21019,19 +24545,31 @@ namespace exprtk
 
          if (lexer().empty())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          "ERR002 - Empty expression!",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               "ERR002 - Empty expression!",
+               exprtk_error_location));
 
             return false;
          }
 
+         if (halt_compilation_check())
+         {
+            exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n"));
+            return false;
+         }
+
          if (!run_assemblies())
          {
             return false;
          }
 
+         if (halt_compilation_check())
+         {
+            exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n"));
+            return false;
+         }
+
          symtab_store_.symtab_list_ = expr.get_symbol_table_list();
          dec_.clear();
 
@@ -21065,11 +24603,11 @@ namespace exprtk
          {
             if (error_list_.empty())
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR003 - Invalid expression encountered",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR003 - Invalid expression encountered",
+                  exprtk_error_location));
             }
 
             if ((0 != e) && branch_deletable(e))
@@ -21088,11 +24626,8 @@ namespace exprtk
       inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
       {
          expression_t expression;
-
          expression.register_symbol_table(symtab);
-
          compile(expression_string,expression);
-
          return expression;
       }
 
@@ -21124,11 +24659,11 @@ namespace exprtk
                   default                         : diagnostic += "Unknown compiler error";
                }
 
-               set_error(
-                  make_error(parser_error::e_lexer,
-                             lexer()[i],
-                             diagnostic + ": " + lexer()[i].value,
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_lexer,
+                  lexer()[i],
+                  diagnostic + ": " + lexer()[i].value,
+                  exprtk_error_location));
             }
          }
       }
@@ -21161,29 +24696,29 @@ namespace exprtk
                if (helper_assembly_.error_token_scanner)
                {
                   lexer::helper::bracket_checker*            bracket_checker_ptr     = 0;
-                  lexer::helper::numeric_checker*            numeric_checker_ptr     = 0;
+                  lexer::helper::numeric_checker<T>*         numeric_checker_ptr     = 0;
                   lexer::helper::sequence_validator*         sequence_validator_ptr  = 0;
                   lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
 
                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
                   {
-                     set_error(
-                        make_error(parser_error::e_token,
-                                   bracket_checker_ptr->error_token(),
-                                   "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_token,
+                        bracket_checker_ptr->error_token(),
+                        "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
+                        exprtk_error_location));
                   }
-                  else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
+                  else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner)))
                   {
                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
                      {
                         lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
 
-                        set_error(
-                           make_error(parser_error::e_token,
-                                      error_token,
-                                      "ERR006 - Invalid numeric token: '" + error_token.value + "'",
-                                      exprtk_error_location));
+                        set_error(make_error(
+                           parser_error::e_token,
+                           error_token,
+                           "ERR006 - Invalid numeric token: '" + error_token.value + "'",
+                           exprtk_error_location));
                      }
 
                      if (numeric_checker_ptr->error_count())
@@ -21197,13 +24732,13 @@ namespace exprtk
                      {
                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
 
-                        set_error(
-                           make_error(parser_error::e_token,
-                                      error_token.first,
-                                      "ERR007 - Invalid token sequence: '" +
-                                      error_token.first.value  + "' and '" +
-                                      error_token.second.value + "'",
-                                      exprtk_error_location));
+                        set_error(make_error(
+                           parser_error::e_token,
+                           error_token.first,
+                           "ERR007 - Invalid token sequence: '" +
+                           error_token.first.value  + "' and '" +
+                           error_token.second.value + "'",
+                           exprtk_error_location));
                      }
 
                      if (sequence_validator_ptr->error_count())
@@ -21217,13 +24752,13 @@ namespace exprtk
                      {
                         std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
 
-                        set_error(
-                           make_error(parser_error::e_token,
-                                      error_token.first,
-                                      "ERR008 - Invalid token sequence: '" +
-                                      error_token.first.value  + "' and '" +
-                                      error_token.second.value + "'",
-                                      exprtk_error_location));
+                        set_error(make_error(
+                           parser_error::e_token,
+                           error_token.first,
+                           "ERR008 - Invalid token sequence: '" +
+                           error_token.first.value  + "' and '" +
+                           error_token.second.value + "'",
+                           exprtk_error_location));
                      }
 
                      if (sequence_validator3_ptr->error_count())
@@ -21248,9 +24783,11 @@ namespace exprtk
       inline parser_error::type get_error(const std::size_t& index) const
       {
          if (index < error_list_.size())
+         {
             return error_list_[index];
-         else
-            throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
+         }
+
+         throw std::invalid_argument("parser::get_error() - Invalid error index specified");
       }
 
       inline std::string error() const
@@ -21319,11 +24856,41 @@ namespace exprtk
          loop_runtime_check_ = &lrtchk;
       }
 
+      inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk)
+      {
+         vector_access_runtime_check_ = &vartchk;
+      }
+
+      inline void register_compilation_timeout_check(compilation_check& compchk)
+      {
+         compilation_check_ptr_ = &compchk;
+      }
+
+      inline void register_assert_check(assert_check& assrt_chck)
+      {
+         assert_check_ = &assrt_chck;
+      }
+
       inline void clear_loop_runtime_check()
       {
          loop_runtime_check_ = loop_runtime_check_ptr(0);
       }
 
+      inline void clear_vector_access_runtime_check()
+      {
+         vector_access_runtime_check_ = vector_access_runtime_check_ptr(0);
+      }
+
+      inline void clear_compilation_timeout_check()
+      {
+         compilation_check_ptr_ = compilation_check_ptr(0);
+      }
+
+      inline void clear_assert_check()
+      {
+         assert_check_ = assert_check_ptr(0);
+      }
+
    private:
 
       inline bool valid_base_operation(const std::string& symbol) const
@@ -21413,7 +24980,7 @@ namespace exprtk
          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
 
          lexer::token begin_token;
-         lexer::token   end_token;
+         lexer::token end_token;
 
          for ( ; ; )
          {
@@ -21427,11 +24994,11 @@ namespace exprtk
             {
                if (error_list_.empty())
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR009 - Invalid expression encountered",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR009 - Invalid expression encountered",
+                     exprtk_error_location));
                }
 
                return error_node();
@@ -21457,15 +25024,31 @@ namespace exprtk
                exprtk_debug(("-------------------------------------------------\n"));
             }
 
-            if (lexer().finished())
-               break;
-            else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
+            if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
             {
                if (lexer().finished())
                   break;
                else
                   next_token();
             }
+            else if (
+                      !settings_.commutative_check_enabled() &&
+                      (
+                        current_token().type == token_t::e_symbol ||
+                        current_token().type == token_t::e_number ||
+                        current_token().type == token_t::e_string ||
+                        token_is_bracket(prsrhlpr_t::e_hold)
+                      )
+                    )
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR010 - Invalid syntax '" + current_token().value  + "' possible missing operator or context",
+                  exprtk_error_location));
+
+               return error_node();
+            }
          }
 
          if (
@@ -21483,13 +25066,17 @@ namespace exprtk
          return result;
       }
 
-      std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
+      std::string construct_subexpr(lexer::token& begin_token,
+                                    lexer::token& end_token,
+                                    const bool cleanup_whitespace = true)
       {
          std::string result = lexer().substr(begin_token.position,end_token.position);
-
-         for (std::size_t i = 0; i < result.size(); ++i)
+         if (cleanup_whitespace)
          {
-            if (details::is_whitespace(result[i])) result[i] = ' ';
+            for (std::size_t i = 0; i < result.size(); ++i)
+            {
+               if (details::is_whitespace(result[i])) result[i] = ' ';
+            }
          }
 
          return result;
@@ -21501,11 +25088,13 @@ namespace exprtk
       {
          inline void set(const precedence_level& l,
                          const precedence_level& r,
-                         const details::operator_type& o)
+                         const details::operator_type& o,
+                         const token_t tkn = token_t())
          {
-            left  = l;
-            right = r;
+            left      = l;
+            right     = r;
             operation = o;
+            token     = tkn;
          }
 
          inline void reset()
@@ -21518,10 +25107,58 @@ namespace exprtk
          precedence_level left;
          precedence_level right;
          details::operator_type operation;
+         token_t token;
       };
 
+      inline void push_current_state(const state_t current_state)
+      {
+         current_state_stack_.push_back(current_state);
+      }
+
+      inline void pop_current_state()
+      {
+         if (!current_state_stack_.empty())
+         {
+            current_state_stack_.pop_back();
+         }
+      }
+
+      inline state_t current_state() const
+      {
+         return (!current_state_stack_.empty()) ?
+                current_state_stack_.back()     :
+                state_t();
+      }
+
+      inline bool halt_compilation_check()
+      {
+         compilation_check::compilation_context context;
+
+         if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context))
+         {
+            const std::string error_message =
+               !context.error_message.empty() ? " Details: " + context.error_message : "";
+
+            set_error(make_error(
+               parser_error::e_parser,
+               token_t(),
+               "ERR011 - Internal compilation check failed." + error_message,
+               exprtk_error_location));
+
+            return true;
+         }
+
+         return false;
+      }
+
       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
       {
+         if (halt_compilation_check())
+         {
+            exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n"));
+            return error_node();
+         }
+
          stack_limit_handler slh(*this);
 
          if (!slh)
@@ -21536,6 +25173,11 @@ namespace exprtk
             return error_node();
          }
 
+         if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
+         {
+            return expression;
+         }
+
          bool break_loop = false;
 
          state_t current_state;
@@ -21546,110 +25188,111 @@ namespace exprtk
 
             switch (current_token().type)
             {
-               case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
-               case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
-               case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
-               case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
-               case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
-               case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
-               case token_t::e_swap   : current_state.set(e_level00,e_level00, details::e_swap  ); break;
-               case token_t::e_lt     : current_state.set(e_level05,e_level06, details::    e_lt); break;
-               case token_t::e_lte    : current_state.set(e_level05,e_level06, details::   e_lte); break;
-               case token_t::e_eq     : current_state.set(e_level05,e_level06, details::    e_eq); break;
-               case token_t::e_ne     : current_state.set(e_level05,e_level06, details::    e_ne); break;
-               case token_t::e_gte    : current_state.set(e_level05,e_level06, details::   e_gte); break;
-               case token_t::e_gt     : current_state.set(e_level05,e_level06, details::    e_gt); break;
-               case token_t::e_add    : current_state.set(e_level07,e_level08, details::   e_add); break;
-               case token_t::e_sub    : current_state.set(e_level07,e_level08, details::   e_sub); break;
-               case token_t::e_div    : current_state.set(e_level10,e_level11, details::   e_div); break;
-               case token_t::e_mul    : current_state.set(e_level10,e_level11, details::   e_mul); break;
-               case token_t::e_mod    : current_state.set(e_level10,e_level11, details::   e_mod); break;
-               case token_t::e_pow    : current_state.set(e_level12,e_level12, details::   e_pow); break;
-               default                : if (token_t::e_symbol == current_token().type)
-                                        {
-                                           static const std::string s_and   =   "and";
-                                           static const std::string s_nand  =  "nand";
-                                           static const std::string s_or    =    "or";
-                                           static const std::string s_nor   =   "nor";
-                                           static const std::string s_xor   =   "xor";
-                                           static const std::string s_xnor  =  "xnor";
-                                           static const std::string s_in    =    "in";
-                                           static const std::string s_like  =  "like";
-                                           static const std::string s_ilike = "ilike";
-                                           static const std::string s_and1  =     "&";
-                                           static const std::string s_or1   =     "|";
-                                           static const std::string s_not   =   "not";
-
-                                           if (details::imatch(current_token().value,s_and))
-                                           {
-                                              current_state.set(e_level03, e_level04, details::e_and);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_and1))
-                                           {
-                                              #ifndef exprtk_disable_sc_andor
-                                              current_state.set(e_level03, e_level04, details::e_scand);
-                                              #else
-                                              current_state.set(e_level03, e_level04, details::e_and);
-                                              #endif
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_nand))
-                                           {
-                                              current_state.set(e_level03, e_level04, details::e_nand);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_or))
-                                           {
-                                              current_state.set(e_level01, e_level02, details::e_or);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_or1))
-                                           {
-                                              #ifndef exprtk_disable_sc_andor
-                                              current_state.set(e_level01, e_level02, details::e_scor);
-                                              #else
-                                              current_state.set(e_level01, e_level02, details::e_or);
-                                              #endif
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_nor))
-                                           {
-                                              current_state.set(e_level01, e_level02, details::e_nor);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_xor))
-                                           {
-                                              current_state.set(e_level01, e_level02, details::e_xor);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_xnor))
-                                           {
-                                              current_state.set(e_level01, e_level02, details::e_xnor);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_in))
-                                           {
-                                              current_state.set(e_level04, e_level04, details::e_in);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_like))
-                                           {
-                                              current_state.set(e_level04, e_level04, details::e_like);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_ilike))
-                                           {
-                                              current_state.set(e_level04, e_level04, details::e_ilike);
-                                              break;
-                                           }
-                                           else if (details::imatch(current_token().value,s_not))
-                                           {
-                                              break;
-                                           }
-                                        }
-
-                                        break_loop = true;
+               case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break;
+               case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break;
+               case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break;
+               case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break;
+               case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break;
+               case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break;
+               case token_t::e_swap   : current_state.set(e_level00, e_level00, details::e_swap  , current_token()); break;
+               case token_t::e_lt     : current_state.set(e_level05, e_level06, details::e_lt    , current_token()); break;
+               case token_t::e_lte    : current_state.set(e_level05, e_level06, details::e_lte   , current_token()); break;
+               case token_t::e_eq     : current_state.set(e_level05, e_level06, details::e_eq    , current_token()); break;
+               case token_t::e_ne     : current_state.set(e_level05, e_level06, details::e_ne    , current_token()); break;
+               case token_t::e_gte    : current_state.set(e_level05, e_level06, details::e_gte   , current_token()); break;
+               case token_t::e_gt     : current_state.set(e_level05, e_level06, details::e_gt    , current_token()); break;
+               case token_t::e_add    : current_state.set(e_level07, e_level08, details::e_add   , current_token()); break;
+               case token_t::e_sub    : current_state.set(e_level07, e_level08, details::e_sub   , current_token()); break;
+               case token_t::e_div    : current_state.set(e_level10, e_level11, details::e_div   , current_token()); break;
+               case token_t::e_mul    : current_state.set(e_level10, e_level11, details::e_mul   , current_token()); break;
+               case token_t::e_mod    : current_state.set(e_level10, e_level11, details::e_mod   , current_token()); break;
+               case token_t::e_pow    : current_state.set(e_level12, e_level12, details::e_pow   , current_token()); break;
+               default                :
+                  if (token_t::e_symbol == current_token().type)
+                  {
+                     static const std::string s_and   = "and"  ;
+                     static const std::string s_nand  = "nand" ;
+                     static const std::string s_or    = "or"   ;
+                     static const std::string s_nor   = "nor"  ;
+                     static const std::string s_xor   = "xor"  ;
+                     static const std::string s_xnor  = "xnor" ;
+                     static const std::string s_in    = "in"   ;
+                     static const std::string s_like  = "like" ;
+                     static const std::string s_ilike = "ilike";
+                     static const std::string s_and1  = "&"    ;
+                     static const std::string s_or1   = "|"    ;
+                     static const std::string s_not   = "not"  ;
+
+                     if (details::imatch(current_token().value,s_and))
+                     {
+                        current_state.set(e_level03, e_level04, details::e_and, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_and1))
+                     {
+                        #ifndef exprtk_disable_sc_andor
+                        current_state.set(e_level03, e_level04, details::e_scand, current_token());
+                        #else
+                        current_state.set(e_level03, e_level04, details::e_and, current_token());
+                        #endif
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_nand))
+                     {
+                        current_state.set(e_level03, e_level04, details::e_nand, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_or))
+                     {
+                        current_state.set(e_level01, e_level02, details::e_or, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_or1))
+                     {
+                        #ifndef exprtk_disable_sc_andor
+                        current_state.set(e_level01, e_level02, details::e_scor, current_token());
+                        #else
+                        current_state.set(e_level01, e_level02, details::e_or, current_token());
+                        #endif
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_nor))
+                     {
+                        current_state.set(e_level01, e_level02, details::e_nor, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_xor))
+                     {
+                        current_state.set(e_level01, e_level02, details::e_xor, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_xnor))
+                     {
+                        current_state.set(e_level01, e_level02, details::e_xnor, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_in))
+                     {
+                        current_state.set(e_level04, e_level04, details::e_in, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_like))
+                     {
+                        current_state.set(e_level04, e_level04, details::e_like, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_ilike))
+                     {
+                        current_state.set(e_level04, e_level04, details::e_ilike, current_token());
+                        break;
+                     }
+                     else if (details::imatch(current_token().value,s_not))
+                     {
+                        break;
+                     }
+                  }
+
+                  break_loop = true;
             }
 
             if (break_loop)
@@ -21669,49 +25312,49 @@ namespace exprtk
 
             if (is_invalid_logic_operation(current_state.operation))
             {
-               free_node(node_allocator_,expression);
+               free_node(node_allocator_, expression);
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             prev_token,
-                             "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  prev_token,
+                  "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
             else if (is_invalid_arithmetic_operation(current_state.operation))
             {
-               free_node(node_allocator_,expression);
+               free_node(node_allocator_, expression);
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             prev_token,
-                             "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  prev_token,
+                  "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
             else if (is_invalid_inequality_operation(current_state.operation))
             {
-               free_node(node_allocator_,expression);
+               free_node(node_allocator_, expression);
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             prev_token,
-                             "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  prev_token,
+                  "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
             else if (is_invalid_assignment_operation(current_state.operation))
             {
-               free_node(node_allocator_,expression);
+               free_node(node_allocator_, expression);
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             prev_token,
-                             "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  prev_token,
+                  "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -21719,44 +25362,48 @@ namespace exprtk
             if (0 != (right_branch = parse_expression(current_state.right)))
             {
                if (
-                    details::is_return_node(  expression) ||
+                    details::is_return_node(expression  ) ||
                     details::is_return_node(right_branch)
                   )
                {
-                  free_node(node_allocator_,   expression);
+                  free_node(node_allocator_, expression  );
                   free_node(node_allocator_, right_branch);
 
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                prev_token,
-                                "ERR014 - Return statements cannot be part of sub-expressions",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     prev_token,
+                     "ERR016 - Return statements cannot be part of sub-expressions",
+                     exprtk_error_location));
 
                   return error_node();
                }
 
+               push_current_state(current_state);
+
                new_expression = expression_generator_
                                   (
                                     current_state.operation,
                                     expression,
                                     right_branch
                                   );
+
+               pop_current_state();
             }
 
             if (0 == new_expression)
             {
                if (error_list_.empty())
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                prev_token,
-                                !synthesis_error_.empty() ?
-                                synthesis_error_ :
-                                "ERR015 - General parsing error at token: '" + prev_token.value + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     prev_token,
+                     !synthesis_error_.empty() ?
+                     synthesis_error_ :
+                     "ERR017 - General parsing error at token: '" + prev_token.value + "'",
+                     exprtk_error_location));
                }
 
-               free_node(node_allocator_,   expression);
+               free_node(node_allocator_, expression  );
                free_node(node_allocator_, right_branch);
 
                return error_node();
@@ -21765,7 +25412,7 @@ namespace exprtk
             {
                if (
                     token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
-                    (precedence == e_level00)
+                    (e_level00 == precedence)
                   )
                {
                   expression = parse_ternary_conditional_statement(new_expression);
@@ -21779,14 +25426,35 @@ namespace exprtk
 
          if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                  current_token(),
-                  "ERR016 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
-                  " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
-                  exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
+               " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
+               exprtk_error_location));
 
-            free_node(node_allocator_,expression);
+            free_node(node_allocator_, expression);
+
+            return error_node();
+         }
+         else if (
+                   !settings_.commutative_check_enabled()          &&
+                   !details::is_logic_opr(current_token().value)   &&
+                   (current_state.operation == details::e_default) &&
+                   (
+                     current_token().type == token_t::e_symbol ||
+                     current_token().type == token_t::e_number ||
+                     current_token().type == token_t::e_string
+                   )
+                 )
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR019 - Invalid syntax '" + current_token().value  + "' possible missing operator or context",
+               exprtk_error_location));
+
+            free_node(node_allocator_, expression);
 
             return error_node();
          }
@@ -21804,7 +25472,7 @@ namespace exprtk
             {
                expression_node_ptr un_r = n->branch(0);
                n->release();
-               free_node(node_allocator_,node);
+               free_node(node_allocator_, node);
                node = un_r;
 
                return true;
@@ -21826,20 +25494,20 @@ namespace exprtk
                     (0 != (return_node = sem_         .get_variable(v)))
                   )
                {
-                  free_node(node_allocator_,node);
+                  free_node(node_allocator_, node);
                   node = return_node;
 
                   return true;
                }
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR017 - Failed to find variable node in symbol table",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR020 - Failed to find variable node in symbol table",
+                     exprtk_error_location));
 
-                  free_node(node_allocator_,node);
+                  free_node(node_allocator_, node);
 
                   return false;
                }
@@ -21857,9 +25525,9 @@ namespace exprtk
       struct scoped_expression_delete
       {
          scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
-         : delete_ptr(true),
-           parser_(pr),
-           expression_(expression)
+         : delete_ptr(true)
+         , parser_(pr)
+         , expression_(expression)
          {}
 
         ~scoped_expression_delete()
@@ -21876,7 +25544,8 @@ namespace exprtk
 
       private:
 
-         scoped_expression_delete& operator=(const scoped_expression_delete&);
+         scoped_expression_delete(const scoped_expression_delete&) exprtk_delete;
+         scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete;
       };
 
       template <typename Type, std::size_t N>
@@ -21885,15 +25554,15 @@ namespace exprtk
          typedef Type* ptr_t;
 
          scoped_delete(parser<T>& pr, ptr_t& p)
-         : delete_ptr(true),
-           parser_(pr),
-           p_(&p)
+         : delete_ptr(true)
+         , parser_(pr)
+         , p_(&p)
          {}
 
          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
-         : delete_ptr(true),
-           parser_(pr),
-           p_(&p[0])
+         : delete_ptr(true)
+         , parser_(pr)
+         , p_(&p[0])
          {}
 
         ~scoped_delete()
@@ -21913,7 +25582,8 @@ namespace exprtk
 
       private:
 
-         scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
+         scoped_delete(const scoped_delete<Type,N>&) exprtk_delete;
+         scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete;
       };
 
       template <typename Type>
@@ -21922,9 +25592,9 @@ namespace exprtk
          typedef Type* ptr_t;
 
          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
-         : delete_ptr(true),
-           parser_(pr),
-           deq_(deq)
+         : delete_ptr(true)
+         , parser_(pr)
+         , deq_(deq)
          {}
 
         ~scoped_deq_delete()
@@ -21933,6 +25603,7 @@ namespace exprtk
             {
                for (std::size_t i = 0; i < deq_.size(); ++i)
                {
+                  exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i])));
                   free_node(parser_.node_allocator_,deq_[i]);
                }
 
@@ -21946,7 +25617,8 @@ namespace exprtk
 
       private:
 
-         scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
+         scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete;
+         scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete;
       };
 
       template <typename Type>
@@ -21955,9 +25627,9 @@ namespace exprtk
          typedef Type* ptr_t;
 
          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
-         : delete_ptr(true),
-           parser_(pr),
-           vec_(vec)
+         : delete_ptr(true)
+         , parser_(pr)
+         , vec_(vec)
          {}
 
         ~scoped_vec_delete()
@@ -21966,6 +25638,7 @@ namespace exprtk
             {
                for (std::size_t i = 0; i < vec_.size(); ++i)
                {
+                  exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i])));
                   free_node(parser_.node_allocator_,vec_[i]);
                }
 
@@ -21973,13 +25646,19 @@ namespace exprtk
             }
          }
 
+         ptr_t operator[](const std::size_t index)
+         {
+            return vec_[index];
+         }
+
          bool delete_ptr;
          parser<T>& parser_;
          std::vector<ptr_t>& vec_;
 
       private:
 
-         scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
+         scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete;
+         scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete;
       };
 
       struct scoped_bool_negator
@@ -21997,8 +25676,8 @@ namespace exprtk
       struct scoped_bool_or_restorer
       {
          explicit scoped_bool_or_restorer(bool& bb)
-         : b(bb),
-           original_value_(bb)
+         : b(bb)
+         , original_value_(bb)
          {}
 
         ~scoped_bool_or_restorer()
@@ -22053,11 +25732,11 @@ namespace exprtk
             case 19 : func_node = parse_function_call<19>(function,function_name); break;
             case 20 : func_node = parse_function_call<20>(function,function_name); break;
             default : {
-                         set_error(
-                            make_error(parser_error::e_syntax,
-                                       current_token(),
-                                       "ERR018 - Invalid number of parameters for function: '" + function_name + "'",
-                                       exprtk_error_location));
+                         set_error(make_error(
+                           parser_error::e_syntax,
+                           current_token(),
+                           "ERR021 - Invalid number of parameters for function: '" + function_name + "'",
+                           exprtk_error_location));
 
                          return error_node();
                       }
@@ -22067,11 +25746,11 @@ namespace exprtk
             return func_node;
          else
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR019 - Failed to generate call to function: '" + function_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR022 - Failed to generate call to function: '" + function_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22086,11 +25765,11 @@ namespace exprtk
          #endif
          if (0 == NumberofParameters)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22109,11 +25788,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR021 - Expecting argument list for function: '" + function_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR024 - Expecting argument list for function: '" + function_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22124,11 +25803,11 @@ namespace exprtk
 
             if (0 == branch[i])
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -22136,11 +25815,11 @@ namespace exprtk
             {
                if (!token_is(token_t::e_comma))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR023 - Invalid number of arguments for function: '" + function_name + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR026 - Invalid number of arguments for function: '" + function_name + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -22149,11 +25828,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_rbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR027 - Invalid number of arguments for function: '" + function_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22178,13 +25857,13 @@ namespace exprtk
               !token_is(token_t::e_rbracket)
             )
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'",
+               exprtk_error_location));
 
-            free_node(node_allocator_,result);
+            free_node(node_allocator_, result);
 
             return error_node();
          }
@@ -22203,23 +25882,23 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR026 - Expected a '(' at start of function call to '" + function_name  +
-                          "', instead got: '" + current_token().value + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR029 - Expected a '(' at start of function call to '" + function_name  +
+               "', instead got: '" + current_token().value + "'",
+               exprtk_error_location));
 
             return 0;
          }
 
          if (token_is(token_t::e_rbracket, e_hold))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR027 - Expected at least one input parameter for function call '" + function_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR030 - Expected at least one input parameter for function call '" + function_name + "'",
+               exprtk_error_location));
 
             return 0;
          }
@@ -22241,11 +25920,11 @@ namespace exprtk
                continue;
             else
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
+                  exprtk_error_location));
 
                return 0;
             }
@@ -22253,11 +25932,11 @@ namespace exprtk
 
          if (sd.delete_ptr)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR029 - Invalid number of input parameters passed to function '" + function_name  + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR032 - Invalid number of input parameters passed to function '" + function_name  + "'",
+               exprtk_error_location));
 
             return 0;
          }
@@ -22276,11 +25955,11 @@ namespace exprtk
 
          if (0 == std::distance(itr_range.first,itr_range.second))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          diagnostic_token,
-                          "ERR030 - No entry found for base operation: " + operation_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               diagnostic_token,
+               "ERR033 - No entry found for base operation: " + operation_name,
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22323,11 +26002,11 @@ namespace exprtk
             free_node(node_allocator_, param_list[i]);
          }
 
-         set_error(
-            make_error(parser_error::e_syntax,
-                       diagnostic_token,
-                       "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'",
-                       exprtk_error_location));
+         set_error(make_error(
+            parser_error::e_syntax,
+            diagnostic_token,
+            "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'",
+            exprtk_error_location));
 
          return error_node();
       }
@@ -22343,75 +26022,118 @@ namespace exprtk
 
          if (!token_is(token_t::e_comma))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR032 - Expected ',' between if-statement condition and consequent",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR035 - Expected ',' between if-statement condition and consequent",
+               exprtk_error_location));
+
             result = false;
          }
          else if (0 == (consequent = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR033 - Failed to parse consequent for if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR036 - Failed to parse consequent for if-statement",
+               exprtk_error_location));
+
             result = false;
          }
          else if (!token_is(token_t::e_comma))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR034 - Expected ',' between if-statement consequent and alternative",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR037 - Expected ',' between if-statement consequent and alternative",
+               exprtk_error_location));
+
             result = false;
          }
          else if (0 == (alternative = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR035 - Failed to parse alternative for if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR038 - Failed to parse alternative for if-statement",
+               exprtk_error_location));
+
             result = false;
          }
          else if (!token_is(token_t::e_rbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR036 - Expected ')' at the end of if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR039 - Expected ')' at the end of if-statement",
+               exprtk_error_location));
+
             result = false;
          }
 
          #ifndef exprtk_disable_string_capabilities
          if (result)
          {
-            const bool consq_is_str = is_generally_string_node( consequent);
+            const bool consq_is_str = is_generally_string_node(consequent );
             const bool alter_is_str = is_generally_string_node(alternative);
 
             if (consq_is_str || alter_is_str)
             {
                if (consq_is_str && alter_is_str)
                {
-                  return expression_generator_
-                           .conditional_string(condition, consequent, alternative);
+                  expression_node_ptr result_node =
+                     expression_generator_
+                        .conditional_string(condition, consequent, alternative);
+
+                  if (result_node && result_node->valid())
+                  {
+                     return result_node;
+                  }
+
+                  set_error(make_error(
+                     parser_error::e_synthesis,
+                     current_token(),
+                     "ERR040 - Failed to synthesize node: conditional_string",
+                     exprtk_error_location));
+
+                  free_node(node_allocator_, result_node);
+                  return error_node();
                }
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR037 - Return types of ternary if-statement differ",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR041 - Return types of if-statement differ: string/non-string",
+                  exprtk_error_location));
 
                result = false;
             }
          }
          #endif
 
+         if (result)
+         {
+            const bool consq_is_vec = is_ivector_node(consequent );
+            const bool alter_is_vec = is_ivector_node(alternative);
+
+            if (consq_is_vec || alter_is_vec)
+            {
+               if (consq_is_vec && alter_is_vec)
+               {
+                  return expression_generator_
+                           .conditional_vector(condition, consequent, alternative);
+               }
+
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR042 - Return types of if-statement differ: vector/non-vector",
+                  exprtk_error_location));
+
+               result = false;
+            }
+         }
+
          if (!result)
          {
             free_node(node_allocator_, condition  );
@@ -22436,11 +26158,31 @@ namespace exprtk
          {
             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR038 - Failed to parse body of consequent for if-statement",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR043 - Failed to parse body of consequent for if-statement",
+                  exprtk_error_location));
+
+               result = false;
+            }
+            else if
+            (
+              !settings_.commutative_check_enabled()           &&
+              !token_is("else",prsrhlpr_t::e_hold)             &&
+              !token_is_loop(prsrhlpr_t::e_hold)               &&
+              !token_is_arithmetic_opr(prsrhlpr_t::e_hold)     &&
+              !token_is_right_bracket (prsrhlpr_t::e_hold)     &&
+              !token_is_ineq_opr      (prsrhlpr_t::e_hold)     &&
+              !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
+              !token_is(token_t::e_eof    ,prsrhlpr_t::e_hold)
+            )
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR044 - Expected ';' at the end of the consequent for if-statement (1)",
+                  exprtk_error_location));
 
                result = false;
             }
@@ -22457,24 +26199,24 @@ namespace exprtk
 
             if (0 != (consequent = parse_expression()))
             {
-               if (!token_is(token_t::e_eof))
+               if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR039 - Expected ';' at the end of the consequent for if-statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR045 - Expected ';' at the end of the consequent for if-statement (2)",
+                     exprtk_error_location));
 
                   result = false;
                }
             }
             else
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR040 - Failed to parse body of consequent for if-statement",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR046 - Failed to parse body of consequent for if-statement",
+                  exprtk_error_location));
 
                result = false;
             }
@@ -22482,19 +26224,27 @@ namespace exprtk
 
          if (result)
          {
-            if (details::imatch(current_token().value,"else"))
+            if (
+                 details::imatch(current_token().value,"else") ||
+                 (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else"))
+               )
             {
                next_token();
 
+               if (details::imatch(current_token().value,"else"))
+               {
+                  next_token();
+               }
+
                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
                {
                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR041 - Failed to parse body of the 'else' for if-statement",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR047 - Failed to parse body of the 'else' for if-statement",
+                        exprtk_error_location));
 
                      result = false;
                   }
@@ -22503,35 +26253,39 @@ namespace exprtk
                {
                   if (0 == (alternative = parse_conditional_statement()))
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR042 - Failed to parse body of if-else statement",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR048 - Failed to parse body of if-else statement",
+                        exprtk_error_location));
 
                      result = false;
                   }
                }
                else if (0 != (alternative = parse_expression()))
                {
-                  if (!token_is(token_t::e_eof))
+                  if (
+                       !token_is(token_t::e_ternary    , prsrhlpr_t::e_hold) &&
+                       !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
+                       !token_is(token_t::e_eof)
+                     )
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement",
+                        exprtk_error_location));
 
                      result = false;
                   }
                }
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR044 - Failed to parse body of the 'else' for if-statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR050 - Failed to parse body of the 'else' for if-statement",
+                     exprtk_error_location));
 
                   result = false;
                }
@@ -22541,7 +26295,7 @@ namespace exprtk
          #ifndef exprtk_disable_string_capabilities
          if (result)
          {
-            const bool consq_is_str = is_generally_string_node( consequent);
+            const bool consq_is_str = is_generally_string_node(consequent );
             const bool alter_is_str = is_generally_string_node(alternative);
 
             if (consq_is_str || alter_is_str)
@@ -22552,21 +26306,44 @@ namespace exprtk
                            .conditional_string(condition, consequent, alternative);
                }
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR045 - Return types of ternary if-statement differ",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR051 - Return types of if-statement differ: string/non-string",
+                  exprtk_error_location));
 
                result = false;
             }
          }
          #endif
 
+         if (result)
+         {
+            const bool consq_is_vec = is_ivector_node(consequent );
+            const bool alter_is_vec = is_ivector_node(alternative);
+
+            if (consq_is_vec || alter_is_vec)
+            {
+               if (consq_is_vec && alter_is_vec)
+               {
+                  return expression_generator_
+                           .conditional_vector(condition, consequent, alternative);
+               }
+
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR052 - Return types of if-statement differ: vector/non-vector",
+                  exprtk_error_location));
+
+               result = false;
+            }
+         }
+
          if (!result)
          {
-            free_node(node_allocator_,   condition);
-            free_node(node_allocator_,  consequent);
+            free_node(node_allocator_, condition  );
+            free_node(node_allocator_, consequent );
             free_node(node_allocator_, alternative);
 
             return error_node();
@@ -22584,21 +26361,21 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (0 == (condition = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR047 - Failed to parse condition for if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR054 - Failed to parse condition for if-statement",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22609,30 +26386,32 @@ namespace exprtk
          }
          else if (token_is(token_t::e_rbracket))
          {
-            // 00. if (x) y;
-            // 01. if (x) y; else z;
-            // 02. if (x) y; else {z0; ... zn;}
-            // 03. if (x) y; else if (z) w;
-            // 04. if (x) y; else if (z) w; else u;
-            // 05. if (x) y; else if (z) w; else {u0; ... un;}
-            // 06. if (x) y; else if (z) {w0; ... wn;}
-            // 07. if (x) {y0; ... yn;}
-            // 08. if (x) {y0; ... yn;} else z;
-            // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
-            // 10. if (x) {y0; ... yn;} else if (z) w;
-            // 11. if (x) {y0; ... yn;} else if (z) w; else u;
-            // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
-            // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
+            /*
+               00. if (x) y;
+               01. if (x) y; else z;
+               02. if (x) y; else {z0; ... zn;}
+               03. if (x) y; else if (z) w;
+               04. if (x) y; else if (z) w; else u;
+               05. if (x) y; else if (z) w; else {u0; ... un;}
+               06. if (x) y; else if (z) {w0; ... wn;}
+               07. if (x) {y0; ... yn;}
+               08. if (x) {y0; ... yn;} else z;
+               09. if (x) {y0; ... yn;} else {z0; ... zn;};
+               10. if (x) {y0; ... yn;} else if (z) w;
+               11. if (x) {y0; ... yn;} else if (z) w; else u;
+               12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
+               13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
+            */
             return parse_conditional_statement_02(condition);
          }
 
-         set_error(
-            make_error(parser_error::e_syntax,
-                       current_token(),
-                       "ERR048 - Invalid if-statement",
-                       exprtk_error_location));
+         set_error(make_error(
+            parser_error::e_syntax,
+            current_token(),
+            "ERR055 - Invalid if-statement",
+            exprtk_error_location));
 
-         free_node(node_allocator_,condition);
+         free_node(node_allocator_, condition);
 
          return error_node();
       }
@@ -22647,51 +26426,51 @@ namespace exprtk
 
          if (0 == condition)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR049 - Encountered invalid condition branch for ternary if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR056 - Encountered invalid condition branch for ternary if-statement",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (!token_is(token_t::e_ternary))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR050 - Expected '?' after condition of ternary if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR057 - Expected '?' after condition of ternary if-statement",
+               exprtk_error_location));
 
             result = false;
          }
          else if (0 == (consequent = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR051 - Failed to parse consequent for ternary if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR058 - Failed to parse consequent for ternary if-statement",
+               exprtk_error_location));
 
             result = false;
          }
          else if (!token_is(token_t::e_colon))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR052 - Expected ':' between ternary if-statement consequent and alternative",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR059 - Expected ':' between ternary if-statement consequent and alternative",
+               exprtk_error_location));
 
             result = false;
          }
          else if (0 == (alternative = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR053 - Failed to parse alternative for ternary if-statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR060 - Failed to parse alternative for ternary if-statement",
+               exprtk_error_location));
 
             result = false;
          }
@@ -22699,7 +26478,7 @@ namespace exprtk
          #ifndef exprtk_disable_string_capabilities
          if (result)
          {
-            const bool consq_is_str = is_generally_string_node( consequent);
+            const bool consq_is_str = is_generally_string_node(consequent );
             const bool alter_is_str = is_generally_string_node(alternative);
 
             if (consq_is_str || alter_is_str)
@@ -22710,21 +26489,44 @@ namespace exprtk
                            .conditional_string(condition, consequent, alternative);
                }
 
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR054 - Return types of ternary if-statement differ",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR061 - Return types of ternary differ: string/non-string",
+                  exprtk_error_location));
 
                result = false;
             }
          }
          #endif
 
+         if (result)
+         {
+            const bool consq_is_vec = is_ivector_node(consequent );
+            const bool alter_is_vec = is_ivector_node(alternative);
+
+            if (consq_is_vec || alter_is_vec)
+            {
+               if (consq_is_vec && alter_is_vec)
+               {
+                  return expression_generator_
+                           .conditional_vector(condition, consequent, alternative);
+               }
+
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR062 - Return types of ternary differ: vector/non-vector",
+                  exprtk_error_location));
+
+               result = false;
+            }
+         }
+
          if (!result)
          {
-            free_node(node_allocator_,   condition);
-            free_node(node_allocator_,  consequent);
+            free_node(node_allocator_, condition  );
+            free_node(node_allocator_, consequent );
             free_node(node_allocator_, alternative);
 
             return error_node();
@@ -22738,11 +26540,11 @@ namespace exprtk
       {
          if (settings_.logic_disabled("not"))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR055 - Invalid or disabled logic operation 'not'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR063 - Invalid or disabled logic operation 'not'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -22750,6 +26552,12 @@ namespace exprtk
          return parse_base_operation();
       }
 
+      void handle_brkcnt_scope_exit()
+      {
+         assert(!brkcnt_list_.empty());
+         brkcnt_list_.pop_front();
+      }
+
       inline expression_node_ptr parse_while_loop()
       {
          // Parse: [while][(][test expr][)][{][expression][}]
@@ -22763,31 +26571,31 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR056 - Expected '(' at start of while-loop condition statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR064 - Expected '(' at start of while-loop condition statement",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (0 == (condition = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR057 - Failed to parse condition for while-loop",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR065 - Failed to parse condition for while-loop",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (!token_is(token_t::e_rbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR058 - Expected ')' at end of while-loop condition statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR066 - Expected ')' at end of while-loop condition statement",
+               exprtk_error_location));
 
             result = false;
          }
@@ -22798,40 +26606,53 @@ namespace exprtk
          {
             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
 
-            if (0 == (branch = parse_multi_sequence("while-loop")))
+            if (0 == (branch = parse_multi_sequence("while-loop", true)))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR059 - Failed to parse body of while-loop"));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR067 - Failed to parse body of while-loop"));
                result = false;
             }
             else if (0 == (result_node = expression_generator_.while_loop(condition,
                                                                           branch,
                                                                           brkcnt_list_.front())))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR060 - Failed to synthesize while-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR068 - Failed to synthesize while-loop",
+                  exprtk_error_location));
 
                result = false;
             }
          }
 
+         handle_brkcnt_scope_exit();
+
          if (!result)
          {
-            free_node(node_allocator_,      branch);
-            free_node(node_allocator_,   condition);
+            free_node(node_allocator_, branch     );
+            free_node(node_allocator_, condition  );
             free_node(node_allocator_, result_node);
 
-            brkcnt_list_.pop_front();
-
             return error_node();
          }
-         else
+
+         if (result_node && result_node->valid())
+         {
             return result_node;
+         }
+
+         set_error(make_error(
+            parser_error::e_synthesis,
+            current_token(),
+            "ERR069 - Failed to synthesize 'valid' while-loop",
+            exprtk_error_location));
+
+         free_node(node_allocator_, result_node);
+
+         return error_node();
       }
 
       inline expression_node_ptr parse_repeat_until_loop()
@@ -22855,7 +26676,7 @@ namespace exprtk
          }
          else
          {
-            const token_t::token_type seperator = token_t::e_eof;
+            const token_t::token_type separator = token_t::e_eof;
 
             scope_handler sh(*this);
 
@@ -22886,13 +26707,13 @@ namespace exprtk
                const bool is_next_until = peek_token_is(token_t::e_symbol) &&
                                           peek_token_is("until");
 
-               if (!token_is(seperator) && is_next_until)
+               if (!token_is(separator) && is_next_until)
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -22910,13 +26731,11 @@ namespace exprtk
 
             if (sdd.delete_ptr)
             {
-               brkcnt_list_.pop_front();
-
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR062 - Failed to parse body of repeat until loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR071 - Failed to parse body of repeat until loop",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -22924,72 +26743,76 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            brkcnt_list_.pop_front();
-
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR063 - Expected '(' before condition statement of repeat until loop",
-                          exprtk_error_location));
-
-            free_node(node_allocator_,branch);
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR072 - Expected '(' before condition statement of repeat until loop",
+               exprtk_error_location));
 
+            free_node(node_allocator_, branch);
             return error_node();
          }
          else if (0 == (condition = parse_expression()))
          {
-            brkcnt_list_.pop_front();
-
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR064 - Failed to parse condition for repeat until loop",
-                          exprtk_error_location));
-
-            free_node(node_allocator_,branch);
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR073 - Failed to parse condition for repeat until loop",
+               exprtk_error_location));
 
+            free_node(node_allocator_, branch);
             return error_node();
          }
          else if (!token_is(token_t::e_rbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR065 - Expected ')' after condition of repeat until loop",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR074 - Expected ')' after condition of repeat until loop",
+               exprtk_error_location));
 
-            free_node(node_allocator_,    branch);
+            free_node(node_allocator_, branch   );
             free_node(node_allocator_, condition);
 
-            brkcnt_list_.pop_front();
-
             return error_node();
          }
 
-         expression_node_ptr result;
-
-         result = expression_generator_
-                     .repeat_until_loop(condition, branch, brkcnt_list_.front());
+         expression_node_ptr result_node =
+            expression_generator_
+               .repeat_until_loop(
+                  condition,
+                  branch,
+                  brkcnt_list_.front());
 
-         if (0 == result)
+         if (0 == result_node)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR066 - Failed to synthesize repeat until loop",
-                          exprtk_error_location));
-
-            free_node(node_allocator_,condition);
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR075 - Failed to synthesize repeat until loop",
+               exprtk_error_location));
 
-            brkcnt_list_.pop_front();
+            free_node(node_allocator_, condition);
 
             return error_node();
          }
-         else
+
+         handle_brkcnt_scope_exit();
+
+         if (result_node && result_node->valid())
          {
-            brkcnt_list_.pop_front();
-            return result;
+            return result_node;
          }
+
+         set_error(make_error(
+            parser_error::e_synthesis,
+            current_token(),
+            "ERR076 - Failed to synthesize 'valid' repeat until loop",
+            exprtk_error_location));
+
+         free_node(node_allocator_, result_node);
+
+         return error_node();
       }
 
       inline expression_node_ptr parse_for_loop()
@@ -23008,11 +26831,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR067 - Expected '(' at start of for-loop",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR077 - Expected '(' at start of for-loop",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23028,21 +26851,21 @@ namespace exprtk
 
                if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR068 - Expected a variable at the start of initialiser section of for-loop",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR078 - Expected a variable at the start of initialiser section of for-loop",
+                     exprtk_error_location));
 
                   return error_node();
                }
                else if (!peek_token_is(token_t::e_assign))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR069 - Expected variable assignment of initialiser section of for-loop",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR079 - Expected variable assignment of initialiser section of for-loop",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -23053,11 +26876,11 @@ namespace exprtk
 
                if ((se->name == loop_counter_symbol) && se->active)
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -23066,7 +26889,7 @@ namespace exprtk
                   if (
                        !se->active &&
                        (se->name == loop_counter_symbol) &&
-                       (se->type ==  scope_element::e_variable)
+                       (se->type == scope_element::e_variable)
                      )
                   {
                      se->active = true;
@@ -23085,11 +26908,11 @@ namespace exprtk
 
                      if (!sem_.add_element(nse))
                      {
-                        set_error(
-                           make_error(parser_error::e_syntax,
-                                      current_token(),
-                                      "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
-                                      exprtk_error_location));
+                        set_error(make_error(
+                           parser_error::e_syntax,
+                           current_token(),
+                           "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
+                           exprtk_error_location));
 
                         sem_.free_element(nse);
 
@@ -23097,7 +26920,7 @@ namespace exprtk
                      }
                      else
                      {
-                        exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
+                        exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str()));
 
                         state_.activate_side_effect("parse_for_loop()");
                      }
@@ -23107,21 +26930,21 @@ namespace exprtk
 
             if (0 == (initialiser = parse_expression()))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR072 - Failed to parse initialiser of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR082 - Failed to parse initialiser of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
             else if (!token_is(token_t::e_eof))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR073 - Expected ';' after initialiser of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR083 - Expected ';' after initialiser of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
@@ -23131,21 +26954,21 @@ namespace exprtk
          {
             if (0 == (condition = parse_expression()))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR074 - Failed to parse condition of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR084 - Failed to parse condition of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
             else if (!token_is(token_t::e_eof))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR075 - Expected ';' after condition section of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR085 - Expected ';' after condition section of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
@@ -23155,21 +26978,21 @@ namespace exprtk
          {
             if (0 == (incrementor = parse_expression()))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR076 - Failed to parse incrementor of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR086 - Failed to parse incrementor of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
             else if (!token_is(token_t::e_rbracket))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR077 - Expected ')' after incrementor section of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR087 - Expected ')' after incrementor section of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
@@ -23181,13 +27004,13 @@ namespace exprtk
 
             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
 
-            if (0 == (loop_body = parse_multi_sequence("for-loop")))
+            if (0 == (loop_body = parse_multi_sequence("for-loop", true)))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR078 - Failed to parse body of for-loop",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR088 - Failed to parse body of for-loop",
+                  exprtk_error_location));
 
                result = false;
             }
@@ -23201,29 +27024,34 @@ namespace exprtk
             }
 
             free_node(node_allocator_, initialiser);
-            free_node(node_allocator_,   condition);
+            free_node(node_allocator_, condition  );
             free_node(node_allocator_, incrementor);
-            free_node(node_allocator_,   loop_body);
-
-            if (!brkcnt_list_.empty())
-            {
-               brkcnt_list_.pop_front();
-            }
-
+            free_node(node_allocator_, loop_body  );
             return error_node();
          }
-         else
-         {
-            expression_node_ptr result_node =
-               expression_generator_.for_loop(initialiser,
-                                              condition,
-                                              incrementor,
-                                              loop_body,
-                                              brkcnt_list_.front());
-            brkcnt_list_.pop_front();
 
+         expression_node_ptr result_node =
+            expression_generator_.for_loop(initialiser,
+                                           condition,
+                                           incrementor,
+                                           loop_body,
+                                           brkcnt_list_.front());
+         handle_brkcnt_scope_exit();
+
+         if (result_node && result_node->valid())
+         {
             return result_node;
          }
+
+         set_error(make_error(
+            parser_error::e_synthesis,
+            current_token(),
+            "ERR089 - Failed to synthesize 'valid' for-loop",
+            exprtk_error_location));
+
+         free_node(node_allocator_, result_node);
+
+         return error_node();
       }
 
       inline expression_node_ptr parse_switch_statement()
@@ -23233,11 +27061,11 @@ namespace exprtk
 
          if (!details::imatch(current_token().value,"switch"))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR079 - Expected keyword 'switch'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR090 - Expected keyword 'switch'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23248,11 +27076,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_lcrlbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR080 - Expected '{' for call to switch statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR091 - Expected '{' for call to switch statement",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23273,18 +27101,21 @@ namespace exprtk
                   return error_node();
                else if (!token_is(token_t::e_colon))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR081 - Expected ':' for case of switch statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR092 - Expected ':' for case of switch statement",
+                     exprtk_error_location));
 
                   free_node(node_allocator_, condition);
 
                   return error_node();
                }
 
-               expression_node_ptr consequent = parse_expression();
+               expression_node_ptr consequent =
+                  (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
+                  parse_multi_sequence("switch-consequent") :
+                  parse_expression();
 
                if (0 == consequent)
                {
@@ -23294,13 +27125,13 @@ namespace exprtk
                }
                else if (!token_is(token_t::e_eof))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR082 - Expected ';' at end of case for switch statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR093 - Expected ';' at end of case for switch statement",
+                     exprtk_error_location));
 
-                  free_node(node_allocator_,  condition);
+                  free_node(node_allocator_, condition );
                   free_node(node_allocator_, consequent);
 
                   return error_node();
@@ -23309,12 +27140,12 @@ namespace exprtk
                // Can we optimise away the case statement?
                if (is_constant_node(condition) && is_false(condition))
                {
-                  free_node(node_allocator_,  condition);
+                  free_node(node_allocator_, condition );
                   free_node(node_allocator_, consequent);
                }
                else
                {
-                  arg_list.push_back( condition);
+                  arg_list.push_back(condition );
                   arg_list.push_back(consequent);
                }
 
@@ -23323,11 +27154,11 @@ namespace exprtk
             {
                if (0 != default_statement)
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR083 - Multiple default cases for switch statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR094 - Multiple default cases for switch statement",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -23336,29 +27167,29 @@ namespace exprtk
 
                if (!token_is(token_t::e_colon))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR084 - Expected ':' for default of switch statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR095 - Expected ':' for default of switch statement",
+                     exprtk_error_location));
 
                   return error_node();
                }
 
-               if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
-                  default_statement = parse_multi_sequence("switch-default");
-               else
-                  default_statement = parse_expression();
+               default_statement =
+                  (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
+                  parse_multi_sequence("switch-default"):
+                  parse_expression();
 
                if (0 == default_statement)
                   return error_node();
                else if (!token_is(token_t::e_eof))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR085 - Expected ';' at end of default for switch statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR096 - Expected ';' at end of default for switch statement",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -23367,11 +27198,11 @@ namespace exprtk
                break;
             else
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR086 - Expected '}' at end of switch statement",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR097 - Expected '}' at end of switch statement",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -23383,6 +27214,10 @@ namespace exprtk
          {
             arg_list.push_back(default_statement);
          }
+         else
+         {
+            arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN()));
+         }
 
          result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
 
@@ -23398,11 +27233,11 @@ namespace exprtk
 
          if (!details::imatch(current_token().value,"[*]"))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR087 - Expected token '[*]'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR098 - Expected token '[*]'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23413,11 +27248,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_lcrlbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR088 - Expected '{' for call to [*] statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR099 - Expected '{' for call to [*] statement",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23426,11 +27261,11 @@ namespace exprtk
          {
             if (!details::imatch("case",current_token().value))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR089 - Expected a 'case' statement for multi-switch",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR100 - Expected a 'case' statement for multi-switch",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -23444,27 +27279,30 @@ namespace exprtk
 
             if (!token_is(token_t::e_colon))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR090 - Expected ':' for case of [*] statement",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR101 - Expected ':' for case of [*] statement",
+                  exprtk_error_location));
 
                return error_node();
             }
 
-            expression_node_ptr consequent = parse_expression();
+            expression_node_ptr consequent =
+               (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
+               parse_multi_sequence("multi-switch-consequent") :
+               parse_expression();
 
             if (0 == consequent)
                return error_node();
 
             if (!token_is(token_t::e_eof))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR091 - Expected ';' at end of case for [*] statement",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR102 - Expected ';' at end of case for [*] statement",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -23472,12 +27310,12 @@ namespace exprtk
             // Can we optimise away the case statement?
             if (is_constant_node(condition) && is_false(condition))
             {
-               free_node(node_allocator_,  condition);
+               free_node(node_allocator_, condition );
                free_node(node_allocator_, consequent);
             }
             else
             {
-               arg_list.push_back( condition);
+               arg_list.push_back(condition );
                arg_list.push_back(consequent);
             }
 
@@ -23489,11 +27327,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_rcrlbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR092 - Expected '}' at end of [*] statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR103 - Expected '}' at end of [*] statement",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23515,11 +27353,11 @@ namespace exprtk
          if (details::imatch(symbol,"~"))
          {
             next_token();
-            return parse_multi_sequence();
+            return check_block_statement_closure(parse_multi_sequence());
          }
          else if (details::imatch(symbol,"[*]"))
          {
-            return parse_multi_switch_statement();
+            return check_block_statement_closure(parse_multi_switch_statement());
          }
          else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
          else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
@@ -23530,11 +27368,11 @@ namespace exprtk
          else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
          else
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR093 - Unsupported vararg function: " + symbol,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR104 - Unsupported built-in vararg function: " + symbol,
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23547,11 +27385,23 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR094 - Expected '(' for call to vararg function: " + symbol,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR105 - Expected '(' for call to vararg function: " + symbol,
+               exprtk_error_location));
+
+            return error_node();
+         }
+
+         if (token_is(token_t::e_rbracket))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR106 - vararg function: " + symbol +
+               " requires at least one input parameter",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -23569,11 +27419,11 @@ namespace exprtk
                break;
             else if (!token_is(token_t::e_comma))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR095 - Expected ',' for call to vararg function: " + symbol,
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR107 - Expected ',' for call to vararg function: " + symbol,
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -23590,13 +27440,13 @@ namespace exprtk
       {
          if (!token_is(token_t::e_lsqrbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR096 - Expected '[' as start of string range definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR108 - Expected '[' as start of string range definition",
+               exprtk_error_location));
 
-            free_node(node_allocator_,expression);
+            free_node(node_allocator_, expression);
 
             return error_node();
          }
@@ -23609,7 +27459,7 @@ namespace exprtk
 
          if (!parse_range(rp,true))
          {
-            free_node(node_allocator_,expression);
+            free_node(node_allocator_, expression);
 
             return error_node();
          }
@@ -23618,19 +27468,32 @@ namespace exprtk
 
          if (0 == result)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR097 - Failed to generate string range node",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR109 - Failed to generate string range node",
+               exprtk_error_location));
 
-            free_node(node_allocator_,expression);
+            free_node(node_allocator_, expression);
             rp.free();
          }
 
          rp.clear();
 
-         return result;
+         if (result && result->valid())
+         {
+            return result;
+         }
+
+         set_error(make_error(
+            parser_error::e_synthesis,
+            current_token(),
+            "ERR110 - Failed to synthesize node: string_range_node",
+            exprtk_error_location));
+
+         free_node(node_allocator_, result);
+         rp.free();
+         return error_node();
       }
       #else
       inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
@@ -23639,7 +27502,7 @@ namespace exprtk
       }
       #endif
 
-      inline void parse_pending_string_rangesize(expression_node_ptr& expression)
+      inline bool parse_pending_string_rangesize(expression_node_ptr& expression)
       {
          // Allow no more than 100 range calls, eg: s[][][]...[][]
          const std::size_t max_rangesize_parses = 100;
@@ -23657,6 +27520,61 @@ namespace exprtk
          {
             expression = parse_string_range_statement(expression);
          }
+
+         return (i > 1);
+      }
+
+      inline void parse_pending_vector_index_operator(expression_node_ptr& expression)
+      {
+         if
+            (
+              (0 != expression)           &&
+              error_list_.empty()         &&
+              is_ivector_node(expression)
+            )
+         {
+            if (
+                 settings_.commutative_check_enabled()       &&
+                 token_is(token_t::e_mul,prsrhlpr_t::e_hold) &&
+                 peek_token_is(token_t::e_lsqrbracket)
+               )
+            {
+               token_is(token_t::e_mul);
+               token_is(token_t::e_lsqrbracket);
+            }
+            else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
+            {
+               token_is(token_t::e_lsqrbracket);
+            }
+            else if (
+                      token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) &&
+                      peek_token_is(token_t::e_lsqrbracket)
+                    )
+            {
+               token_is(token_t::e_rbracket   );
+               token_is(token_t::e_lsqrbracket);
+            }
+            else
+               return;
+
+            details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression);
+
+            if (vi)
+            {
+               details::vector_holder<T>& vec = vi->vec()->vec_holder();
+               const std::string vector_name  = sem_.get_vector_name(vec.data());
+               expression_node_ptr index      = parse_vector_index(vector_name);
+
+               if (index)
+               {
+                  expression = synthesize_vector_element(vector_name, &vec, expression, index);
+                  return;
+               }
+            }
+
+            free_node(node_allocator_, expression);
+            expression = error_node();
+         }
       }
 
       template <typename Allocator1,
@@ -23673,6 +27591,10 @@ namespace exprtk
 
          Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
 
+         exprtk_debug(("simplify() - expression_list.size: %d  side_effect_list.size(): %d\n",
+                       static_cast<int>(expression_list .size()),
+                       static_cast<int>(side_effect_list.size())));
+
          bool return_node_present = false;
 
          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
@@ -23692,7 +27614,7 @@ namespace exprtk
 
                for (std::size_t j = i + 1; j < expression_list.size(); ++j)
                {
-                  free_node(node_allocator_,expression_list[j]);
+                  free_node(node_allocator_, expression_list[j]);
                }
 
                return_node_present = true;
@@ -23705,7 +27627,7 @@ namespace exprtk
                       !side_effect_list[i]
                     )
             {
-               free_node(node_allocator_,expression_list[i]);
+               free_node(node_allocator_, expression_list[i]);
                continue;
             }
             else
@@ -23727,8 +27649,8 @@ namespace exprtk
          }
 
          if (
-              return_node_present          ||
-              side_effect_list.back()      ||
+              return_node_present     ||
+              side_effect_list.back() ||
               (expression_list.size() > 1)
             )
             state_.activate_side_effect("simplify()");
@@ -23741,31 +27663,34 @@ namespace exprtk
             return expression_generator_.vararg_function(details::e_multi,expression_list);
       }
 
-      inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
+      inline expression_node_ptr parse_multi_sequence(const std::string& source = "",
+                                                      const bool enforce_crlbrackets = false)
       {
+         token_t::token_type open_bracket  = token_t::e_lcrlbracket;
          token_t::token_type close_bracket = token_t::e_rcrlbracket;
-         token_t::token_type seperator     = token_t::e_eof;
+         token_t::token_type separator     = token_t::e_eof;
 
-         if (!token_is(token_t::e_lcrlbracket))
+         if (!token_is(open_bracket))
          {
-            if (token_is(token_t::e_lbracket))
+            if (!enforce_crlbrackets && token_is(token_t::e_lbracket))
             {
+               open_bracket  = token_t::e_lbracket;
                close_bracket = token_t::e_rbracket;
-               seperator     = token_t::e_comma;
+               separator     = token_t::e_comma;
             }
             else
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
-                             ((!source.empty()) ? std::string(" section of " + source): ""),
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" +
+                  ((!source.empty()) ? std::string(" section of " + source): ""),
+                  exprtk_error_location));
 
                return error_node();
             }
          }
-         else if (token_is(token_t::e_rcrlbracket))
+         else if (token_is(close_bracket))
          {
             return node_allocator_.allocate<details::null_node<T> >();
          }
@@ -23800,13 +27725,13 @@ namespace exprtk
 
             const bool is_next_close = peek_token_is(close_bracket);
 
-            if (!token_is(seperator) && is_next_close)
+            if (!token_is(separator) && is_next_close)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source,
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -23815,7 +27740,7 @@ namespace exprtk
                break;
          }
 
-         result = simplify(arg_list,side_effect_list,source.empty());
+         result = simplify(arg_list, side_effect_list, source.empty());
 
          sdd.delete_ptr = (0 == result);
          return result;
@@ -23824,23 +27749,23 @@ namespace exprtk
       inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
       {
          // Examples of valid ranges:
-         // 1. [1:5]     -> 1..5
-         // 2. [ :5]     -> 0..5
-         // 3. [1: ]     -> 1..end
-         // 4. [x:y]     -> x..y where x <= y
-         // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
-         // 6. [ :y]     -> 0..y where 0 <= y
-         // 7. [x: ]     -> x..end where x <= end
+         // 1. [1:5]     -> [1,5)
+         // 2. [ :5]     -> [0,5)
+         // 3. [1: ]     -> [1,end)
+         // 4. [x:y]     -> [x,y) where x <= y
+         // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2
+         // 6. [ :y]     -> [0,y) where 0 <= y
+         // 7. [x: ]     -> [x,end) where x <= end
 
          rp.clear();
 
          if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR100 - Expected '[' for start of range",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR113 - Expected '[' for start of range",
+               exprtk_error_location));
 
             return false;
          }
@@ -23857,11 +27782,11 @@ namespace exprtk
 
             if (0 == r0)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR101 - Failed parse begin section of range",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR114 - Failed parse begin section of range",
+                  exprtk_error_location));
 
                return false;
             }
@@ -23876,15 +27801,15 @@ namespace exprtk
                   rp.cache.first = rp.n0_c.second;
                }
 
-               free_node(node_allocator_,r0);
+               free_node(node_allocator_, r0);
 
                if (r0_value < T(0))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0",
+                     exprtk_error_location));
 
                   return false;
                }
@@ -23897,11 +27822,11 @@ namespace exprtk
 
             if (!token_is(token_t::e_colon))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR103 - Expected ':' for break  in range",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR116 - Expected ':' for break  in range",
+                  exprtk_error_location));
 
                rp.free();
 
@@ -23920,11 +27845,11 @@ namespace exprtk
 
             if (0 == r1)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR104 - Failed parse end section of range",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR117 - Failed parse end section of range",
+                  exprtk_error_location));
 
                rp.free();
 
@@ -23941,15 +27866,15 @@ namespace exprtk
                   rp.cache.second = rp.n1_c.second;
                }
 
-               free_node(node_allocator_,r1);
+               free_node(node_allocator_, r1);
 
                if (r1_value < T(0))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0",
+                     exprtk_error_location));
 
                   rp.free();
 
@@ -23964,11 +27889,11 @@ namespace exprtk
 
             if (!token_is(token_t::e_rsqrbracket))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR106 - Expected ']' for start of range",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR119 - Expected ']' for start of range",
+                  exprtk_error_location));
 
                rp.free();
 
@@ -23992,11 +27917,11 @@ namespace exprtk
 
             if (!rp_result || (r0 > r1))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR107 - Invalid range, Constraint: r0 <= r1",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR120 - Invalid range, Constraint: r0 <= r1",
+                  exprtk_error_location));
 
                return false;
             }
@@ -24031,24 +27956,36 @@ namespace exprtk
          }
          else
          {
-            if (!symtab_store_.is_conststr_stringvar(symbol))
+            typedef typename symtab_store::string_context str_ctxt_t;
+            str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol);
+
+            if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR108 - Unknown string symbol",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR121 - Unknown string symbol",
+                  exprtk_error_location));
 
                return error_node();
             }
 
-            result = symtab_store_.get_stringvar(symbol);
+            assert(str_ctx.str_var != 0);
+            assert(str_ctx.symbol_table != 0);
+
+            result = str_ctx.str_var;
 
             if (symtab_store_.is_constant_string(symbol))
             {
                const_str_node = static_cast<strvar_node_t>(result);
                result = expression_generator_(const_str_node->str());
             }
+            else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability())
+            {
+               lodge_immutable_symbol(
+                  current_token(),
+                  make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size()));
+            }
 
             lodge_symbol(symbol, e_st_string);
          }
@@ -24064,7 +28001,7 @@ namespace exprtk
 
                if (const_str_node)
                {
-                  free_node(node_allocator_,result);
+                  free_node(node_allocator_, result);
 
                   return expression_generator_(T(const_str_node->size()));
                }
@@ -24077,13 +28014,13 @@ namespace exprtk
 
             if (!parse_range(rp))
             {
-               free_node(node_allocator_,result);
+               free_node(node_allocator_, result);
 
                return error_node();
             }
             else if (const_str_node)
             {
-               free_node(node_allocator_,result);
+               free_node(node_allocator_, result);
                result = expression_generator_(const_str_node->ref(),rp);
             }
             else
@@ -24120,7 +28057,7 @@ namespace exprtk
                next_token();
                next_token();
 
-               free_node(node_allocator_,result);
+               free_node(node_allocator_, result);
 
                return expression_generator_(T(const_str.size()));
             }
@@ -24129,13 +28066,13 @@ namespace exprtk
 
             if (!parse_range(rp))
             {
-               free_node(node_allocator_,result);
+               free_node(node_allocator_, result);
                rp.free();
 
                return error_node();
             }
 
-            free_node(node_allocator_,result);
+            free_node(node_allocator_, result);
 
             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
             {
@@ -24148,13 +28085,13 @@ namespace exprtk
                  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
                )
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR109 - Overflow in range for string: '" + const_str + "'[" +
-                             (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
-                             (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR122 - Overflow in range for string: '" + const_str + "'[" +
+                  (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
+                  (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
+                  exprtk_error_location));
 
                rp.free();
 
@@ -24178,35 +28115,82 @@ namespace exprtk
       }
       #endif
 
+      inline expression_node_ptr parse_vector_index(const std::string& vector_name = "")
+      {
+         expression_node_ptr index_expr = error_node();
+
+         if (0 == (index_expr = parse_expression()))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR123 - Failed to parse index for vector: '" + vector_name + "'",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_rsqrbracket))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR124 - Expected ']' for index of vector: '" + vector_name + "'",
+               exprtk_error_location));
+
+            free_node(node_allocator_, index_expr);
+
+            return error_node();
+         }
+
+         return index_expr;
+      }
+
       inline expression_node_ptr parse_vector()
       {
-         const std::string symbol = current_token().value;
+         const std::string vector_name = current_token().value;
 
          vector_holder_ptr vec = vector_holder_ptr(0);
 
-         const scope_element& se = sem_.get_active_element(symbol);
+         const scope_element& se = sem_.get_active_element(vector_name);
 
          if (
-              !details::imatch(se.name, symbol) ||
+              !details::imatch(se.name, vector_name) ||
               (se.depth > state_.scope_depth)   ||
               (scope_element::e_vector != se.type)
             )
          {
-            if (0 == (vec = symtab_store_.get_vector(symbol)))
+            typedef typename symtab_store::vector_context vec_ctxt_t;
+            vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name);
+
+            if (0 == vec_ctx.vector_holder)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR110 - Symbol '" + symbol+ " not a vector",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR125 - Symbol '" + vector_name + " not a vector",
+                  exprtk_error_location));
 
                return error_node();
             }
+
+            assert(0 != vec_ctx.vector_holder);
+            assert(0 != vec_ctx.symbol_table );
+
+            vec = vec_ctx.vector_holder;
+
+            if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability())
+            {
+               lodge_immutable_symbol(
+                  current_token(),
+                  make_memory_range(vec->data(), vec->size()));
+            }
          }
          else
+         {
             vec = se.vec_node;
+         }
 
-         expression_node_ptr index_expr = error_node();
+         assert(0 != vec);
 
          next_token();
 
@@ -24216,31 +28200,28 @@ namespace exprtk
          }
          else if (token_is(token_t::e_rsqrbracket))
          {
-            return expression_generator_(T(vec->size()));
+            return (vec->rebaseable()) ?
+               node_allocator_.allocate<vector_size_node_t>(vec) :
+               expression_generator_(T(vec->size()));
          }
-         else if (0 == (index_expr = parse_expression()))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR111 - Failed to parse index for vector: '" + symbol + "'",
-                          exprtk_error_location));
 
-            return error_node();
-         }
-         else if (!token_is(token_t::e_rsqrbracket))
-         {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR112 - Expected ']' for index of vector: '" + symbol + "'",
-                          exprtk_error_location));
+         expression_node_ptr index_expr = parse_vector_index(vector_name);
 
-            free_node(node_allocator_,index_expr);
+         if (index_expr)
+         {
+            expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec);
 
-            return error_node();
+            return synthesize_vector_element(vector_name, vec, vec_node, index_expr);
          }
 
+         return error_node();
+      }
+
+      inline expression_node_ptr synthesize_vector_element(const std::string& vector_name,
+                                                           vector_holder_ptr vec,
+                                                           expression_node_ptr vec_node,
+                                                           expression_node_ptr index_expr)
+      {
          // Perform compile-time range check
          if (details::is_constant_node(index_expr))
          {
@@ -24249,20 +28230,21 @@ namespace exprtk
 
             if (index >= vec_size)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR113 - Index of " + details::to_str(index) + " out of range for "
-                             "vector '" + symbol + "' of size " + details::to_str(vec_size),
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR126 - Index of " + details::to_str(index) + " out of range for "
+                  "vector '" + vector_name + "' of size " + details::to_str(vec_size),
+                  exprtk_error_location));
 
-               free_node(node_allocator_,index_expr);
+               free_node(node_allocator_, vec_node  );
+               free_node(node_allocator_, index_expr);
 
                return error_node();
             }
          }
 
-         return expression_generator_.vector_element(symbol, vec, index_expr);
+         return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr);
       }
 
       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
@@ -24281,12 +28263,12 @@ namespace exprtk
             {
                if (!vararg_function->allow_zero_parameters())
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR114 - Zero parameter call to vararg function: "
-                                + vararg_function_name + " not allowed",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR127 - Zero parameter call to vararg function: "
+                     + vararg_function_name + " not allowed",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -24306,12 +28288,12 @@ namespace exprtk
                      break;
                   else if (!token_is(token_t::e_comma))
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR115 - Expected ',' for call to vararg function: "
-                                   + vararg_function_name,
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR128 - Expected ',' for call to vararg function: "
+                        + vararg_function_name,
+                        exprtk_error_location));
 
                      return error_node();
                   }
@@ -24320,37 +28302,37 @@ namespace exprtk
          }
          else if (!vararg_function->allow_zero_parameters())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR116 - Zero parameter call to vararg function: "
-                          + vararg_function_name + " not allowed",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR129 - Zero parameter call to vararg function: "
+               + vararg_function_name + " not allowed",
+               exprtk_error_location));
 
             return error_node();
          }
 
          if (arg_list.size() < vararg_function->min_num_args())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR117 - Invalid number of parameters to call to vararg function: "
-                          + vararg_function_name + ", require at least "
-                          + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR130 - Invalid number of parameters to call to vararg function: "
+               + vararg_function_name + ", require at least "
+               + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (arg_list.size() > vararg_function->max_num_args())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR118 - Invalid number of parameters to call to vararg function: "
-                          + vararg_function_name + ", require no more than "
-                          + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR131 - Invalid number of parameters to call to vararg function: "
+               + vararg_function_name + ", require no more than "
+               + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -24386,10 +28368,10 @@ namespace exprtk
                       const std::string& func_name,
                       const std::string& func_prototypes,
                       const return_type_t default_return_type)
-         : invalid_state_(true),
-           parser_(p),
-           function_name_(func_name),
-           default_return_type_(default_return_type)
+         : invalid_state_(true)
+         , parser_(p)
+         , function_name_(func_name)
+         , default_return_type_(default_return_type)
          {
             parse_function_prototypes(func_prototypes);
          }
@@ -24421,14 +28403,13 @@ namespace exprtk
 
             if (1 == error_list.size())
             {
-               parser_.
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                parser_.current_token(),
-                                "ERR119 - Failed parameter type check for function '" + function_name_ + "', "
-                                "Expected '" + function_definition_list_[0].param_seq +
-                                "'  call set: '" + param_seq + "'",
-                                exprtk_error_location));
+               parser_.set_error(make_error(
+                  parser_error::e_syntax,
+                  parser_.current_token(),
+                  "ERR132 - Failed parameter type check for function '" + function_name_ + "', "
+                  "Expected '" + function_definition_list_[0].param_seq +
+                  "' call set: '" + param_seq + "'",
+                  exprtk_error_location));
             }
             else
             {
@@ -24443,14 +28424,13 @@ namespace exprtk
                   }
                }
 
-               parser_.
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                parser_.current_token(),
-                                "ERR120 - Failed parameter type check for function '" + function_name_ + "', "
-                                "Best match: '" + function_definition_list_[max_diff_index].param_seq +
-                                "'  call set: '" + param_seq + "'",
-                                exprtk_error_location));
+               parser_.set_error(make_error(
+                  parser_error::e_syntax,
+                  parser_.current_token(),
+                  "ERR133 - Failed parameter type check for function '" + function_name_ + "', "
+                  "Best match: '" + function_definition_list_[max_diff_index].param_seq +
+                  "' call set: '" + param_seq + "'",
+                  exprtk_error_location));
             }
 
             return false;
@@ -24585,13 +28565,12 @@ namespace exprtk
                {
                   invalid_state_ = false;
 
-                  parser_.
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   parser_.current_token(),
-                                   "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] +
-                                   "' for function: " + function_name_,
-                                   exprtk_error_location));
+                  parser_.set_error(make_error(
+                     parser_error::e_syntax,
+                     parser_.current_token(),
+                     "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] +
+                     "' for function: " + function_name_,
+                     exprtk_error_location));
                   return;
                }
 
@@ -24601,15 +28580,14 @@ namespace exprtk
                {
                   invalid_state_ = false;
 
-                  parser_.
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   parser_.current_token(),
-                                   "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
-                                   "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
-                                   "pseq_idx[" + details::to_str(i) + "] " +
-                                   "param seq: " + param_seq_list[i],
-                                   exprtk_error_location));
+                  parser_.set_error(make_error(
+                     parser_error::e_syntax,
+                     parser_.current_token(),
+                     "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
+                     "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
+                     "pseq_idx[" + details::to_str(i) + "] " +
+                     "param seq: " + param_seq_list[i],
+                     exprtk_error_location));
                   return;
                }
 
@@ -24617,8 +28595,8 @@ namespace exprtk
             }
          }
 
-         type_checker(const type_checker&);
-         type_checker& operator=(const type_checker&);
+         type_checker(const type_checker&) exprtk_delete;
+         type_checker& operator=(const type_checker&) exprtk_delete;
 
          bool invalid_state_;
          parser_t& parser_;
@@ -24637,15 +28615,19 @@ namespace exprtk
 
          std::string param_type_list;
 
-         type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
+         type_checker tc(
+            (*this),
+            function_name,
+            function->parameter_sequence,
+            type_checker::e_string);
 
          if (tc.invalid())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR123 - Type checker instantiation failure for generic function: " + function_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR136 - Type checker instantiation failure for generic function: " + function_name,
+               exprtk_error_location));
 
             return error_node();
          }
@@ -24659,12 +28641,12 @@ namespace exprtk
                     !tc       .allow_zero_parameters()
                   )
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR124 - Zero parameter call to generic function: "
-                                + function_name + " not allowed",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR137 - Zero parameter call to generic function: "
+                     + function_name + " not allowed",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -24691,11 +28673,11 @@ namespace exprtk
                      break;
                   else if (!token_is(token_t::e_comma))
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR125 - Expected ',' for call to generic function: " + function_name,
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR138 - Expected ',' for call to generic function: " + function_name,
+                        exprtk_error_location));
 
                      return error_node();
                   }
@@ -24708,12 +28690,12 @@ namespace exprtk
                    !tc      .allow_zero_parameters    ()
                  )
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR126 - Zero parameter call to generic function: "
-                          + function_name + " not allowed",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR139 - Zero parameter call to generic function: "
+               + function_name + " not allowed",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -24725,22 +28707,21 @@ namespace exprtk
               !tc.verify(param_type_list, param_seq_index)
             )
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name,
+               exprtk_error_location));
 
             return error_node();
          }
 
          expression_node_ptr result = error_node();
 
-         if (tc.paramseq_count() <= 1)
-            result = expression_generator_
-                       .generic_function_call(function, arg_list);
-         else
-            result = expression_generator_
+         result = (tc.paramseq_count() <= 1) ?
+                  expression_generator_
+                       .generic_function_call(function, arg_list) :
+                  expression_generator_
                        .generic_function_call(function, arg_list, param_seq_index);
 
          sdd.delete_ptr = (0 == result);
@@ -24763,12 +28744,12 @@ namespace exprtk
                     !tc       .allow_zero_parameters()
                   )
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR128 - Zero parameter call to generic function: "
-                                + function_name + " not allowed",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR141 - Zero parameter call to generic function: "
+                     + function_name + " not allowed",
+                     exprtk_error_location));
 
                   return false;
                }
@@ -24795,11 +28776,11 @@ namespace exprtk
                      break;
                   else if (!token_is(token_t::e_comma))
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR129 - Expected ',' for call to string function: " + function_name,
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR142 - Expected ',' for call to string function: " + function_name,
+                        exprtk_error_location));
 
                      return false;
                   }
@@ -24842,22 +28823,21 @@ namespace exprtk
 
          if (!tc.verify(param_type_list, param_seq_index))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR130 - Invalid input parameter sequence for call to string function: " + function_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR143 - Invalid input parameter sequence for call to string function: " + function_name,
+               exprtk_error_location));
 
             return error_node();
          }
 
          expression_node_ptr result = error_node();
 
-         if (tc.paramseq_count() <= 1)
-            result = expression_generator_
-                       .string_function_call(function, arg_list);
-         else
-            result = expression_generator_
+         result = (tc.paramseq_count() <= 1) ?
+                  expression_generator_
+                       .string_function_call(function, arg_list) :
+                  expression_generator_
                        .string_function_call(function, arg_list, param_seq_index);
 
          sdd.delete_ptr = (0 == result);
@@ -24894,11 +28874,11 @@ namespace exprtk
 
          if (!tc.verify(param_type_list, param_seq_index))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name,
+               exprtk_error_location));
 
             return error_node();
          }
@@ -24925,11 +28905,11 @@ namespace exprtk
          }
          else
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR132 - Invalid return type for call to overloaded function: " + function_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR145 - Invalid return type for call to overloaded function: " + function_name,
+               exprtk_error_location));
          }
 
          sdd.delete_ptr = (0 == result);
@@ -24953,11 +28933,11 @@ namespace exprtk
 
             if (!p.token_is(token_t::e_lbracket))
             {
-               p.set_error(
-                    make_error(parser_error::e_syntax,
-                               p.current_token(),
-                               "ERR133 - Expected '(' for special function '" + sf_name + "'",
-                               exprtk_error_location));
+               p.set_error(make_error(
+                  parser_error::e_syntax,
+                  p.current_token(),
+                  "ERR146 - Expected '(' for special function '" + sf_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -24974,11 +28954,11 @@ namespace exprtk
                {
                   if (!p.token_is(token_t::e_comma))
                   {
-                     p.set_error(
-                          make_error(parser_error::e_syntax,
-                                     p.current_token(),
-                                     "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'",
-                                     exprtk_error_location));
+                     p.set_error(make_error(
+                        parser_error::e_syntax,
+                        p.current_token(),
+                        "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'",
+                        exprtk_error_location));
 
                      return p.error_node();
                   }
@@ -24987,11 +28967,11 @@ namespace exprtk
 
             if (!p.token_is(token_t::e_rbracket))
             {
-               p.set_error(
-                    make_error(parser_error::e_syntax,
-                               p.current_token(),
-                               "ERR135 - Invalid number of parameters for special function '" + sf_name + "'",
-                               exprtk_error_location));
+               p.set_error(make_error(
+                  parser_error::e_syntax,
+                  p.current_token(),
+                  "ERR148 - Invalid number of parameters for special function '" + sf_name + "'",
+                  exprtk_error_location));
 
                return p.error_node();
             }
@@ -25014,11 +28994,11 @@ namespace exprtk
               !details::is_digit(sf_name[3])
             )
          {
-            set_error(
-               make_error(parser_error::e_token,
-                          current_token(),
-                          "ERR136 - Invalid special function[1]: " + sf_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_token,
+               current_token(),
+               "ERR149 - Invalid special function[1]: " + sf_name,
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25028,11 +29008,11 @@ namespace exprtk
 
          if (id >= details::e_sffinal)
          {
-            set_error(
-               make_error(parser_error::e_token,
-                          current_token(),
-                          "ERR137 - Invalid special function[2]: " + sf_name,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_token,
+               current_token(),
+               "ERR150 - Invalid special function[2]: " + sf_name,
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25060,21 +29040,21 @@ namespace exprtk
       {
          if (state_.parsing_break_stmt)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR138 - Invoking 'break' within a break call is not allowed",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR151 - Invoking 'break' within a break call is not allowed",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (0 == state_.parsing_loop_stmt_count)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR152 - Invalid use of 'break', allowed only in the scope of a loop",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25093,23 +29073,23 @@ namespace exprtk
             {
                if (0 == (return_expr = parse_expression()))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR140 - Failed to parse return expression for 'break' statement",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR153 - Failed to parse return expression for 'break' statement",
+                     exprtk_error_location));
 
                   return error_node();
                }
                else if (!token_is(token_t::e_rsqrbracket))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR141 - Expected ']' at the completion of break's return expression",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR154 - Expected ']' at the completion of break's return expression",
+                     exprtk_error_location));
 
-                  free_node(node_allocator_,return_expr);
+                  free_node(node_allocator_, return_expr);
 
                   return error_node();
                }
@@ -25121,11 +29101,11 @@ namespace exprtk
          }
          else
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR142 - Invalid use of 'break', allowed only in the scope of a loop",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR155 - Invalid use of 'break', allowed only in the scope of a loop",
+               exprtk_error_location));
          }
 
          return error_node();
@@ -25135,11 +29115,11 @@ namespace exprtk
       {
          if (0 == state_.parsing_loop_stmt_count)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25157,123 +29137,222 @@ namespace exprtk
 
       inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
       {
-         expression_node_ptr size_expr = error_node();
+         expression_node_ptr size_expression_node = error_node();
 
          if (!token_is(token_t::e_lsqrbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR144 - Expected '[' as part of vector size definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR157 - Expected '[' as part of vector size definition",
+               exprtk_error_location));
 
             return error_node();
          }
-         else if (0 == (size_expr = parse_expression()))
+         else if (0 == (size_expression_node = parse_expression()))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR145 - Failed to determine size of vector '" + vec_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR158 - Failed to determine size of vector '" + vec_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
-         else if (!is_constant_node(size_expr))
+         else if (!is_constant_node(size_expression_node))
          {
-            free_node(node_allocator_,size_expr);
+            const bool is_rebaseble_vector =
+               (size_expression_node->type() == details::expression_node<T>::e_vecsize) &&
+               static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable();
 
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR146 - Expected a literal number as size of vector '" + vec_name + "'",
-                          exprtk_error_location));
+            free_node(node_allocator_, size_expression_node);
+
+            const std::string error_msg = (is_rebaseble_vector) ?
+                                          std::string("Rebasable/Resizable vector cannot be used to define the size of vector") :
+                                          std::string("Expected a constant literal number as size of vector");
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR159 - " + error_msg + " '" + vec_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
 
-         const T vector_size = size_expr->value();
+         const T vector_size = size_expression_node->value();
 
-         free_node(node_allocator_,size_expr);
+         free_node(node_allocator_, size_expression_node);
 
-         const T max_vector_size = T(2000000000.0);
+         const std::size_t max_vector_size = settings_.max_local_vector_size();
 
          if (
               (vector_size <= T(0)) ||
               std::not_equal_to<T>()
               (T(0),vector_size - details::numeric::trunc(vector_size)) ||
-              (vector_size > max_vector_size)
+              (static_cast<std::size_t>(vector_size) > max_vector_size)
             )
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
-                          details::to_str(details::numeric::to_int32(vector_size)),
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR160 - Invalid vector size. Must be an integer in the "
+               "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " +
+               details::to_str(details::numeric::to_int32(vector_size)),
+               exprtk_error_location));
 
             return error_node();
          }
 
+         typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
+
+         const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
+
+         scope_element& se = sem_.get_element(vec_name);
+
+         if (se.name == vec_name)
+         {
+            if (se.active)
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR161 - Illegal redefinition of local vector: '" + vec_name + "'",
+                  exprtk_error_location));
+
+               return error_node();
+            }
+            else if (
+                      (se.size == vec_size) &&
+                      (scope_element::e_vector == se.type)
+                    )
+            {
+               vec_holder = se.vec_node;
+               se.active  = true;
+               se.depth   = state_.scope_depth;
+               se.ref_count++;
+            }
+         }
+
+         if (0 == vec_holder)
+         {
+            scope_element nse;
+            nse.name      = vec_name;
+            nse.active    = true;
+            nse.ref_count = 1;
+            nse.type      = scope_element::e_vector;
+            nse.depth     = state_.scope_depth;
+            nse.size      = vec_size;
+            nse.data      = new T[vec_size];
+            nse.vec_node  = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
+
+            details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size);
+
+            if (!sem_.add_element(nse))
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR162 - Failed to add new local vector '" + vec_name + "' to SEM",
+                  exprtk_error_location));
+
+               sem_.free_element(nse);
+
+               return error_node();
+            }
+
+            vec_holder = nse.vec_node;
+
+            exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
+                          nse.name.c_str(),
+                          static_cast<int>(nse.size)));
+         }
+
+         state_.activate_side_effect("parse_define_vector_statement()");
+
+         lodge_symbol(vec_name, e_st_local_vector);
+
          std::vector<expression_node_ptr> vec_initilizer_list;
 
          scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
 
          bool single_value_initialiser = false;
+         bool range_value_initialiser  = false;
          bool vec_to_vec_initialiser   = false;
          bool null_initialisation      = false;
 
          if (!token_is(token_t::e_rsqrbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR148 - Expected ']' as part of vector size definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR163 - Expected ']' as part of vector size definition",
+               exprtk_error_location));
 
             return error_node();
          }
-         else if (!token_is(token_t::e_eof))
+         else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold))
          {
             if (!token_is(token_t::e_assign))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR149 - Expected ':=' as part of vector definition",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR164 - Expected ':=' as part of vector definition",
+                  exprtk_error_location));
 
                return error_node();
             }
             else if (token_is(token_t::e_lsqrbracket))
             {
-               expression_node_ptr initialiser = parse_expression();
+               expression_node_ptr initialiser_component = parse_expression();
 
-               if (0 == initialiser)
+               if (0 == initialiser_component)
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR150 - Failed to parse single vector initialiser",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR165 - Failed to parse first component of vector initialiser for vector: " + vec_name,
+                     exprtk_error_location));
 
                   return error_node();
                }
 
-               vec_initilizer_list.push_back(initialiser);
+               vec_initilizer_list.push_back(initialiser_component);
+
+               if (token_is(token_t::e_colon))
+               {
+                  initialiser_component = parse_expression();
+
+                  if (0 == initialiser_component)
+                  {
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR166 - Failed to parse second component of vector initialiser for vector: " + vec_name,
+                        exprtk_error_location));
+
+                     return error_node();
+                  }
+
+                  vec_initilizer_list.push_back(initialiser_component);
+               }
 
                if (!token_is(token_t::e_rsqrbracket))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR151 - Expected ']' to close single value vector initialiser",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR167 - Expected ']' to close single value vector initialiser",
+                     exprtk_error_location));
 
                   return error_node();
                }
 
-               single_value_initialiser = true;
+               switch (vec_initilizer_list.size())
+               {
+                  case 1 : single_value_initialiser = true; break;
+                  case 2 : range_value_initialiser  = true; break;
+               }
             }
             else if (!token_is(token_t::e_lcrlbracket))
             {
@@ -25283,9 +29362,9 @@ namespace exprtk
                if (token_t::e_symbol == current_token().type)
                {
                   // Is it a locally defined vector?
-                  const scope_element& se = sem_.get_active_element(current_token().value);
+                  const scope_element& lcl_se = sem_.get_active_element(current_token().value);
 
-                  if (scope_element::e_vector == se.type)
+                  if (scope_element::e_vector == lcl_se.type)
                   {
                      if (0 != (initialiser = parse_expression()))
                         vec_initilizer_list.push_back(initialiser);
@@ -25311,11 +29390,11 @@ namespace exprtk
                {
                   if (0 == initialiser)
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR152 - Expected '{' as part of vector initialiser list",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR168 - Expected '{' as part of vector initialiser list",
+                        exprtk_error_location));
 
                      return error_node();
                   }
@@ -25331,11 +29410,11 @@ namespace exprtk
 
                   if (0 == initialiser)
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR153 - Expected '{' as part of vector initialiser list",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR169 - Expected '{' as part of vector initialiser list",
+                        exprtk_error_location));
 
                      return error_node();
                   }
@@ -25349,11 +29428,11 @@ namespace exprtk
 
                   if (!token_is(token_t::e_comma) && is_next_close)
                   {
-                     set_error(
-                        make_error(parser_error::e_syntax,
-                                   current_token(),
-                                   "ERR154 - Expected ',' between vector initialisers",
-                                   exprtk_error_location));
+                     set_error(make_error(
+                        parser_error::e_syntax,
+                        current_token(),
+                        "ERR170 - Expected ',' between vector initialisers",
+                        exprtk_error_location));
 
                      return error_node();
                   }
@@ -25369,99 +29448,118 @@ namespace exprtk
                  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
                )
             {
-               if (!token_is(token_t::e_eof))
+               if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR155 - Expected ';' at end of vector definition",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR171 - Expected ';' at end of vector definition",
+                     exprtk_error_location));
 
                   return error_node();
                }
             }
 
-            if (vec_initilizer_list.size() > vector_size)
+            if (
+                 !single_value_initialiser &&
+                 !range_value_initialiser  &&
+                 (T(vec_initilizer_list.size()) > vector_size)
+               )
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR172 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
          }
 
-         typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
-
-         const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
-
-         scope_element& se = sem_.get_element(vec_name);
+         expression_node_ptr result = error_node();
 
-         if (se.name == vec_name)
+         if (
+              (vec_initilizer_list.size() == 1) &&
+              single_value_initialiser
+            )
          {
-            if (se.active)
+            if (details::is_constant_node(vec_initilizer_list[0]))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'",
-                             exprtk_error_location));
-
-               return error_node();
+              // vector_init_zero_value_node   var v[10] := [0]
+               if (T(0) == vec_initilizer_list[0]->value())
+               {
+                  result = node_allocator_
+                              .allocate<details::vector_init_zero_value_node<T> >(
+                                 (*vec_holder)[0],
+                                 vec_size,
+                                 vec_initilizer_list);
+               }
+               else
+               {
+                  // vector_init_single_constvalue_node   var v[10] := [123]
+                  result = node_allocator_
+                              .allocate<details::vector_init_single_constvalue_node<T> >(
+                                 (*vec_holder)[0],
+                                 vec_size,
+                                 vec_initilizer_list);
+               }
             }
-            else if (
-                      (se.size == vec_size) &&
-                      (scope_element::e_vector == se.type)
-                    )
+            else
             {
-               vec_holder = se.vec_node;
-               se.active  = true;
-               se.depth   = state_.scope_depth;
-               se.ref_count++;
+               // vector_init_single_value_node   var v[10] := [123 + (x / y)]
+               result = node_allocator_
+                           .allocate<details::vector_init_single_value_node<T> >(
+                              (*vec_holder)[0],
+                              vec_size,
+                              vec_initilizer_list);
             }
          }
-
-         if (0 == vec_holder)
+         else if (
+                   (vec_initilizer_list.size() == 2) &&
+                   range_value_initialiser
+                 )
          {
-            scope_element nse;
-            nse.name      = vec_name;
-            nse.active    = true;
-            nse.ref_count = 1;
-            nse.type      = scope_element::e_vector;
-            nse.depth     = state_.scope_depth;
-            nse.size      = vec_size;
-            nse.data      = new T[vec_size];
-            nse.vec_node  = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
+            bool base_const = details::is_constant_node(vec_initilizer_list[0]);
+            bool inc_const  = details::is_constant_node(vec_initilizer_list[1]);
 
-            if (!sem_.add_element(nse))
+            if (base_const && inc_const)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM",
-                             exprtk_error_location));
-
-               sem_.free_element(nse);
-
-               return error_node();
+               // vector_init_single_value_node   var v[10] := [1 : 3.5]
+               result = node_allocator_
+                           .allocate<details::vector_init_iota_constconst_node<T> >(
+                              (*vec_holder)[0],
+                              vec_size,
+                              vec_initilizer_list);
+            }
+            else if (base_const && !inc_const)
+            {
+               // vector_init_single_value_node   var v[10] := [1 : x + y]
+               result = node_allocator_
+                           .allocate<details::vector_init_iota_constnconst_node<T> >(
+                              (*vec_holder)[0],
+                              vec_size,
+                              vec_initilizer_list);
+            }
+            else if (!base_const && inc_const)
+            {
+               // vector_init_single_value_node   var v[10] := [x + y : 3]
+               result = node_allocator_
+                           .allocate<details::vector_init_iota_nconstconst_node<T> >(
+                              (*vec_holder)[0],
+                              vec_size,
+                              vec_initilizer_list);
+            }
+            else if (!base_const && !inc_const)
+            {
+               // vector_init_single_value_node   var v[10] := [x + y :  z / w]
+               result = node_allocator_
+                           .allocate<details::vector_init_iota_nconstnconst_node<T> >(
+                              (*vec_holder)[0],
+                              vec_size,
+                              vec_initilizer_list);
             }
-
-            vec_holder = nse.vec_node;
-
-            exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
-                          nse.name.c_str(),
-                          static_cast<int>(nse.size)));
          }
-
-         state_.activate_side_effect("parse_define_vector_statement()");
-
-         lodge_symbol(vec_name, e_st_local_vector);
-
-         expression_node_ptr result = error_node();
-
-         if (null_initialisation)
+         else if (null_initialisation)
             result = expression_generator_(T(0.0));
          else if (vec_to_vec_initialiser)
          {
@@ -25473,16 +29571,31 @@ namespace exprtk
                         vec_initilizer_list[0]);
          }
          else
+         {
             result = node_allocator_
-                        .allocate<details::vector_assignment_node<T> >(
+                        .allocate<details::vector_initialisation_node<T> >(
                            (*vec_holder)[0],
                            vec_size,
                            vec_initilizer_list,
                            single_value_initialiser);
+         }
 
-         svd.delete_ptr = (0 == result);
+         svd.delete_ptr = false;
 
-         return result;
+         if (result && result->valid())
+         {
+            return result;
+         }
+
+         details::free_node(node_allocator_, result);
+
+         set_error(make_error(
+            parser_error::e_synthesis,
+            current_token(),
+            "ERR173 - Failed to generate initialisation node for vector: " + vec_name,
+            exprtk_error_location));
+
+         return error_node();
       }
 
       #ifndef exprtk_disable_string_capabilities
@@ -25496,13 +29609,13 @@ namespace exprtk
          {
             if (se.active)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR159 - Illegal redefinition of local variable: '" + str_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR174 - Illegal redefinition of local variable: '" + str_name + "'",
+                  exprtk_error_location));
 
-               free_node(node_allocator_,initialisation_expression);
+               free_node(node_allocator_, initialisation_expression);
 
                return error_node();
             }
@@ -25528,13 +29641,13 @@ namespace exprtk
 
             if (!sem_.add_element(nse))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR175 - Failed to add new local string variable '" + str_name + "' to SEM",
+                  exprtk_error_location));
 
-               free_node(node_allocator_,initialisation_expression);
+               free_node(node_allocator_, initialisation_expression);
 
                sem_.free_element(nse);
 
@@ -25543,7 +29656,7 @@ namespace exprtk
 
             str_node = nse.str_node;
 
-            exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
+            exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str()));
          }
 
          lodge_symbol(str_name, e_st_local_string);
@@ -25574,11 +29687,11 @@ namespace exprtk
       {
          if (settings_.vardef_disabled())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR161 - Illegal variable definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR176 - Illegal variable definition",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25595,41 +29708,41 @@ namespace exprtk
 
          if (!token_is(token_t::e_symbol))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR162 - Expected a symbol for variable definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR177 - Expected a symbol for variable definition",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (details::is_reserved_symbol(var_name))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR178 - Illegal redefinition of reserved keyword: '" + var_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (symtab_store_.symbol_exists(var_name))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR164 - Illegal redefinition of variable '" + var_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR179 - Illegal redefinition of variable '" + var_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (local_variable_is_shadowed(var_name))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR180 - Illegal redefinition of local variable: '" + var_name + "'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25645,11 +29758,11 @@ namespace exprtk
          {
             if (0 == (initialisation_expression = parse_expression()))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR166 - Failed to parse initialisation expression",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR181 - Failed to parse initialisation expression for variable '" + var_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -25663,13 +29776,13 @@ namespace exprtk
          {
             if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR167 - Expected ';' after variable definition",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR182 - Expected ';' after variable '" + var_name + "' definition",
+                  exprtk_error_location));
 
-               free_node(node_allocator_,initialisation_expression);
+               free_node(node_allocator_, initialisation_expression);
 
                return error_node();
             }
@@ -25691,11 +29804,11 @@ namespace exprtk
          {
             if (se.active)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR168 - Illegal redefinition of local variable: '" + var_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR183 - Illegal redefinition of local variable: '" + var_name + "'",
+                  exprtk_error_location));
 
                free_node(node_allocator_, initialisation_expression);
 
@@ -25723,11 +29836,11 @@ namespace exprtk
 
             if (!sem_.add_element(nse))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR169 - Failed to add new local variable '" + var_name + "' to SEM",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR184 - Failed to add new local variable '" + var_name + "' to SEM",
+                  exprtk_error_location));
 
                free_node(node_allocator_, initialisation_expression);
 
@@ -25738,7 +29851,7 @@ namespace exprtk
 
             var_node = nse.var_node;
 
-            exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
+            exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str()));
          }
 
          state_.activate_side_effect("parse_define_var_statement()");
@@ -25753,6 +29866,174 @@ namespace exprtk
          return expression_generator_(details::e_assign,branch);
       }
 
+      inline expression_node_ptr parse_define_constvar_statement()
+      {
+         if (settings_.vardef_disabled())
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR185 - Illegal const variable definition",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (!token_is("const"))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR186 - Expected 'const' keyword for const-variable definition",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (!token_is("var"))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR187 - Expected 'var' keyword for const-variable definition",
+               exprtk_error_location));
+
+            return error_node();
+         }
+
+         const std::string var_name = current_token().value;
+
+         expression_node_ptr initialisation_expression = error_node();
+
+         if (!token_is(token_t::e_symbol))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR188 - Expected a symbol for const-variable definition",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (details::is_reserved_symbol(var_name))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR189 - Illegal redefinition of reserved keyword: '" + var_name + "'",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (symtab_store_.symbol_exists(var_name))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR190 - Illegal redefinition of variable '" + var_name + "'",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (local_variable_is_shadowed(var_name))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR191 - Illegal redefinition of local variable: '" + var_name + "'",
+               exprtk_error_location));
+
+            return error_node();
+         }
+         else if (token_is(token_t::e_assign))
+         {
+            if (0 == (initialisation_expression = parse_expression()))
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR192 - Failed to parse initialisation expression for const-variable: '" + var_name + "'",
+                  exprtk_error_location));
+
+               return error_node();
+            }
+            else if (!details::is_literal_node(initialisation_expression))
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR193 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal",
+                  exprtk_error_location));
+
+               free_node(node_allocator_, initialisation_expression);
+
+               return error_node();
+            }
+         }
+
+         const T init_value = initialisation_expression->value();
+
+         free_node(node_allocator_, initialisation_expression);
+
+         expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
+
+         scope_element& se = sem_.get_element(var_name);
+
+         if (se.name == var_name)
+         {
+            if (se.active)
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR194 - Illegal redefinition of local variable: '" + var_name + "'",
+                  exprtk_error_location));
+
+               return error_node();
+            }
+            else if (scope_element::e_literal == se.type)
+            {
+               var_node  = se.var_node;
+               se.active = true;
+               se.depth  = state_.scope_depth;
+               se.ref_count++;
+            }
+         }
+
+         if (0 == var_node)
+         {
+            scope_element nse;
+            nse.name      = var_name;
+            nse.active    = true;
+            nse.ref_count = 1;
+            nse.type      = scope_element::e_literal;
+            nse.depth     = state_.scope_depth;
+            nse.data      = 0;
+            nse.var_node  = node_allocator_.allocate<literal_node_t>(init_value);
+
+            if (!sem_.add_element(nse))
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR195 - Failed to add new local const-variable '" + var_name + "' to SEM",
+                  exprtk_error_location));
+
+               sem_.free_element(nse);
+
+               return error_node();
+            }
+
+            var_node = nse.var_node;
+
+            exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str()));
+         }
+
+         state_.activate_side_effect("parse_define_constvar_statement()");
+
+         lodge_symbol(var_name, e_st_local_variable);
+
+         return expression_generator_(var_node->value());
+      }
+
       inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
       {
          if (
@@ -25760,21 +30041,21 @@ namespace exprtk
               !token_is(token_t::e_rcrlbracket)
             )
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR170 - Expected a '{}' for uninitialised var definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR196 - Expected a '{}' for uninitialised var definition",
+               exprtk_error_location));
 
             return error_node();
          }
          else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR171 - Expected ';' after uninitialised variable definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR197 - Expected ';' after uninitialised variable definition",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25787,11 +30068,11 @@ namespace exprtk
          {
             if (se.active)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR172 - Illegal redefinition of local variable: '" + var_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR198 - Illegal redefinition of local variable: '" + var_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -25817,11 +30098,11 @@ namespace exprtk
 
             if (!sem_.add_element(nse))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR173 - Failed to add new local variable '" + var_name + "' to SEM",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR199 - Failed to add new local variable '" + var_name + "' to SEM",
+                  exprtk_error_location));
 
                sem_.free_element(nse);
 
@@ -25850,11 +30131,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_lbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR174 - Expected '(' at start of swap statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR200 - Expected '(' at start of swap statement",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25869,11 +30150,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR175 - Expected a symbol for variable or vector element definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR201 - Expected a symbol for variable or vector element definition",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -25881,11 +30162,11 @@ namespace exprtk
          {
             if (0 == (variable0 = parse_vector()))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR202 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -25914,11 +30195,11 @@ namespace exprtk
 
             if (0 == variable0)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR203 - First parameter to swap is an invalid variable: '" + var0_name + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -25928,15 +30209,15 @@ namespace exprtk
 
          if (!token_is(token_t::e_comma))
          {
-            set_error(
-                make_error(parser_error::e_syntax,
-                           current_token(),
-                           "ERR178 - Expected ',' between parameters to swap",
-                           exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR204 - Expected ',' between parameters to swap",
+               exprtk_error_location));
 
             if (variable0_generated)
             {
-               free_node(node_allocator_,variable0);
+               free_node(node_allocator_, variable0);
             }
 
             return error_node();
@@ -25946,15 +30227,15 @@ namespace exprtk
 
          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR179 - Expected a symbol for variable or vector element definition",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR205 - Expected a symbol for variable or vector element definition",
+               exprtk_error_location));
 
             if (variable0_generated)
             {
-               free_node(node_allocator_,variable0);
+               free_node(node_allocator_, variable0);
             }
 
             return error_node();
@@ -25963,15 +30244,15 @@ namespace exprtk
          {
             if (0 == (variable1 = parse_vector()))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR206 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
+                  exprtk_error_location));
 
                if (variable0_generated)
                {
-                  free_node(node_allocator_,variable0);
+                  free_node(node_allocator_, variable0);
                }
 
                return error_node();
@@ -26001,15 +30282,15 @@ namespace exprtk
 
             if (0 == variable1)
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR207 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
+                  exprtk_error_location));
 
                if (variable0_generated)
                {
-                  free_node(node_allocator_,variable0);
+                  free_node(node_allocator_, variable0);
                }
 
                return error_node();
@@ -26020,20 +30301,20 @@ namespace exprtk
 
          if (!token_is(token_t::e_rbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR182 - Expected ')' at end of swap statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR208 - Expected ')' at end of swap statement",
+               exprtk_error_location));
 
             if (variable0_generated)
             {
-               free_node(node_allocator_,variable0);
+               free_node(node_allocator_, variable0);
             }
 
             if (variable1_generated)
             {
-               free_node(node_allocator_,variable1);
+               free_node(node_allocator_, variable1);
             }
 
             return error_node();
@@ -26055,12 +30336,12 @@ namespace exprtk
 
             if (variable0_generated)
             {
-               free_node(node_allocator_,variable0);
+               free_node(node_allocator_, variable0);
             }
 
             if (variable1_generated)
             {
-               free_node(node_allocator_,variable1);
+               free_node(node_allocator_, variable1);
             }
          }
          else
@@ -26077,11 +30358,11 @@ namespace exprtk
       {
          if (state_.parsing_return_stmt)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR183 - Return call within a return call is not allowed",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR209 - Return call within a return call is not allowed",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -26101,11 +30382,11 @@ namespace exprtk
 
          if (!token_is(token_t::e_lsqrbracket))
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR184 - Expected '[' at start of return statement",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR210 - Expected '[' at start of return statement",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -26124,11 +30405,11 @@ namespace exprtk
                   break;
                else if (!token_is(token_t::e_comma))
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR185 - Expected ',' between values during call to return",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR211 - Expected ',' between values during call to return",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26136,11 +30417,11 @@ namespace exprtk
          }
          else if (settings_.zero_return_disabled())
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR186 - Zero parameter return statement not allowed",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR212 - Zero parameter return statement not allowed",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -26151,11 +30432,11 @@ namespace exprtk
          {
             if (!arg_list.empty())
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             prev_token,
-                             "ERR187 - Invalid ']' found during return call",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  prev_token,
+                  "ERR213 - Invalid ']' found during return call",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -26194,6 +30475,194 @@ namespace exprtk
       }
       #endif
 
+      inline expression_node_ptr parse_assert_statement()
+      {
+         assert(details::imatch(current_token().value, "assert"));
+
+         if (state_.parsing_assert_stmt)
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR214 - Assert statement within an assert statement is not allowed",
+               exprtk_error_location));
+
+            return error_node();
+         }
+
+         scoped_bool_negator sbn(state_.parsing_assert_stmt);
+
+         next_token();
+
+         std::vector<expression_node_ptr> assert_arg_list(3, error_node());
+         scoped_vec_delete<expression_node_t> sdd((*this), assert_arg_list);
+
+         expression_node_ptr& assert_condition = assert_arg_list[0];
+         expression_node_ptr& assert_message   = assert_arg_list[1];
+         expression_node_ptr& assert_id        = assert_arg_list[2];
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR215 - Expected '(' at start of assert statement",
+               exprtk_error_location));
+
+            return error_node();
+         }
+
+         const token_t start_token = current_token();
+
+         // Parse the assert condition
+         if (0 == (assert_condition = parse_expression()))
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR216 - Failed to parse condition for assert statement",
+               exprtk_error_location));
+
+            return error_node();
+         }
+
+         const token_t end_token = current_token();
+
+         if (!token_is(token_t::e_rbracket))
+         {
+            if (!token_is(token_t::e_comma))
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR217 - Expected ',' between condition and message for assert statement",
+                  exprtk_error_location));
+
+               return error_node();
+            }
+            // Parse the assert message
+            else if (
+                      (0 == (assert_message = parse_expression())) ||
+                      !details::is_generally_string_node(assert_message)
+                    )
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR218 - " +
+                  (assert_message ?
+                  std::string("Expected string for assert message") :
+                  std::string("Failed to parse message for assert statement")),
+                  exprtk_error_location));
+
+               return error_node();
+            }
+            else if (!token_is(token_t::e_rbracket))
+            {
+               if (!token_is(token_t::e_comma))
+               {
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR219 - Expected ',' between message and ID for assert statement",
+                     exprtk_error_location));
+
+                  return error_node();
+               }
+               // Parse assert ID
+               else if (
+                         (0 == (assert_id = parse_expression())) ||
+                         !details::is_const_string_node(assert_id)
+                       )
+               {
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR220 - " +
+                     (assert_id ?
+                     std::string("Expected literal string for assert ID") :
+                     std::string("Failed to parse string for assert ID")),
+                     exprtk_error_location));
+
+                  return error_node();
+               }
+               else if (!token_is(token_t::e_rbracket))
+               {
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR221 - Expected ')' at start of assert statement",
+                     exprtk_error_location));
+
+                  return error_node();
+               }
+            }
+         }
+
+         exprtk::assert_check::assert_context context;
+         context.condition = lexer().substr(start_token.position, end_token.position);
+         context.offet     = start_token.position;
+
+         if (0 == assert_check_)
+         {
+            exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n",
+                          context.condition.c_str()));
+
+            return new details::null_node<T>();
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         if (assert_message && details::is_const_string_node(assert_message))
+         {
+            context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str();
+         }
+
+         if (assert_id && details::is_const_string_node(assert_id))
+         {
+            context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str();
+
+            if (assert_ids_.end() != assert_ids_.find(context.id))
+            {
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR222 - Duplicate assert ID: " + context.id,
+                  exprtk_error_location));
+
+               return error_node();
+            }
+
+            assert_ids_.insert(context.id);
+            free_node(node_allocator_, assert_id);
+         }
+         #endif
+
+         expression_node_ptr result_node =
+            expression_generator_.assert_call(
+               assert_condition,
+               assert_message,
+               context);
+
+         exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str()      ));
+         exprtk_debug(("parse_assert_statement() - assert message:   [%s]\n", context.message  .c_str()      ));
+         exprtk_debug(("parse_assert_statement() - assert id:        [%s]\n", context.id       .c_str()      ));
+         exprtk_debug(("parse_assert_statement() - assert offset:    [%d]\n", static_cast<int>(context.offet)));
+
+         if (0 == result_node)
+         {
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR223 - Failed to synthesize assert",
+               exprtk_error_location));
+
+            return error_node();
+         }
+
+         sdd.delete_ptr = false;
+         return result_node;
+      }
+
       inline bool post_variable_process(const std::string& symbol)
       {
          if (
@@ -26204,11 +30673,11 @@ namespace exprtk
          {
             if (!settings_.commutative_check_enabled())
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR224 - Invalid sequence of variable '" + symbol + "' and bracket",
+                  exprtk_error_location));
 
                return false;
             }
@@ -26223,26 +30692,29 @@ namespace exprtk
       {
          bool implied_mul = false;
 
-         if (is_generally_string_node(branch))
+         if (details::is_generally_string_node(branch))
+            return true;
+
+         if (details::is_ivector_node(branch))
             return true;
 
          const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
 
          switch (token)
          {
-            case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
-                                                        token_is(token_t::e_lcrlbracket,hold) ||
-                                                        token_is(token_t::e_lsqrbracket,hold) ;
+            case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   , hold) ||
+                                                        token_is(token_t::e_lcrlbracket, hold) ||
+                                                        token_is(token_t::e_lsqrbracket, hold) ;
                                           break;
 
-            case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
-                                                        token_is(token_t::e_lcrlbracket,hold) ||
-                                                        token_is(token_t::e_lsqrbracket,hold) ;
+            case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   , hold) ||
+                                                        token_is(token_t::e_lcrlbracket, hold) ||
+                                                        token_is(token_t::e_lsqrbracket, hold) ;
                                           break;
 
-            case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
-                                                        token_is(token_t::e_lcrlbracket,hold) ||
-                                                        token_is(token_t::e_lsqrbracket,hold) ;
+            case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   , hold) ||
+                                                        token_is(token_t::e_lcrlbracket, hold) ||
+                                                        token_is(token_t::e_lsqrbracket, hold) ;
                                           break;
 
             default                     : return true;
@@ -26252,11 +30724,11 @@ namespace exprtk
          {
             if (!settings_.commutative_check_enabled())
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR189 - Invalid sequence of brackets",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR225 - Invalid sequence of brackets",
+                  exprtk_error_location));
 
                return false;
             }
@@ -26271,27 +30743,65 @@ namespace exprtk
          return true;
       }
 
+      typedef typename interval_container_t<const void*>::interval_t interval_t;
+      typedef interval_container_t<const void*> immutable_memory_map_t;
+      typedef std::map<interval_t,token_t> immutable_symtok_map_t;
+
+      inline interval_t make_memory_range(const T& t)
+      {
+         const T* begin = reinterpret_cast<const T*>(&t);
+         const T* end   = begin + 1;
+         return interval_t(begin, end);
+      }
+
+      inline interval_t make_memory_range(const T* begin, const std::size_t size)
+      {
+         return interval_t(begin, begin + size);
+      }
+
+      inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size)
+      {
+         return interval_t(begin, begin + size);
+      }
+
+      void lodge_immutable_symbol(const lexer::token& token, const interval_t interval)
+      {
+         immutable_memory_map_.add_interval(interval);
+         immutable_symtok_map_[interval] = token;
+      }
+
       inline expression_node_ptr parse_symtab_symbol()
       {
          const std::string symbol = current_token().value;
 
          // Are we dealing with a variable or a special constant?
-         expression_node_ptr variable = symtab_store_.get_variable(symbol);
+         typedef typename symtab_store::variable_context var_ctxt_t;
+         var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol);
 
-         if (variable)
+         if (var_ctx.variable)
          {
+            assert(var_ctx.symbol_table);
+
+            expression_node_ptr result_variable = var_ctx.variable;
+
             if (symtab_store_.is_constant_node(symbol))
             {
-               variable = expression_generator_(variable->value());
+               result_variable = expression_generator_(var_ctx.variable->value());
+            }
+            else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability())
+            {
+               lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref()));
+               result_variable = var_ctx.variable;
             }
 
             if (!post_variable_process(symbol))
                return error_node();
 
             lodge_symbol(symbol, e_st_variable);
+
             next_token();
 
-            return variable;
+            return result_variable;
          }
 
          // Are we dealing with a locally defined variable, vector or string?
@@ -26301,7 +30811,10 @@ namespace exprtk
 
             if (se.active && details::imatch(se.name, symbol))
             {
-               if (scope_element::e_variable == se.type)
+               if (
+                    (scope_element::e_variable == se.type) ||
+                    (scope_element::e_literal  == se.type)
+                  )
                {
                   se.active = true;
                   lodge_symbol(symbol, e_st_local_variable);
@@ -26311,7 +30824,9 @@ namespace exprtk
 
                   next_token();
 
-                  return se.var_node;
+                  return (scope_element::e_variable == se.type) ?
+                           se.var_node :
+                           expression_generator_(se.var_node->value());
                }
                else if (scope_element::e_vector == se.type)
                {
@@ -26349,11 +30864,11 @@ namespace exprtk
                   return func_node;
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR190 - Failed to generate node for function: '" + symbol + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR226 - Failed to generate node for function: '" + symbol + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26375,11 +30890,11 @@ namespace exprtk
                   return vararg_func_node;
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR191 - Failed to generate node for vararg function: '" + symbol + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR227 - Failed to generate node for vararg function: '" + symbol + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26401,11 +30916,11 @@ namespace exprtk
                   return genericfunc_node;
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR192 - Failed to generate node for generic function: '" + symbol + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR228 - Failed to generate node for generic function: '" + symbol + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26428,11 +30943,11 @@ namespace exprtk
                   return stringfunc_node;
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR193 - Failed to generate node for string function: '" + symbol + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR229 - Failed to generate node for string function: '" + symbol + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26454,11 +30969,11 @@ namespace exprtk
                   return overloadfunc_node;
                else
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR194 - Failed to generate node for overload function: '" + symbol + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR230 - Failed to generate node for overload function: '" + symbol + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26480,11 +30995,11 @@ namespace exprtk
                     !details::is_base_function(symbol)
                   )
                {
-                  set_error(
-                     make_error(parser_error::e_syntax,
-                                current_token(),
-                                "ERR195 - Invalid use of reserved symbol '" + symbol + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_syntax,
+                     current_token(),
+                     "ERR231 - Invalid use of reserved symbol '" + symbol + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26511,11 +31026,13 @@ namespace exprtk
 
                      switch (usr_symbol_type)
                      {
-                        case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
-                                                                            break;
+                        case unknown_symbol_resolver::e_usr_variable_type :
+                           create_result = symtab.create_variable(symbol, default_value);
+                           break;
 
-                        case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
-                                                                            break;
+                        case unknown_symbol_resolver::e_usr_constant_type :
+                           create_result = symtab.add_constant(symbol, default_value);
+                           break;
 
                         default                                           : create_result = false;
                      }
@@ -26543,12 +31060,12 @@ namespace exprtk
                      }
                   }
 
-                  set_error(
-                     make_error(parser_error::e_symtab,
-                                current_token(),
-                                "ERR196 - Failed to create variable: '" + symbol + "'" +
-                                (error_message.empty() ? "" : " - " + error_message),
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_symtab,
+                     current_token(),
+                     "ERR232 - Failed to create variable: '" + symbol + "'" +
+                     (error_message.empty() ? "" : " - " + error_message),
+                     exprtk_error_location));
 
                }
                else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
@@ -26563,27 +31080,51 @@ namespace exprtk
                      }
                   }
 
-                  set_error(
-                     make_error(parser_error::e_symtab,
-                                current_token(),
-                                "ERR197 - Failed to resolve symbol: '" + symbol + "'" +
-                                (error_message.empty() ? "" : " - " + error_message),
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_symtab,
+                     current_token(),
+                     "ERR233 - Failed to resolve symbol: '" + symbol + "'" +
+                     (error_message.empty() ? "" : " - " + error_message),
+                     exprtk_error_location));
                }
 
                return error_node();
             }
          }
 
-         set_error(
-            make_error(parser_error::e_syntax,
-                       current_token(),
-                       "ERR198 - Undefined symbol: '" + symbol + "'",
-                       exprtk_error_location));
+         set_error(make_error(
+            parser_error::e_syntax,
+            current_token(),
+            "ERR234 - Undefined symbol: '" + symbol + "'",
+            exprtk_error_location));
 
          return error_node();
       }
 
+      inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression)
+      {
+         if (
+              expression &&
+              (
+                (current_token().type == token_t::e_symbol) ||
+                (current_token().type == token_t::e_number)
+              )
+            )
+         {
+            free_node(node_allocator_, expression);
+
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR235 - Invalid syntax '" + current_token().value  + "' possible missing operator or context",
+               exprtk_error_location));
+
+               return error_node();
+         }
+
+         return expression;
+      }
+
       inline expression_node_ptr parse_symbol()
       {
          static const std::string symbol_if       = "if"      ;
@@ -26595,103 +31136,116 @@ namespace exprtk
          static const std::string symbol_break    = "break"   ;
          static const std::string symbol_continue = "continue";
          static const std::string symbol_var      = "var"     ;
+         static const std::string symbol_const    = "const"   ;
          static const std::string symbol_swap     = "swap"    ;
          static const std::string symbol_return   = "return"  ;
          static const std::string symbol_not      = "not"     ;
+         static const std::string symbol_assert   = "assert"  ;
 
-         if (valid_vararg_operation(current_token().value))
+         const std::string symbol = current_token().value;
+
+         if (valid_vararg_operation(symbol))
          {
             return parse_vararg_function();
          }
-         else if (details::imatch(current_token().value, symbol_not))
+         else if (details::imatch(symbol, symbol_not))
          {
             return parse_not_statement();
          }
-         else if (valid_base_operation(current_token().value))
+         else if (valid_base_operation(symbol))
          {
             return parse_base_operation();
          }
          else if (
-                   details::imatch(current_token().value, symbol_if) &&
-                   settings_.control_struct_enabled(current_token().value)
+                   details::imatch(symbol, symbol_if) &&
+                   settings_.control_struct_enabled(symbol)
                  )
          {
             return parse_conditional_statement();
          }
          else if (
-                   details::imatch(current_token().value, symbol_while) &&
-                   settings_.control_struct_enabled(current_token().value)
+                   details::imatch(symbol, symbol_while) &&
+                   settings_.control_struct_enabled(symbol)
                  )
          {
-            return parse_while_loop();
+            return check_block_statement_closure(parse_while_loop());
          }
          else if (
-                   details::imatch(current_token().value, symbol_repeat) &&
-                   settings_.control_struct_enabled(current_token().value)
+                   details::imatch(symbol, symbol_repeat) &&
+                   settings_.control_struct_enabled(symbol)
                  )
          {
-            return parse_repeat_until_loop();
+            return check_block_statement_closure(parse_repeat_until_loop());
          }
          else if (
-                   details::imatch(current_token().value, symbol_for) &&
-                   settings_.control_struct_enabled(current_token().value)
+                   details::imatch(symbol, symbol_for) &&
+                   settings_.control_struct_enabled(symbol)
                  )
          {
-            return parse_for_loop();
+            return check_block_statement_closure(parse_for_loop());
          }
          else if (
-                   details::imatch(current_token().value, symbol_switch) &&
-                   settings_.control_struct_enabled(current_token().value)
+                   details::imatch(symbol, symbol_switch) &&
+                   settings_.control_struct_enabled(symbol)
                  )
          {
-            return parse_switch_statement();
+            return check_block_statement_closure(parse_switch_statement());
          }
-         else if (details::is_valid_sf_symbol(current_token().value))
+         else if (details::is_valid_sf_symbol(symbol))
          {
             return parse_special_function();
          }
-         else if (details::imatch(current_token().value, symbol_null))
+         else if (details::imatch(symbol, symbol_null))
          {
             return parse_null_statement();
          }
          #ifndef exprtk_disable_break_continue
-         else if (details::imatch(current_token().value, symbol_break))
+         else if (details::imatch(symbol, symbol_break))
          {
             return parse_break_statement();
          }
-         else if (details::imatch(current_token().value, symbol_continue))
+         else if (details::imatch(symbol, symbol_continue))
          {
             return parse_continue_statement();
          }
          #endif
-         else if (details::imatch(current_token().value, symbol_var))
+         else if (details::imatch(symbol, symbol_var))
          {
             return parse_define_var_statement();
          }
-         else if (details::imatch(current_token().value, symbol_swap))
+         else if (details::imatch(symbol, symbol_const))
+         {
+            return parse_define_constvar_statement();
+         }
+         else if (details::imatch(symbol, symbol_swap))
          {
             return parse_swap_statement();
          }
          #ifndef exprtk_disable_return_statement
          else if (
-                   details::imatch(current_token().value, symbol_return) &&
-                   settings_.control_struct_enabled(current_token().value)
+                   details::imatch(symbol, symbol_return) &&
+                   settings_.control_struct_enabled(symbol)
                  )
          {
-            return parse_return_statement();
+            return check_block_statement_closure(parse_return_statement());
          }
          #endif
+         else if (details::imatch(symbol, symbol_assert))
+         {
+            return parse_assert_statement();
+         }
          else if (symtab_store_.valid() || !sem_.empty())
          {
             return parse_symtab_symbol();
          }
          else
          {
-            set_error(
-               make_error(parser_error::e_symtab,
-                          current_token(),
-                          "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_symtab,
+               current_token(),
+               "ERR236 - Unknown variable or function encountered. Symbol table(s) "
+               "is either invalid or does not contain symbol: '" + symbol + "'",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -26718,11 +31272,11 @@ namespace exprtk
 
                if (0 == literal_exp)
                {
-                  set_error(
-                     make_error(parser_error::e_numeric,
-                                current_token(),
-                                "ERR200 - Failed generate node for scalar: '" + current_token().value + "'",
-                                exprtk_error_location));
+                  set_error(make_error(
+                     parser_error::e_numeric,
+                     current_token(),
+                     "ERR237 - Failed generate node for scalar: '" + current_token().value + "'",
+                     exprtk_error_location));
 
                   return error_node();
                }
@@ -26732,11 +31286,11 @@ namespace exprtk
             }
             else
             {
-               set_error(
-                  make_error(parser_error::e_numeric,
-                             current_token(),
-                             "ERR201 - Failed to convert '" + current_token().value + "' to a number",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_numeric,
+                  current_token(),
+                  "ERR238 - Failed to convert '" + current_token().value + "' to a number",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -26756,25 +31310,32 @@ namespace exprtk
             next_token();
 
             if (0 == (branch = parse_expression()))
+            {
                return error_node();
-            else if (!token_is(token_t::e_rbracket))
+            }
+
+            token_is(token_t::e_eof);
+
+            if (!token_is(token_t::e_rbracket))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR202 - Expected ')' instead of: '" + current_token().value + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR239 - Expected ')' instead of: '" + current_token().value + "'",
+                  exprtk_error_location));
 
-               free_node(node_allocator_,branch);
+               details::free_node(node_allocator_, branch);
 
                return error_node();
             }
             else if (!post_bracket_process(token_t::e_lbracket,branch))
             {
-               free_node(node_allocator_,branch);
+               details::free_node(node_allocator_, branch);
 
                return error_node();
             }
+
+            parse_pending_vector_index_operator(branch);
          }
          else if (token_t::e_lsqrbracket == current_token().type)
          {
@@ -26784,19 +31345,19 @@ namespace exprtk
                return error_node();
             else if (!token_is(token_t::e_rsqrbracket))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR203 - Expected ']' instead of: '" + current_token().value + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR240 - Expected ']' instead of: '" + current_token().value + "'",
+                  exprtk_error_location));
 
-               free_node(node_allocator_,branch);
+               details::free_node(node_allocator_, branch);
 
                return error_node();
             }
             else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
             {
-               free_node(node_allocator_,branch);
+               details::free_node(node_allocator_, branch);
 
                return error_node();
             }
@@ -26809,19 +31370,19 @@ namespace exprtk
                return error_node();
             else if (!token_is(token_t::e_rcrlbracket))
             {
-               set_error(
-                  make_error(parser_error::e_syntax,
-                             current_token(),
-                             "ERR204 - Expected '}' instead of: '" + current_token().value + "'",
-                             exprtk_error_location));
+               set_error(make_error(
+                  parser_error::e_syntax,
+                  current_token(),
+                  "ERR241 - Expected '}' instead of: '" + current_token().value + "'",
+                  exprtk_error_location));
 
-               free_node(node_allocator_,branch);
+               details::free_node(node_allocator_, branch);
 
                return error_node();
             }
             else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
             {
-               free_node(node_allocator_,branch);
+               details::free_node(node_allocator_, branch);
 
                return error_node();
             }
@@ -26843,7 +31404,7 @@ namespace exprtk
 
                if (0 == result)
                {
-                  free_node(node_allocator_,branch);
+                  details::free_node(node_allocator_, branch);
 
                   return error_node();
                }
@@ -26858,21 +31419,21 @@ namespace exprtk
          }
          else if (token_t::e_eof == current_token().type)
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR205 - Premature end of expression[1]",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR242 - Premature end of expression[1]",
+               exprtk_error_location));
 
             return error_node();
          }
          else
          {
-            set_error(
-               make_error(parser_error::e_syntax,
-                          current_token(),
-                          "ERR206 - Premature end of expression[2]",
-                          exprtk_error_location));
+            set_error(make_error(
+               parser_error::e_syntax,
+               current_token(),
+               "ERR243 - Premature end of expression[2]",
+               exprtk_error_location));
 
             return error_node();
          }
@@ -26973,6 +31534,8 @@ namespace exprtk
             register_synthezier(synthesize_covocov_expression4)
             register_synthezier(synthesize_vocovoc_expression4)
             register_synthezier(synthesize_covovoc_expression4)
+
+            #undef register_synthezier
             #endif
          }
 
@@ -27025,7 +31588,7 @@ namespace exprtk
          {
             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
 
-            if ((*binary_op_map_).end() == bop_itr)
+            if (binary_op_map_->end() == bop_itr)
                return false;
 
             bop = bop_itr->second;
@@ -27437,13 +32000,20 @@ namespace exprtk
 
                if (details::is_string_node(branch[0]))
                   return !b1_is_genstring;
+               else if (details::is_literal_node(branch[0]))
+                  return true;
                else
                   return (
-                           !details::is_variable_node          (branch[0]) &&
-                           !details::is_vector_elem_node       (branch[0]) &&
-                           !details::is_rebasevector_elem_node (branch[0]) &&
-                           !details::is_rebasevector_celem_node(branch[0]) &&
-                           !details::is_vector_node            (branch[0])
+                           !details::is_variable_node              (branch[0]) &&
+                           !details::is_vector_elem_node           (branch[0]) &&
+                           !details::is_vector_celem_node          (branch[0]) &&
+                           !details::is_vector_elem_rtc_node       (branch[0]) &&
+                           !details::is_vector_celem_rtc_node      (branch[0]) &&
+                           !details::is_rebasevector_elem_node     (branch[0]) &&
+                           !details::is_rebasevector_celem_node    (branch[0]) &&
+                           !details::is_rebasevector_elem_rtc_node (branch[0]) &&
+                           !details::is_rebasevector_celem_rtc_node(branch[0]) &&
+                           !details::is_vector_node                (branch[0])
                          )
                          || b1_is_genstring;
             }
@@ -27573,9 +32143,9 @@ namespace exprtk
                         (details::e_equal == operation) ||
                         (details::e_and   == operation) ||
                         (details::e_nand  == operation) ||
-                        (details::  e_or  == operation) ||
-                        (details:: e_nor  == operation) ||
-                        (details:: e_xor  == operation) ||
+                        (details::e_or    == operation) ||
+                        (details::e_nor   == operation) ||
+                        (details::e_xor   == operation) ||
                         (details::e_xnor  == operation)
                       );
          }
@@ -27598,18 +32168,42 @@ namespace exprtk
          {
             if ((0 == branch[0]) || (0 == branch[1]))
             {
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR244 - Invalid branches received for operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
+
                return error_node();
             }
             else if (is_invalid_string_op(operation,branch))
             {
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR245 - Invalid branch pair for string operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
+
                return error_node();
             }
             else if (is_invalid_assignment_op(operation,branch))
             {
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR246 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
+
                return error_node();
             }
             else if (is_invalid_break_continue_op(branch))
             {
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR247 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
+
                return error_node();
             }
             else if (details::e_assign == operation)
@@ -27728,10 +32322,22 @@ namespace exprtk
             {
                details::free_all_nodes(*node_allocator_,branch);
 
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR248 - Invalid branches operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
+
                return error_node();
             }
             else if (is_invalid_string_op(operation, branch))
             {
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR249 - Invalid branches for string operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
+
                return error_node();
             }
             else if (is_string_operation(operation, branch))
@@ -27774,9 +32380,19 @@ namespace exprtk
          {
             if ((0 == condition) || (0 == consequent))
             {
-               free_node(*node_allocator_,   condition);
-               free_node(*node_allocator_,  consequent);
-               free_node(*node_allocator_, alternative);
+               details::free_node(*node_allocator_, condition  );
+               details::free_node(*node_allocator_, consequent );
+               details::free_node(*node_allocator_, alternative);
+
+               const std::string invalid_branches =
+                                 ((0 == condition ) ? std::string("condition ") : "") +
+                                 ((0 == consequent) ? std::string("consequent") : "") ;
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_parser,
+                  parser_->current_state().token,
+                  "ERR250 - Invalid " + invalid_branches + " for conditional statement",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -27786,16 +32402,16 @@ namespace exprtk
                // True branch
                if (details::is_true(condition))
                {
-                  free_node(*node_allocator_,   condition);
-                  free_node(*node_allocator_, alternative);
+                  details::free_node(*node_allocator_, condition  );
+                  details::free_node(*node_allocator_, alternative);
 
                   return consequent;
                }
                // False branch
                else
                {
-                  free_node(*node_allocator_,  condition);
-                  free_node(*node_allocator_, consequent);
+                  details::free_node(*node_allocator_, condition );
+                  details::free_node(*node_allocator_, consequent);
 
                   if (alternative)
                      return alternative;
@@ -27803,14 +32419,34 @@ namespace exprtk
                      return node_allocator_->allocate<details::null_node<T> >();
                }
             }
-            else if ((0 != consequent) && (0 != alternative))
+
+            expression_node_ptr result = error_node();
+            std::string node_name      = "Unknown!";
+
+            if ((0 != consequent) && (0 != alternative))
             {
-               return node_allocator_->
-                        allocate<conditional_node_t>(condition, consequent, alternative);
+               result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative);
+               node_name = "conditional_node_t";
             }
             else
-               return node_allocator_->
-                        allocate<cons_conditional_node_t>(condition, consequent);
+            {
+               result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent);
+               node_name = "cons_conditional_node_t";
+            }
+
+            if (result && result->valid())
+            {
+               return result;
+            }
+
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_parser,
+               token_t(),
+               "ERR251 - Failed to synthesize node: " + node_name,
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
          }
 
          #ifndef exprtk_disable_string_capabilities
@@ -27820,9 +32456,19 @@ namespace exprtk
          {
             if ((0 == condition) || (0 == consequent))
             {
-               free_node(*node_allocator_,   condition);
-               free_node(*node_allocator_,  consequent);
-               free_node(*node_allocator_, alternative);
+               details::free_node(*node_allocator_, condition  );
+               details::free_node(*node_allocator_, consequent );
+               details::free_node(*node_allocator_, alternative);
+
+               const std::string invalid_branches =
+                                 ((0 == condition ) ? std::string("condition ") : "") +
+                                 ((0 == consequent) ? std::string("consequent") : "") ;
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_parser,
+                  parser_->current_state().token,
+                  "ERR252 - Invalid " + invalid_branches + " for string conditional statement",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -27832,16 +32478,16 @@ namespace exprtk
                // True branch
                if (details::is_true(condition))
                {
-                  free_node(*node_allocator_,   condition);
-                  free_node(*node_allocator_, alternative);
+                  details::free_node(*node_allocator_, condition  );
+                  details::free_node(*node_allocator_, alternative);
 
                   return consequent;
                }
                // False branch
                else
                {
-                  free_node(*node_allocator_,  condition);
-                  free_node(*node_allocator_, consequent);
+                  details::free_node(*node_allocator_, condition );
+                  details::free_node(*node_allocator_, consequent);
 
                   if (alternative)
                      return alternative;
@@ -27851,10 +32497,25 @@ namespace exprtk
                }
             }
             else if ((0 != consequent) && (0 != alternative))
-               return node_allocator_->
-                        allocate<conditional_string_node_t>(condition, consequent, alternative);
-            else
-               return error_node();
+            {
+               expression_node_ptr result =
+                  node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative);
+
+               if (result && result->valid())
+               {
+                  return result;
+               }
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_parser,
+                  token_t(),
+                  "ERR253 - Failed to synthesize node: conditional_string_node_t",
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
+            }
+
+            return error_node();
          }
          #else
          inline expression_node_ptr conditional_string(expression_node_ptr,
@@ -27865,6 +32526,61 @@ namespace exprtk
          }
          #endif
 
+         inline expression_node_ptr conditional_vector(expression_node_ptr condition,
+                                                       expression_node_ptr consequent,
+                                                       expression_node_ptr alternative) const
+         {
+            if ((0 == condition) || (0 == consequent))
+            {
+               details::free_node(*node_allocator_, condition  );
+               details::free_node(*node_allocator_, consequent );
+               details::free_node(*node_allocator_, alternative);
+
+               const std::string invalid_branches =
+                                 ((0 == condition ) ? std::string("condition ") : "") +
+                                 ((0 == consequent) ? std::string("consequent") : "") ;
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_parser,
+                  parser_->current_state().token,
+                  "ERR254 - Invalid " + invalid_branches + " for vector conditional statement",
+                  exprtk_error_location));
+
+               return error_node();
+            }
+            // Can the condition be immediately evaluated? if so optimise.
+            else if (details::is_constant_node(condition))
+            {
+               // True branch
+               if (details::is_true(condition))
+               {
+                  details::free_node(*node_allocator_, condition  );
+                  details::free_node(*node_allocator_, alternative);
+
+                  return consequent;
+               }
+               // False branch
+               else
+               {
+                  details::free_node(*node_allocator_, condition );
+                  details::free_node(*node_allocator_, consequent);
+
+                  if (alternative)
+                     return alternative;
+                  else
+                     return node_allocator_->allocate<details::null_node<T> >();
+
+               }
+            }
+            else if ((0 != consequent) && (0 != alternative))
+            {
+               return node_allocator_->
+                        allocate<conditional_vector_node_t>(condition, consequent, alternative);
+            }
+            else
+               return error_node();
+         }
+
          inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
          {
             if (
@@ -27878,45 +32594,70 @@ namespace exprtk
             return loop_runtime_check_ptr(0);
          }
 
+         inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const
+         {
+            return parser_->vector_access_runtime_check_;
+         }
+
          inline expression_node_ptr while_loop(expression_node_ptr& condition,
                                                expression_node_ptr& branch,
-                                               const bool brkcont = false) const
+                                               const bool break_continue_present = false) const
          {
-            if (!brkcont && details::is_constant_node(condition))
+            if (
+                 !break_continue_present              &&
+                 !parser_->state_.return_stmt_present &&
+                 details::is_constant_node(condition)
+               )
             {
                expression_node_ptr result = error_node();
                if (details::is_true(condition))
+               {
                   // Infinite loops are not allowed.
+
+                  parser_->set_error(parser_error::make_error(
+                     parser_error::e_parser,
+                     parser_->current_state().token,
+                     "ERR255 - Infinite loop condition without 'break' or 'return' not allowed in while-loops",
+                     exprtk_error_location));
+
                   result = error_node();
+               }
                else
                   result = node_allocator_->allocate<details::null_node<Type> >();
 
-               free_node(*node_allocator_, condition);
-               free_node(*node_allocator_,    branch);
+               details::free_node(*node_allocator_, condition);
+               details::free_node(*node_allocator_, branch   );
 
                return result;
             }
             else if (details::is_null_node(condition))
             {
-               free_node(*node_allocator_,condition);
+               details::free_node(*node_allocator_,condition);
 
                return branch;
             }
-            else if (!brkcont)
-               return node_allocator_->allocate<while_loop_node_t>
-                        (
-                          condition,
-                          branch,
-                          get_loop_runtime_check(loop_runtime_check::e_while_loop)
-                        );
+
+            loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop);
+
+            if (!break_continue_present)
+            {
+               if (rtc)
+                  return node_allocator_->allocate<while_loop_rtc_node_t>
+                           (condition, branch,  rtc);
+               else
+                  return node_allocator_->allocate<while_loop_node_t>
+                           (condition, branch);
+            }
             #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<while_loop_bc_node_t>
-                        (
-                          condition,
-                          branch,
-                          get_loop_runtime_check(loop_runtime_check::e_while_loop)
-                        );
+            {
+               if (rtc)
+                  return node_allocator_->allocate<while_loop_bc_rtc_node_t>
+                           (condition, branch, rtc);
+               else
+                  return node_allocator_->allocate<while_loop_bc_node_t>
+                           (condition, branch);
+            }
             #else
                return error_node();
             #endif
@@ -27924,9 +32665,9 @@ namespace exprtk
 
          inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
                                                       expression_node_ptr& branch,
-                                                      const bool brkcont = false) const
+                                                      const bool break_continue_present = false) const
          {
-            if (!brkcont && details::is_constant_node(condition))
+            if (!break_continue_present && details::is_constant_node(condition))
             {
                if (
                     details::is_true(condition) &&
@@ -27938,32 +32679,39 @@ namespace exprtk
                   return branch;
                }
 
-               free_node(*node_allocator_, condition);
-               free_node(*node_allocator_,    branch);
+               details::free_node(*node_allocator_, condition);
+               details::free_node(*node_allocator_, branch   );
 
                return error_node();
             }
             else if (details::is_null_node(condition))
             {
-               free_node(*node_allocator_,condition);
+               details::free_node(*node_allocator_,condition);
 
                return branch;
             }
-            else if (!brkcont)
-               return node_allocator_->allocate<repeat_until_loop_node_t>
-                        (
-                          condition,
-                          branch,
-                          get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
-                        );
+
+            loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop);
+
+            if (!break_continue_present)
+            {
+               if (rtc)
+                  return node_allocator_->allocate<repeat_until_loop_rtc_node_t>
+                           (condition, branch,  rtc);
+               else
+                  return node_allocator_->allocate<repeat_until_loop_node_t>
+                           (condition, branch);
+            }
             #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<repeat_until_loop_bc_node_t>
-                        (
-                          condition,
-                          branch,
-                          get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
-                        );
+            {
+               if (rtc)
+                  return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t>
+                           (condition, branch, rtc);
+               else
+                  return node_allocator_->allocate<repeat_until_loop_bc_node_t>
+                           (condition, branch);
+            }
             #else
                return error_node();
             #endif
@@ -27973,55 +32721,92 @@ namespace exprtk
                                              expression_node_ptr& condition,
                                              expression_node_ptr& incrementor,
                                              expression_node_ptr& loop_body,
-                                             bool brkcont = false) const
+                                             bool break_continue_present = false) const
          {
-            if (!brkcont && details::is_constant_node(condition))
+            if (
+                 !break_continue_present              &&
+                 !parser_->state_.return_stmt_present &&
+                 details::is_constant_node(condition)
+               )
             {
                expression_node_ptr result = error_node();
 
                if (details::is_true(condition))
+               {
                   // Infinite loops are not allowed.
+
+                  parser_->set_error(parser_error::make_error(
+                     parser_error::e_parser,
+                     parser_->current_state().token,
+                     "ERR256 - Infinite loop condition without 'break' or 'return' not allowed in for-loop",
+                     exprtk_error_location));
+
                   result = error_node();
+               }
                else
                   result = node_allocator_->allocate<details::null_node<Type> >();
 
-               free_node(*node_allocator_, initialiser);
-               free_node(*node_allocator_,   condition);
-               free_node(*node_allocator_, incrementor);
-               free_node(*node_allocator_,   loop_body);
+               details::free_node(*node_allocator_, initialiser);
+               details::free_node(*node_allocator_, condition  );
+               details::free_node(*node_allocator_, incrementor);
+               details::free_node(*node_allocator_, loop_body  );
 
                return result;
             }
             else if (details::is_null_node(condition) || (0 == condition))
             {
-               free_node(*node_allocator_, initialiser);
-               free_node(*node_allocator_,   condition);
-               free_node(*node_allocator_, incrementor);
+               details::free_node(*node_allocator_, initialiser);
+               details::free_node(*node_allocator_, condition  );
+               details::free_node(*node_allocator_, incrementor);
 
                return loop_body;
             }
-            else if (!brkcont)
-               return node_allocator_->allocate<for_loop_node_t>
-                                       (
-                                         initialiser,
-                                         condition,
-                                         incrementor,
-                                         loop_body,
-                                         get_loop_runtime_check(loop_runtime_check::e_for_loop)
-                                       );
 
+            loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop);
+
+            if (!break_continue_present)
+            {
+               if (rtc)
+                  return node_allocator_->allocate<for_loop_rtc_node_t>
+                                          (
+                                             initialiser,
+                                             condition,
+                                             incrementor,
+                                             loop_body,
+                                             rtc
+                                          );
+               else
+                  return node_allocator_->allocate<for_loop_node_t>
+                                          (
+                                             initialiser,
+                                             condition,
+                                             incrementor,
+                                             loop_body
+                                          );
+            }
             #ifndef exprtk_disable_break_continue
             else
-               return node_allocator_->allocate<for_loop_bc_node_t>
-                                       (
-                                         initialiser,
-                                         condition,
-                                         incrementor,
-                                         loop_body,
-                                         get_loop_runtime_check(loop_runtime_check::e_for_loop)
-                                       );
+            {
+               if (rtc)
+                  return node_allocator_->allocate<for_loop_bc_rtc_node_t>
+                                          (
+                                             initialiser,
+                                             condition,
+                                             incrementor,
+                                             loop_body,
+                                             rtc
+                                          );
+               else
+                  return node_allocator_->allocate<for_loop_bc_node_t>
+                                          (
+                                             initialiser,
+                                             condition,
+                                             incrementor,
+                                             loop_body
+                                          );
+            }
             #else
-            return error_node();
+               return error_node();
             #endif
          }
 
@@ -28080,8 +32865,8 @@ namespace exprtk
 
             if (0 == result)
             {
-               T zero = T(0);
-               result = node_allocator_->allocate<literal_node_t>(zero);
+               const T zero = T(0);
+               result       = node_allocator_->allocate<literal_node_t>(zero);
             }
 
             for (std::size_t i = 0; i < arg_list.size(); ++i)
@@ -28090,7 +32875,7 @@ namespace exprtk
 
                if (current_expr && (current_expr != result))
                {
-                  free_node(*node_allocator_,current_expr);
+                  details::free_node(*node_allocator_,current_expr);
                }
             }
 
@@ -28104,49 +32889,57 @@ namespace exprtk
             #define case_stmt(N)                                                         \
             if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
 
-            struct switch_1
+            struct switch_impl_1
             {
                static inline T process(const arg_list_t& arg)
                {
                   case_stmt(0)
 
+                  assert(arg.size() == ((2 * 1) + 1));
+
                   return arg.back().first->value();
                }
             };
 
-            struct switch_2
+            struct switch_impl_2
             {
                static inline T process(const arg_list_t& arg)
                {
                   case_stmt(0) case_stmt(1)
 
+                  assert(arg.size() == ((2 * 2) + 1));
+
                   return arg.back().first->value();
                }
             };
 
-            struct switch_3
+            struct switch_impl_3
             {
                static inline T process(const arg_list_t& arg)
                {
                   case_stmt(0) case_stmt(1)
                   case_stmt(2)
 
+                  assert(arg.size() == ((2 * 3) + 1));
+
                   return arg.back().first->value();
                }
             };
 
-            struct switch_4
+            struct switch_impl_4
             {
                static inline T process(const arg_list_t& arg)
                {
                   case_stmt(0) case_stmt(1)
                   case_stmt(2) case_stmt(3)
 
+                  assert(arg.size() == ((2 * 4) + 1));
+
                   return arg.back().first->value();
                }
             };
 
-            struct switch_5
+            struct switch_impl_5
             {
                static inline T process(const arg_list_t& arg)
                {
@@ -28154,11 +32947,13 @@ namespace exprtk
                   case_stmt(2) case_stmt(3)
                   case_stmt(4)
 
+                  assert(arg.size() == ((2 * 5) + 1));
+
                   return arg.back().first->value();
                }
             };
 
-            struct switch_6
+            struct switch_impl_6
             {
                static inline T process(const arg_list_t& arg)
                {
@@ -28166,11 +32961,13 @@ namespace exprtk
                   case_stmt(2) case_stmt(3)
                   case_stmt(4) case_stmt(5)
 
+                  assert(arg.size() == ((2 * 6) + 1));
+
                   return arg.back().first->value();
                }
             };
 
-            struct switch_7
+            struct switch_impl_7
             {
                static inline T process(const arg_list_t& arg)
                {
@@ -28179,6 +32976,8 @@ namespace exprtk
                   case_stmt(4) case_stmt(5)
                   case_stmt(6)
 
+                  assert(arg.size() == ((2 * 7) + 1));
+
                   return arg.back().first->value();
                }
             };
@@ -28206,11 +33005,11 @@ namespace exprtk
 
             switch ((arg_list.size() - 1) / 2)
             {
-               #define case_stmt(N)                                                 \
-               case N :                                                             \
-                  return node_allocator_->                                          \
-                            allocate<details::switch_n_node                         \
-                              <Type,typename switch_nodes::switch_##N> >(arg_list); \
+               #define case_stmt(N)                                                       \
+               case N :                                                                   \
+                  return node_allocator_->                                                \
+                            allocate<details::switch_n_node                               \
+                              <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \
 
                case_stmt(1)
                case_stmt(2)
@@ -28241,47 +33040,69 @@ namespace exprtk
                return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
          }
 
-         #define unary_opr_switch_statements            \
-         case_stmt(details::  e_abs, details::  abs_op) \
-         case_stmt(details:: e_acos, details:: acos_op) \
-         case_stmt(details::e_acosh, details::acosh_op) \
-         case_stmt(details:: e_asin, details:: asin_op) \
-         case_stmt(details::e_asinh, details::asinh_op) \
-         case_stmt(details:: e_atan, details:: atan_op) \
-         case_stmt(details::e_atanh, details::atanh_op) \
-         case_stmt(details:: e_ceil, details:: ceil_op) \
-         case_stmt(details::  e_cos, details::  cos_op) \
-         case_stmt(details:: e_cosh, details:: cosh_op) \
-         case_stmt(details::  e_exp, details::  exp_op) \
-         case_stmt(details::e_expm1, details::expm1_op) \
-         case_stmt(details::e_floor, details::floor_op) \
-         case_stmt(details::  e_log, details::  log_op) \
-         case_stmt(details::e_log10, details::log10_op) \
-         case_stmt(details:: e_log2, details:: log2_op) \
-         case_stmt(details::e_log1p, details::log1p_op) \
-         case_stmt(details::  e_neg, details::  neg_op) \
-         case_stmt(details::  e_pos, details::  pos_op) \
-         case_stmt(details::e_round, details::round_op) \
-         case_stmt(details::  e_sin, details::  sin_op) \
-         case_stmt(details:: e_sinc, details:: sinc_op) \
-         case_stmt(details:: e_sinh, details:: sinh_op) \
-         case_stmt(details:: e_sqrt, details:: sqrt_op) \
-         case_stmt(details::  e_tan, details::  tan_op) \
-         case_stmt(details:: e_tanh, details:: tanh_op) \
-         case_stmt(details::  e_cot, details::  cot_op) \
-         case_stmt(details::  e_sec, details::  sec_op) \
-         case_stmt(details::  e_csc, details::  csc_op) \
-         case_stmt(details::  e_r2d, details::  r2d_op) \
-         case_stmt(details::  e_d2r, details::  d2r_op) \
-         case_stmt(details::  e_d2g, details::  d2g_op) \
-         case_stmt(details::  e_g2d, details::  g2d_op) \
-         case_stmt(details:: e_notl, details:: notl_op) \
-         case_stmt(details::  e_sgn, details::  sgn_op) \
-         case_stmt(details::  e_erf, details::  erf_op) \
-         case_stmt(details:: e_erfc, details:: erfc_op) \
-         case_stmt(details:: e_ncdf, details:: ncdf_op) \
-         case_stmt(details:: e_frac, details:: frac_op) \
-         case_stmt(details::e_trunc, details::trunc_op) \
+         inline expression_node_ptr assert_call(expression_node_ptr& assert_condition,
+                                                expression_node_ptr& assert_message,
+                                                const assert_check::assert_context& context)
+         {
+            typedef details::assert_node<Type> alloc_type;
+
+            expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type>
+               (assert_condition, assert_message, parser_->assert_check_, context);
+
+            if (result && result->valid())
+            {
+               parser_->state_.activate_side_effect("assert_call()");
+               return result;
+            }
+
+            details::free_node(*node_allocator_, result          );
+            details::free_node(*node_allocator_, assert_condition);
+            details::free_node(*node_allocator_, assert_message  );
+
+            return error_node();
+         }
+
+         #define unary_opr_switch_statements             \
+         case_stmt(details::e_abs   , details::abs_op  ) \
+         case_stmt(details::e_acos  , details::acos_op ) \
+         case_stmt(details::e_acosh , details::acosh_op) \
+         case_stmt(details::e_asin  , details::asin_op ) \
+         case_stmt(details::e_asinh , details::asinh_op) \
+         case_stmt(details::e_atan  , details::atan_op ) \
+         case_stmt(details::e_atanh , details::atanh_op) \
+         case_stmt(details::e_ceil  , details::ceil_op ) \
+         case_stmt(details::e_cos   , details::cos_op  ) \
+         case_stmt(details::e_cosh  , details::cosh_op ) \
+         case_stmt(details::e_exp   , details::exp_op  ) \
+         case_stmt(details::e_expm1 , details::expm1_op) \
+         case_stmt(details::e_floor , details::floor_op) \
+         case_stmt(details::e_log   , details::log_op  ) \
+         case_stmt(details::e_log10 , details::log10_op) \
+         case_stmt(details::e_log2  , details::log2_op ) \
+         case_stmt(details::e_log1p , details::log1p_op) \
+         case_stmt(details::e_neg   , details::neg_op  ) \
+         case_stmt(details::e_pos   , details::pos_op  ) \
+         case_stmt(details::e_round , details::round_op) \
+         case_stmt(details::e_sin   , details::sin_op  ) \
+         case_stmt(details::e_sinc  , details::sinc_op ) \
+         case_stmt(details::e_sinh  , details::sinh_op ) \
+         case_stmt(details::e_sqrt  , details::sqrt_op ) \
+         case_stmt(details::e_tan   , details::tan_op  ) \
+         case_stmt(details::e_tanh  , details::tanh_op ) \
+         case_stmt(details::e_cot   , details::cot_op  ) \
+         case_stmt(details::e_sec   , details::sec_op  ) \
+         case_stmt(details::e_csc   , details::csc_op  ) \
+         case_stmt(details::e_r2d   , details::r2d_op  ) \
+         case_stmt(details::e_d2r   , details::d2r_op  ) \
+         case_stmt(details::e_d2g   , details::d2g_op  ) \
+         case_stmt(details::e_g2d   , details::g2d_op  ) \
+         case_stmt(details::e_notl  , details::notl_op ) \
+         case_stmt(details::e_sgn   , details::sgn_op  ) \
+         case_stmt(details::e_erf   , details::erf_op  ) \
+         case_stmt(details::e_erfc  , details::erfc_op ) \
+         case_stmt(details::e_ncdf  , details::ncdf_op ) \
+         case_stmt(details::e_frac  , details::frac_op ) \
+         case_stmt(details::e_trunc , details::trunc_op) \
 
          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
                                                              expression_node_ptr (&branch)[1])
@@ -28290,7 +33111,7 @@ namespace exprtk
 
             switch (operation)
             {
-               #define case_stmt(op0,op1)                                                          \
+               #define case_stmt(op0, op1)                                                         \
                case op0 : return node_allocator_->                                                 \
                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
 
@@ -28305,7 +33126,7 @@ namespace exprtk
          {
             switch (operation)
             {
-               #define case_stmt(op0,op1)                                                    \
+               #define case_stmt(op0, op1)                                                   \
                case op0 : return node_allocator_->                                           \
                              allocate<typename details::unary_vector_node<Type,op1<Type> > > \
                                 (operation, branch[0]);                                      \
@@ -28321,7 +33142,7 @@ namespace exprtk
          {
             switch (operation)
             {
-               #define case_stmt(op0,op1)                                                                \
+               #define case_stmt(op0, op1)                                                               \
                case op0 : return node_allocator_->                                                       \
                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
 
@@ -28360,6 +33181,8 @@ namespace exprtk
                default : return error_node();
             }
 
+            assert(temp_node);
+
             const T v = temp_node->value();
 
             details::free_node(*node_allocator_,temp_node);
@@ -28463,6 +33286,8 @@ namespace exprtk
                default : return error_node();
             }
 
+            assert(temp_node);
+
             const T v = temp_node->value();
 
             details::free_node(*node_allocator_,temp_node);
@@ -28545,7 +33370,7 @@ namespace exprtk
 
             switch (operation)
             {
-               #define case_stmt(op0,op1)                                                 \
+               #define case_stmt(op0, op1)                                                \
                case op0 : temp_node = node_allocator_->                                   \
                                          allocate<details::vararg_node<Type,op1<Type> > > \
                                             (arg_list);                                   \
@@ -28583,11 +33408,12 @@ namespace exprtk
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
-         inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation,
+                                                                Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             switch (operation)
             {
-               #define case_stmt(op0,op1)                                                   \
+               #define case_stmt(op0, op1)                                                  \
                case op0 : return node_allocator_->                                          \
                              allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
 
@@ -28606,13 +33432,14 @@ namespace exprtk
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
-         inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         inline expression_node_ptr vectorize_func(const details::operator_type& operation,
+                                                   Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             if (1 == arg_list.size())
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                      \
+                  #define case_stmt(op0, op1)                                                     \
                   case op0 : return node_allocator_->                                             \
                                 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
 
@@ -28631,7 +33458,8 @@ namespace exprtk
 
          template <typename Allocator,
                    template <typename, typename> class Sequence>
-         inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         inline expression_node_ptr vararg_function(const details::operator_type& operation,
+                                                    Sequence<expression_node_ptr,Allocator>& arg_list)
          {
             if (!all_nodes_valid(arg_list))
             {
@@ -28641,9 +33469,9 @@ namespace exprtk
             }
             else if (is_constant_foldable(arg_list))
                return const_optimise_varargfunc(operation,arg_list);
-            else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
+            else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0]))
                return vectorize_func(operation,arg_list);
-            else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
+            else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation))
                return arg_list[0];
             else if (all_nodes_variables(arg_list))
                return varnode_optimise_varargfunc(operation,arg_list);
@@ -28651,17 +33479,32 @@ namespace exprtk
             #ifndef exprtk_disable_string_capabilities
             if (details::e_smulti == operation)
             {
-               return node_allocator_->
+               expression_node_ptr result = node_allocator_->
                  allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
+               if (result && result->valid())
+               {
+                  return result;
+               }
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_synthesis,
+                  token_t(),
+                  "ERR257 - Failed to synthesize node: str_vararg_node<vararg_multi_op>",
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
             }
             else
             #endif
             {
+               expression_node_ptr result = error_node();
+
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                \
-                  case op0 : return node_allocator_->                                       \
+                  #define case_stmt(op0, op1)                                               \
+                  case op0 : result = node_allocator_->                                     \
                                 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
+                             break;                                                         \
 
                   case_stmt(details::e_sum   , details::vararg_add_op  )
                   case_stmt(details::e_prod  , details::vararg_mul_op  )
@@ -28674,7 +33517,22 @@ namespace exprtk
                   #undef case_stmt
                   default : return error_node();
                }
+
+               if (result && result->valid())
+               {
+                  return result;
+               }
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_synthesis,
+                  token_t(),
+                  "ERR258 - Failed to synthesize node: vararg_node",
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
             }
+
+            return error_node();
          }
 
          template <std::size_t N>
@@ -28715,7 +33573,19 @@ namespace exprtk
                   return error_node();
                }
 
-               return result;
+               if (result && result->valid())
+               {
+                  return result;
+               }
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_synthesis,
+                  token_t(),
+                  "ERR259 - Failed to synthesize node: function_N_node_t",
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
+               return error_node();
             }
          }
 
@@ -28752,7 +33622,19 @@ namespace exprtk
 
             parser_->state_.activate_side_effect("vararg_function_call()");
 
-            return result;
+            if (result && result->valid())
+            {
+               return result;
+            }
+
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_synthesis,
+               token_t(),
+               "ERR260 - Failed to synthesize node: vararg_function_node<ivararg_function_t>",
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
          }
 
          inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
@@ -28771,14 +33653,23 @@ namespace exprtk
             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
 
             expression_node_ptr result = error_node();
+            std::string node_name = "Unknown";
 
             if (no_psi == param_seq_index)
+            {
                result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
+               node_name = "generic_function_node<igeneric_function_t>";
+            }
             else
+            {
                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
+               node_name = "multimode_genfunction_node<igeneric_function_t>";
+            }
 
             alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
 
+            assert(genfunc_node_ptr);
+
             if (
                  !arg_list.empty()                  &&
                  !gf->has_side_effects()            &&
@@ -28796,9 +33687,20 @@ namespace exprtk
             }
             else if (genfunc_node_ptr->init_branches())
             {
-               parser_->state_.activate_side_effect("generic_function_call()");
+               if (result && result->valid())
+               {
+                  parser_->state_.activate_side_effect("generic_function_call()");
+                  return result;
+               }
 
-               return result;
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_synthesis,
+                  token_t(),
+                  "ERR261 - Failed to synthesize node: " + node_name,
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
+               return error_node();
             }
             else
             {
@@ -28826,14 +33728,23 @@ namespace exprtk
             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
 
             expression_node_ptr result = error_node();
+            std::string node_name = "Unknown";
 
             if (no_psi == param_seq_index)
+            {
                result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
+               node_name = "string_function_node<igeneric_function_t>";
+            }
             else
+            {
                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
+               node_name = "multimode_strfunction_node<igeneric_function_t>";
+            }
 
             alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
 
+            assert(strfunc_node_ptr);
+
             if (
                  !arg_list.empty()       &&
                  !gf->has_side_effects() &&
@@ -28850,9 +33761,20 @@ namespace exprtk
             }
             else if (strfunc_node_ptr->init_branches())
             {
-               parser_->state_.activate_side_effect("string_function_call()");
+               if (result && result->valid())
+               {
+                  parser_->state_.activate_side_effect("string_function_call()");
+                  return result;
+               }
 
-               return result;
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_synthesis,
+                  token_t(),
+                  "ERR262 - Failed to synthesize node: " + node_name,
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
+               return error_node();
             }
             else
             {
@@ -28880,16 +33802,29 @@ namespace exprtk
 
             alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
 
+            assert(return_node_ptr);
+
             if (return_node_ptr->init_branches())
             {
-               parser_->state_.activate_side_effect("return_call()");
+               if (result && result->valid())
+               {
+                  parser_->state_.activate_side_effect("return_call()");
+                  return result;
+               }
 
-               return result;
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_synthesis,
+                  token_t(),
+                  "ERR263 - Failed to synthesize node: return_node",
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, result);
+               return error_node();
             }
             else
             {
-               details::free_node     (*node_allocator_,result  );
-               details::free_all_nodes(*node_allocator_,arg_list);
+               details::free_node     (*node_allocator_, result  );
+               details::free_all_nodes(*node_allocator_, arg_list);
 
                return error_node();
             }
@@ -28922,28 +33857,93 @@ namespace exprtk
          }
          #endif
 
-         inline expression_node_ptr vector_element(const std::string& symbol,
-                                                   vector_holder_ptr vector_base,
+         inline expression_node_ptr vector_element(const std::string&  symbol,
+                                                   vector_holder_ptr   vector_base,
+                                                   expression_node_ptr vec_node,
                                                    expression_node_ptr index)
          {
             expression_node_ptr result = error_node();
+            std::string node_name = "Unknown";
 
             if (details::is_constant_node(index))
             {
-               std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
+               const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
 
                details::free_node(*node_allocator_,index);
 
+               if (vec_index >= vector_base->size())
+               {
+                  parser_->set_error(parser_error::make_error(
+                     parser_error::e_parser,
+                     token_t(),
+                     "ERR264 - Index of " + details::to_str(vec_index) + " out of range for "
+                     "vector '" + symbol + "' of size " + details::to_str(vector_base->size()),
+                     exprtk_error_location));
+
+                  details::free_node(*node_allocator_,vec_node);
+
+                  return error_node();
+               }
+
                if (vector_base->rebaseable())
                {
-                  return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
+                  vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
+
+                  result = (rtc) ?
+                     node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
+                     node_allocator_->allocate<rebasevector_celem_node_t    >(vec_node, vec_index, vector_base     ) ;
+
+                  node_name = (rtc) ?
+                     "rebasevector_elem_rtc_node_t" :
+                     "rebasevector_elem_node_t"     ;
+
+                  if (result && result->valid())
+                  {
+                     return result;
+                  }
+
+                  parser_->set_error(parser_error::make_error(
+                     parser_error::e_synthesis,
+                     token_t(),
+                     "ERR265 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
+                     exprtk_error_location));
+
+                  details::free_node(*node_allocator_, result);
+                  return error_node();
+               }
+               else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node))
+               {
+                  vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
+
+                  result = (rtc) ?
+                     node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
+                     node_allocator_->allocate<vector_celem_node_t    >(vec_node, vec_index, vector_base     ) ;
+
+                  node_name = (rtc) ?
+                     "vector_elem_rtc_node_t" :
+                     "vector_elem_node_t"     ;
+
+                  if (result && result->valid())
+                  {
+                     return result;
+                  }
+
+                  parser_->set_error(parser_error::make_error(
+                     parser_error::e_synthesis,
+                     token_t(),
+                     "ERR266 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
+                     exprtk_error_location));
+
+                  details::free_node(*node_allocator_, result);
+                  return error_node();
                }
 
-               const scope_element& se = parser_->sem_.get_element(symbol,i);
+               const scope_element& se = parser_->sem_.get_element(symbol,vec_index);
 
-               if (se.index == i)
+               if (se.index == vec_index)
                {
                   result = se.var_node;
+                  details::free_node(*node_allocator_,vec_node);
                }
                else
                {
@@ -28952,10 +33952,10 @@ namespace exprtk
                   nse.active    = true;
                   nse.ref_count = 1;
                   nse.type      = scope_element::e_vecelem;
-                  nse.index     = i;
+                  nse.index     = vec_index;
                   nse.depth     = parser_->state_.scope_depth;
                   nse.data      = 0;
-                  nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
+                  nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index]));
 
                   if (!parser_->sem_.add_element(nse))
                   {
@@ -28966,19 +33966,55 @@ namespace exprtk
                      result = error_node();
                   }
 
-                  exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
+                  details::free_node(*node_allocator_,vec_node);
+
+                  exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str()));
 
                   parser_->state_.activate_side_effect("vector_element()");
 
                   result = nse.var_node;
+                  node_name = "variable_node_t";
                }
             }
-            else if (vector_base->rebaseable())
-               result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
             else
-               result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
+            {
+               vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
 
-            return result;
+               if (vector_base->rebaseable())
+               {
+                  result = (rtc) ?
+                     node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
+                     node_allocator_->allocate<rebasevector_elem_node_t    >(vec_node, index, vector_base     ) ;
+
+                  node_name = (rtc) ?
+                     "rebasevector_elem_rtc_node_t" :
+                     "rebasevector_elem_node_t"     ;
+               }
+               else
+               {
+                  result = rtc ?
+                     node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
+                     node_allocator_->allocate<vector_elem_node_t    >(vec_node, index, vector_base     ) ;
+
+                  node_name = (rtc) ?
+                     "vector_elem_rtc_node_t" :
+                     "vector_elem_node_t"     ;
+               }
+            }
+
+            if (result && result->valid())
+            {
+               return result;
+            }
+
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_synthesis,
+               token_t(),
+               "ERR267 - Failed to synthesize node: " + node_name,
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
          }
 
       private:
@@ -29063,43 +34099,130 @@ namespace exprtk
             }
          }
 
+         const void* base_ptr(expression_node_ptr node)
+         {
+            if (node)
+            {
+               switch(node->type())
+               {
+                  case details::expression_node<T>::e_variable:
+                     return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_vecelem:
+                     return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_veccelem:
+                     return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_vecelemrtc:
+                     return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_veccelemrtc:
+                     return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_rbvecelem:
+                     return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_rbvecelemrtc:
+                     return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_rbveccelem:
+                     return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_rbveccelemrtc:
+                     return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref());
+
+                  case details::expression_node<T>::e_vector:
+                     return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data());
+
+                  #ifndef exprtk_disable_string_capabilities
+                  case details::expression_node<T>::e_stringvar:
+                     return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base()));
+
+                  case details::expression_node<T>::e_stringvarrng:
+                     return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base()));
+                  #endif
+                  default : return reinterpret_cast<const void*>(0);
+               }
+            }
+
+            return reinterpret_cast<const void*>(0);
+         }
+
+         bool assign_immutable_symbol(expression_node_ptr node)
+         {
+            interval_t interval;
+            const void* baseptr_addr = base_ptr(node);
+
+            exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr));
+
+            if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval))
+            {
+               typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval);
+
+               if (parser_->immutable_symtok_map_.end() != itr)
+               {
+                  token_t& token = itr->second;
+                  parser_->set_error(parser_error::make_error(
+                     parser_error::e_parser,
+                     token,
+                     "ERR268 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.",
+                     exprtk_error_location));
+               }
+               else
+                  parser_->set_synthesis_error("Unable to assign symbol is immutable.");
+
+               return true;
+            }
+
+            return false;
+         }
+
          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
          {
-            if (details::is_variable_node(branch[0]))
+            if (assign_immutable_symbol(branch[0]))
+            {
+               return error_node();
+            }
+            else if (details::is_variable_node(branch[0]))
             {
                lodge_assignment(e_st_variable,branch[0]);
-
                return synthesize_expression<assignment_node_t,2>(operation,branch);
             }
-            else if (details::is_vector_elem_node(branch[0]))
+            else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0]))
             {
                lodge_assignment(e_st_vecelem,branch[0]);
-
                return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
             }
+            else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
+               return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch);
+            }
             else if (details::is_rebasevector_elem_node(branch[0]))
             {
                lodge_assignment(e_st_vecelem,branch[0]);
-
                return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
             }
+            else if (details::is_rebasevector_elem_rtc_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
+               return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch);
+            }
             else if (details::is_rebasevector_celem_node(branch[0]))
             {
                lodge_assignment(e_st_vecelem,branch[0]);
-
                return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
             }
             #ifndef exprtk_disable_string_capabilities
             else if (details::is_string_node(branch[0]))
             {
                lodge_assignment(e_st_string,branch[0]);
-
                return synthesize_expression<assignment_string_node_t,2>(operation, branch);
             }
             else if (details::is_string_range_node(branch[0]))
             {
                lodge_assignment(e_st_string,branch[0]);
-
                return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
             }
             #endif
@@ -29109,12 +34232,26 @@ namespace exprtk
 
                if (details::is_ivector_node(branch[1]))
                   return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
-              else
+               else
                   return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
             }
+            else if (details::is_literal_node(branch[0]))
+            {
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR269 - Cannot assign value to const variable",
+                  exprtk_error_location));
+
+               return error_node();
+            }
             else
             {
-               parser_->set_synthesis_error("Invalid assignment operation.[1]");
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR270 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
@@ -29123,22 +34260,32 @@ namespace exprtk
          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
                                                                                expression_node_ptr (&branch)[2])
          {
+            if (assign_immutable_symbol(branch[0]))
+            {
+               return error_node();
+            }
+
+            expression_node_ptr result = error_node();
+            std::string node_name = "Unknown";
+
             if (details::is_variable_node(branch[0]))
             {
                lodge_assignment(e_st_variable,branch[0]);
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                  \
-                  case op0 : return node_allocator_->                                                         \
+                  #define case_stmt(op0, op1)                                                                 \
+                  case op0 : result = node_allocator_->                                                       \
                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                         \
-
-                  case_stmt(details::e_addass,details::add_op)
-                  case_stmt(details::e_subass,details::sub_op)
-                  case_stmt(details::e_mulass,details::mul_op)
-                  case_stmt(details::e_divass,details::div_op)
-                  case_stmt(details::e_modass,details::mod_op)
+                             node_name = "assignment_op_node";                                                \
+                             break;                                                                           \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
                   #undef case_stmt
                   default : return error_node();
                }
@@ -29149,16 +34296,62 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                            \
-                  case op0 : return node_allocator_->                                                                   \
+                  #define case_stmt(op0, op1)                                                                           \
+                  case op0 : result = node_allocator_->                                                                 \
                                  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
                                     (operation, branch[0], branch[1]);                                                  \
+                             node_name = "assignment_vec_elem_op_node";                                                 \
+                             break;                                                                                     \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (details::is_vector_elem_rtc_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
 
-                  case_stmt(details::e_addass,details::add_op)
-                  case_stmt(details::e_subass,details::sub_op)
-                  case_stmt(details::e_mulass,details::mul_op)
-                  case_stmt(details::e_divass,details::div_op)
-                  case_stmt(details::e_modass,details::mod_op)
+               switch (operation)
+               {
+                  #define case_stmt(op0, op1)                                                                               \
+                  case op0 : result = node_allocator_->                                                                     \
+                                 template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \
+                                    (operation, branch[0], branch[1]);                                                      \
+                             node_name = "assignment_vec_elem_op_rtc_node";                                                 \
+                             break;                                                                                         \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (details::is_vector_celem_rtc_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
+
+               switch (operation)
+               {
+                  #define case_stmt(op0, op1)                                                                                \
+                  case op0 : result = node_allocator_->                                                                      \
+                                 template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \
+                                    (operation, branch[0], branch[1]);                                                       \
+                             node_name = "assignment_vec_celem_op_rtc_node";                                                 \
+                             break;                                                                                          \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
                   #undef case_stmt
                   default : return error_node();
                }
@@ -29169,16 +34362,18 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                                  \
-                  case op0 : return node_allocator_->                                                                         \
+                  #define case_stmt(op0, op1)                                                                                 \
+                  case op0 : result = node_allocator_->                                                                       \
                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
                                     (operation, branch[0], branch[1]);                                                        \
-
-                  case_stmt(details::e_addass,details::add_op)
-                  case_stmt(details::e_subass,details::sub_op)
-                  case_stmt(details::e_mulass,details::mul_op)
-                  case_stmt(details::e_divass,details::div_op)
-                  case_stmt(details::e_modass,details::mod_op)
+                             node_name = "assignment_rebasevec_elem_op_node";                                                 \
+                             break;                                                                                           \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
                   #undef case_stmt
                   default : return error_node();
                }
@@ -29189,16 +34384,62 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                                   \
-                  case op0 : return node_allocator_->                                                                          \
+                  #define case_stmt(op0, op1)                                                                                  \
+                  case op0 : result = node_allocator_->                                                                        \
                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
                                     (operation, branch[0], branch[1]);                                                         \
+                             node_name = "assignment_rebasevec_celem_op_node";                                                 \
+                             break;                                                                                            \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (details::is_rebasevector_elem_rtc_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
 
-                  case_stmt(details::e_addass,details::add_op)
-                  case_stmt(details::e_subass,details::sub_op)
-                  case_stmt(details::e_mulass,details::mul_op)
-                  case_stmt(details::e_divass,details::div_op)
-                  case_stmt(details::e_modass,details::mod_op)
+               switch (operation)
+               {
+                  #define case_stmt(op0, op1)                                                                                     \
+                  case op0 : result = node_allocator_->                                                                           \
+                                 template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \
+                                    (operation, branch[0], branch[1]);                                                            \
+                             node_name = "assignment_rebasevec_elem_op_rtc_node";                                                 \
+                             break;                                                                                               \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (details::is_rebasevector_celem_rtc_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
+
+               switch (operation)
+               {
+                  #define case_stmt(op0, op1)                                                                                      \
+                  case op0 : result = node_allocator_->                                                                            \
+                                 template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \
+                                    (operation, branch[0], branch[1]);                                                             \
+                             node_name = "assignment_rebasevec_celem_op_rtc_node";                                                 \
+                             break;                                                                                                \
+
+                  case_stmt(details::e_addass , details::add_op)
+                  case_stmt(details::e_subass , details::sub_op)
+                  case_stmt(details::e_mulass , details::mul_op)
+                  case_stmt(details::e_divass , details::div_op)
+                  case_stmt(details::e_modass , details::mod_op)
                   #undef case_stmt
                   default : return error_node();
                }
@@ -29211,16 +34452,18 @@ namespace exprtk
                {
                   switch (operation)
                   {
-                     #define case_stmt(op0,op1)                                                                         \
-                     case op0 : return node_allocator_->                                                                \
+                     #define case_stmt(op0, op1)                                                                        \
+                     case op0 : result = node_allocator_->                                                              \
                                    template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
                                       (operation, branch[0], branch[1]);                                                \
-
-                     case_stmt(details::e_addass,details::add_op)
-                     case_stmt(details::e_subass,details::sub_op)
-                     case_stmt(details::e_mulass,details::mul_op)
-                     case_stmt(details::e_divass,details::div_op)
-                     case_stmt(details::e_modass,details::mod_op)
+                                node_name = "assignment_rebasevec_celem_op_node";                                       \
+                                break;                                                                                  \
+
+                     case_stmt(details::e_addass , details::add_op)
+                     case_stmt(details::e_subass , details::sub_op)
+                     case_stmt(details::e_mulass , details::mul_op)
+                     case_stmt(details::e_divass , details::div_op)
+                     case_stmt(details::e_modass , details::mod_op)
                      #undef case_stmt
                      default : return error_node();
                   }
@@ -29229,16 +34472,18 @@ namespace exprtk
                {
                   switch (operation)
                   {
-                     #define case_stmt(op0,op1)                                                                      \
-                     case op0 : return node_allocator_->                                                             \
+                     #define case_stmt(op0, op1)                                                                     \
+                     case op0 : result = node_allocator_->                                                           \
                                    template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
                                       (operation, branch[0], branch[1]);                                             \
-
-                     case_stmt(details::e_addass,details::add_op)
-                     case_stmt(details::e_subass,details::sub_op)
-                     case_stmt(details::e_mulass,details::mul_op)
-                     case_stmt(details::e_divass,details::div_op)
-                     case_stmt(details::e_modass,details::mod_op)
+                                node_name = "assignment_vec_op_node";                                                \
+                                break;                                                                               \
+
+                     case_stmt(details::e_addass , details::add_op)
+                     case_stmt(details::e_subass , details::sub_op)
+                     case_stmt(details::e_mulass , details::mul_op)
+                     case_stmt(details::e_divass , details::div_op)
+                     case_stmt(details::e_modass , details::mod_op)
                      #undef case_stmt
                      default : return error_node();
                   }
@@ -29254,15 +34499,34 @@ namespace exprtk
 
                lodge_assignment(e_st_string,branch[0]);
 
-               return synthesize_expression<addass_t,2>(operation,branch);
+               result = synthesize_expression<addass_t,2>(operation,branch);
+               node_name = "assignment_string_node<T,details::asn_addassignment>";
             }
             #endif
             else
             {
-               parser_->set_synthesis_error("Invalid assignment operation[2]");
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_syntax,
+                  parser_->current_state().token,
+                  "ERR271 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
+                  exprtk_error_location));
 
                return error_node();
             }
+
+            if (result && result->valid())
+            {
+               return result;
+            }
+
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_synthesis,
+               token_t(),
+               "ERR272 - Failed to synthesize node: " + node_name,
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
          }
 
          inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
@@ -29271,29 +34535,34 @@ namespace exprtk
             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
 
-            #define batch_eqineq_logic_case                \
-            case_stmt(details::   e_lt, details::   lt_op) \
-            case_stmt(details::  e_lte, details::  lte_op) \
-            case_stmt(details::   e_gt, details::   gt_op) \
-            case_stmt(details::  e_gte, details::  gte_op) \
-            case_stmt(details::   e_eq, details::   eq_op) \
-            case_stmt(details::   e_ne, details::   ne_op) \
-            case_stmt(details::e_equal, details::equal_op) \
-            case_stmt(details::  e_and, details::  and_op) \
-            case_stmt(details:: e_nand, details:: nand_op) \
-            case_stmt(details::   e_or, details::   or_op) \
-            case_stmt(details::  e_nor, details::  nor_op) \
-            case_stmt(details::  e_xor, details::  xor_op) \
-            case_stmt(details:: e_xnor, details:: xnor_op) \
+            #define batch_eqineq_logic_case                 \
+            case_stmt(details::e_lt    , details::lt_op   ) \
+            case_stmt(details::e_lte   , details::lte_op  ) \
+            case_stmt(details::e_gt    , details::gt_op   ) \
+            case_stmt(details::e_gte   , details::gte_op  ) \
+            case_stmt(details::e_eq    , details::eq_op   ) \
+            case_stmt(details::e_ne    , details::ne_op   ) \
+            case_stmt(details::e_equal , details::equal_op) \
+            case_stmt(details::e_and   , details::and_op  ) \
+            case_stmt(details::e_nand  , details::nand_op ) \
+            case_stmt(details::e_or    , details::or_op   ) \
+            case_stmt(details::e_nor   , details::nor_op  ) \
+            case_stmt(details::e_xor   , details::xor_op  ) \
+            case_stmt(details::e_xnor  , details::xnor_op ) \
+
+            expression_node_ptr result = error_node();
+            std::string node_name = "Unknown";
 
             if (is_b0_ivec && is_b1_ivec)
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                     \
-                  case op0 : return node_allocator_->                                                            \
+                  #define case_stmt(op0, op1)                                                                    \
+                  case op0 : result = node_allocator_->                                                          \
                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                            \
+                             node_name = "vec_binop_vecvec_node";                                                \
+                             break;                                                                              \
 
                   batch_eqineq_logic_case
                   #undef case_stmt
@@ -29304,10 +34573,12 @@ namespace exprtk
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                     \
-                  case op0 : return node_allocator_->                                                            \
+                  #define case_stmt(op0, op1)                                                                    \
+                  case op0 : result = node_allocator_->                                                          \
                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                            \
+                             node_name = "vec_binop_vecval_node";                                                \
+                             break;                                                                              \
 
                   batch_eqineq_logic_case
                   #undef case_stmt
@@ -29318,10 +34589,12 @@ namespace exprtk
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                     \
-                  case op0 : return node_allocator_->                                                            \
+                  #define case_stmt(op0, op1)                                                                    \
+                  case op0 : result = node_allocator_->                                                          \
                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                            \
+                             node_name = "vec_binop_valvec_node";                                                \
+                             break;                                                                              \
 
                   batch_eqineq_logic_case
                   #undef case_stmt
@@ -29331,6 +34604,20 @@ namespace exprtk
             else
                return error_node();
 
+            if (result && result->valid())
+            {
+               return result;
+            }
+
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_synthesis,
+               token_t(),
+               "ERR273 - Failed to synthesize node: " + node_name,
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
+
             #undef batch_eqineq_logic_case
          }
 
@@ -29340,21 +34627,26 @@ namespace exprtk
             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
 
-            #define vector_ops                        \
-            case_stmt(details::e_add,details::add_op) \
-            case_stmt(details::e_sub,details::sub_op) \
-            case_stmt(details::e_mul,details::mul_op) \
-            case_stmt(details::e_div,details::div_op) \
-            case_stmt(details::e_mod,details::mod_op) \
+            #define vector_ops                          \
+            case_stmt(details::e_add , details::add_op) \
+            case_stmt(details::e_sub , details::sub_op) \
+            case_stmt(details::e_mul , details::mul_op) \
+            case_stmt(details::e_div , details::div_op) \
+            case_stmt(details::e_mod , details::mod_op) \
+
+            expression_node_ptr result = error_node();
+            std::string node_name = "Unknown";
 
             if (is_b0_ivec && is_b1_ivec)
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                     \
-                  case op0 : return node_allocator_->                                                            \
+                  #define case_stmt(op0, op1)                                                                    \
+                  case op0 : result = node_allocator_->                                                          \
                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                            \
+                             node_name = "vec_binop_vecvec_node";                                                \
+                             break;                                                                              \
 
                   vector_ops
                   case_stmt(details::e_pow,details:: pow_op)
@@ -29366,10 +34658,12 @@ namespace exprtk
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                     \
-                  case op0 : return node_allocator_->                                                            \
+                  #define case_stmt(op0, op1)                                                                    \
+                  case op0 : result = node_allocator_->                                                          \
                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                            \
+                             node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)";                                \
+                             break;                                                                              \
 
                   vector_ops
                   case_stmt(details::e_pow,details:: pow_op)
@@ -29381,10 +34675,12 @@ namespace exprtk
             {
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                                     \
-                  case op0 : return node_allocator_->                                                            \
+                  #define case_stmt(op0, op1)                                                                    \
+                  case op0 : result = node_allocator_->                                                          \
                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
                                    (operation, branch[0], branch[1]);                                            \
+                             node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)";                                \
+                             break;                                                                              \
 
                   vector_ops
                   #undef case_stmt
@@ -29394,6 +34690,20 @@ namespace exprtk
             else
                return error_node();
 
+            if (result && result->valid())
+            {
+               return result;
+            }
+
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_synthesis,
+               token_t(),
+               "ERR274 - Failed to synthesize node: " + node_name,
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
+
             #undef vector_ops
          }
 
@@ -29411,6 +34721,7 @@ namespace exprtk
             #endif
 
             expression_node_ptr result = error_node();
+            std::string node_name      = "Unknown";
 
             if (v0_is_ivar && v1_is_ivar)
             {
@@ -29424,36 +34735,57 @@ namespace exprtk
                     (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
                   )
                {
-                  result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
+                  result    = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
+                  node_name = "swap_node";
                }
                else
-                  result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
+               {
+                  result    = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
+                  node_name = "swap_generic_node";
+               }
             }
             else if (v0_is_ivec && v1_is_ivec)
             {
-               result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
+               result    = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
+               node_name = "swap_vecvec_node";
             }
             #ifndef exprtk_disable_string_capabilities
             else if (v0_is_str && v1_is_str)
             {
                if (is_string_node(branch[0]) && is_string_node(branch[1]))
+               {
                   result = node_allocator_->allocate<details::swap_string_node<T> >
                                                (branch[0], branch[1]);
+                  node_name = "swap_string_node";
+               }
                else
+               {
                   result = node_allocator_->allocate<details::swap_genstrings_node<T> >
                                                (branch[0], branch[1]);
+                  node_name = "swap_genstrings_node";
+               }
             }
             #endif
             else
             {
                parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
-
                return error_node();
             }
 
-            parser_->state_.activate_side_effect("synthesize_swap_expression()");
+            if (result && result->valid())
+            {
+               parser_->state_.activate_side_effect("synthesize_swap_expression()");
+               return result;
+            }
 
-            return result;
+            parser_->set_error(parser_error::make_error(
+               parser_error::e_synthesis,
+               token_t(),
+               "ERR275 - Failed to synthesize node: " + node_name,
+               exprtk_error_location));
+
+            details::free_node(*node_allocator_, result);
+            return error_node();
          }
 
          #ifndef exprtk_disable_sc_andor
@@ -29491,8 +34823,8 @@ namespace exprtk
 
             if (result)
             {
-               free_node(*node_allocator_, branch[0]);
-               free_node(*node_allocator_, branch[1]);
+               details::free_node(*node_allocator_, branch[0]);
+               details::free_node(*node_allocator_, branch[1]);
 
                return result;
             }
@@ -29514,27 +34846,27 @@ namespace exprtk
          }
          #endif
 
-         #define basic_opr_switch_statements        \
-         case_stmt(details::e_add, details::add_op) \
-         case_stmt(details::e_sub, details::sub_op) \
-         case_stmt(details::e_mul, details::mul_op) \
-         case_stmt(details::e_div, details::div_op) \
-         case_stmt(details::e_mod, details::mod_op) \
-         case_stmt(details::e_pow, details::pow_op) \
-
-         #define extended_opr_switch_statements       \
-         case_stmt(details::  e_lt, details::  lt_op) \
-         case_stmt(details:: e_lte, details:: lte_op) \
-         case_stmt(details::  e_gt, details::  gt_op) \
-         case_stmt(details:: e_gte, details:: gte_op) \
-         case_stmt(details::  e_eq, details::  eq_op) \
-         case_stmt(details::  e_ne, details::  ne_op) \
-         case_stmt(details:: e_and, details:: and_op) \
-         case_stmt(details::e_nand, details::nand_op) \
-         case_stmt(details::  e_or, details::  or_op) \
-         case_stmt(details:: e_nor, details:: nor_op) \
-         case_stmt(details:: e_xor, details:: xor_op) \
-         case_stmt(details::e_xnor, details::xnor_op) \
+         #define basic_opr_switch_statements         \
+         case_stmt(details::e_add , details::add_op) \
+         case_stmt(details::e_sub , details::sub_op) \
+         case_stmt(details::e_mul , details::mul_op) \
+         case_stmt(details::e_div , details::div_op) \
+         case_stmt(details::e_mod , details::mod_op) \
+         case_stmt(details::e_pow , details::pow_op) \
+
+         #define extended_opr_switch_statements        \
+         case_stmt(details::e_lt   , details::lt_op  ) \
+         case_stmt(details::e_lte  , details::lte_op ) \
+         case_stmt(details::e_gt   , details::gt_op  ) \
+         case_stmt(details::e_gte  , details::gte_op ) \
+         case_stmt(details::e_eq   , details::eq_op  ) \
+         case_stmt(details::e_ne   , details::ne_op  ) \
+         case_stmt(details::e_and  , details::and_op ) \
+         case_stmt(details::e_nand , details::nand_op) \
+         case_stmt(details::e_or   , details::or_op  ) \
+         case_stmt(details::e_nor  , details::nor_op ) \
+         case_stmt(details::e_xor  , details::xor_op ) \
+         case_stmt(details::e_xnor , details::xnor_op) \
 
          #ifndef exprtk_disable_cardinal_pow_optimisation
          template <typename TType, template <typename, typename> class IPowNode>
@@ -29609,7 +34941,7 @@ namespace exprtk
             else if (not_recipricol)
                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
             else
-               return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
+               return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p);
          }
          #else
          inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
@@ -29765,7 +35097,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                           \
+                  #define case_stmt(op0, op1)                                                          \
                   case op0 : return expr_gen.node_allocator_->                                         \
                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
                                    (branch[0], branch[1]);                                             \
@@ -29797,7 +35129,7 @@ namespace exprtk
 
                   if (synthesis_result)
                   {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
+                     details::free_node(*expr_gen.node_allocator_,branch[1]);
                      return result;
                   }
                }
@@ -29818,7 +35150,7 @@ namespace exprtk
                      {
                         const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
 
                         switch (operation)
                         {
@@ -29840,7 +35172,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
                                    (v, branch[1]);                                                 \
@@ -29872,7 +35204,7 @@ namespace exprtk
 
                   if (synthesis_result)
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
 
                      return result;
                   }
@@ -29896,7 +35228,7 @@ namespace exprtk
                      {
                         const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
 
-                        free_node(*expr_gen.node_allocator_,branch[0]);
+                        details::free_node(*expr_gen.node_allocator_,branch[0]);
 
                         switch (operation)
                         {
@@ -29926,7 +35258,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
                                    (branch[0], v);                                                 \
@@ -29947,17 +35279,17 @@ namespace exprtk
             {
                const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
 
-               free_node(*expr_gen.node_allocator_,branch[0]);
+               details::free_node(*expr_gen.node_allocator_,branch[0]);
 
                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
                {
-                  free_node(*expr_gen.node_allocator_,branch[1]);
+                  details::free_node(*expr_gen.node_allocator_,branch[1]);
 
                   return expr_gen(T(0));
                }
                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
                {
-                  free_node(*expr_gen.node_allocator_, branch[1]);
+                  details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                   return expr_gen(T(0));
                }
@@ -29972,8 +35304,8 @@ namespace exprtk
                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
                   if (
-                       (operation == details::e_mul) ||
-                       (operation == details::e_add)
+                       (details::e_mul == operation) ||
+                       (details::e_add == operation)
                      )
                   {
                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
@@ -30038,7 +35370,7 @@ namespace exprtk
                            default             : return error_node();
                         }
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
 
                         return new_cobnode;
                      }
@@ -30055,7 +35387,7 @@ namespace exprtk
 
                   if (synthesis_result)
                   {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
+                     details::free_node(*expr_gen.node_allocator_,branch[1]);
 
                      return result;
                   }
@@ -30064,7 +35396,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
                                    (c,  branch[1]);                                                \
@@ -30089,13 +35421,13 @@ namespace exprtk
 
                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
                {
-                  free_node(*expr_gen.node_allocator_, branch[0]);
+                  details::free_node(*expr_gen.node_allocator_, branch[0]);
 
                   return expr_gen(T(0));
                }
                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
                {
-                  free_node(*expr_gen.node_allocator_, branch[0]);
+                  details::free_node(*expr_gen.node_allocator_, branch[0]);
 
                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
                }
@@ -30110,8 +35442,8 @@ namespace exprtk
                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
                   if (
-                       (operation == details::e_mul) ||
-                       (operation == details::e_add)
+                       (details::e_mul == operation) ||
+                       (details::e_add == operation)
                      )
                   {
                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
@@ -30183,7 +35515,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
                                    (branch[0], c);                                                 \
@@ -30213,33 +35545,33 @@ namespace exprtk
 
                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return expr_gen(T(0));
                   }
                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
                   }
                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return branch[0];
                   }
                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return branch[0];
                   }
                   else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return branch[0];
                   }
@@ -30282,13 +35614,13 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
                                        (cobnode->c() / c, cobnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_, branch[0]);
+                        details::free_node(*expr_gen.node_allocator_, branch[0]);
                      }
                   }
 
                   if (result)
                   {
-                     free_node(*expr_gen.node_allocator_,branch[1]);
+                     details::free_node(*expr_gen.node_allocator_,branch[1]);
                   }
                }
 
@@ -30301,27 +35633,27 @@ namespace exprtk
 
                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return expr_gen(T(0));
                   }
                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
 
                      return expr_gen(T(0));
                   }
                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
 
                      return branch[1];
                   }
                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
                   {
-                     free_node(*expr_gen.node_allocator_, branch[0]);
+                     details::free_node(*expr_gen.node_allocator_, branch[0]);
 
                      return branch[1];
                   }
@@ -30339,7 +35671,7 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
                                        (c - cobnode->c(), cobnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
                   else if (details::e_sub == cobnode->operation())
@@ -30355,7 +35687,7 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
                                        (c - cobnode->c(), cobnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
                   else if (details::e_mul == cobnode->operation())
@@ -30371,7 +35703,7 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
                                        (c / cobnode->c(), cobnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
                   else if (details::e_div == cobnode->operation())
@@ -30387,13 +35719,13 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
                                        (c / cobnode->c(), cobnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
 
                   if (result)
                   {
-                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     details::free_node(*expr_gen.node_allocator_,branch[0]);
                   }
                }
 
@@ -30446,7 +35778,7 @@ namespace exprtk
                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
                                        (bocnode->move_branch(0), c - bocnode->c());
 
-                        free_node(*expr_gen.node_allocator_,branch[0]);
+                        details::free_node(*expr_gen.node_allocator_,branch[0]);
                      }
                      else if (details::e_sub == operation)
                      {
@@ -30468,7 +35800,7 @@ namespace exprtk
 
                   if (result)
                   {
-                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     details::free_node(*expr_gen.node_allocator_, branch[1]);
                   }
                }
 
@@ -30492,7 +35824,7 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
                                        (c - bocnode->c(), bocnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
                   else if (details::e_sub == bocnode->operation())
@@ -30503,7 +35835,7 @@ namespace exprtk
                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
                                        (bocnode->move_branch(0), c - bocnode->c());
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                      else if (details::e_sub == operation)
                      {
@@ -30511,7 +35843,7 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
                                        (c + bocnode->c(), bocnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
                   else if (details::e_mul == bocnode->operation())
@@ -30527,7 +35859,7 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
                                        (c / bocnode->c(), bocnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
                   else if (details::e_div == bocnode->operation())
@@ -30543,13 +35875,13 @@ namespace exprtk
                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
                                        (c * bocnode->c(), bocnode->move_branch(0));
 
-                        free_node(*expr_gen.node_allocator_,branch[1]);
+                        details::free_node(*expr_gen.node_allocator_,branch[1]);
                      }
                   }
 
                   if (result)
                   {
-                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     details::free_node(*expr_gen.node_allocator_,branch[0]);
                   }
                }
 
@@ -30592,7 +35924,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
                                    (v1, v2);                                                       \
@@ -30627,7 +35959,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
                                    (c, v);                                                         \
@@ -30671,7 +36003,7 @@ namespace exprtk
 
                switch (operation)
                {
-                  #define case_stmt(op0,op1)                                                       \
+                  #define case_stmt(op0, op1)                                                      \
                   case op0 : return expr_gen.node_allocator_->                                     \
                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
                                    (v, c);                                                         \
@@ -30740,7 +36072,6 @@ namespace exprtk
                   case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                        \
 
-
                   #define case_stmt1(op)                                                                                             \
                   case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                               \
@@ -30941,9 +36272,6 @@ namespace exprtk
                const details::operator_type o0 = vov->operation();
                const details::operator_type o1 = operation;
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
 
                expression_node_ptr result = error_node();
@@ -30955,7 +36283,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
+                           template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
 
                      exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
 
@@ -30969,7 +36297,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -30978,12 +36310,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "t";
             }
          };
 
@@ -31004,9 +36337,6 @@ namespace exprtk
                const details::operator_type o0 = operation;
                const details::operator_type o1 = vov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
                expression_node_ptr result = error_node();
@@ -31018,7 +36348,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
+                           template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
 
                      exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
 
@@ -31032,7 +36362,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31041,12 +36375,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)";
             }
          };
 
@@ -31067,9 +36402,6 @@ namespace exprtk
                const details::operator_type o0 = vov->operation();
                const details::operator_type o1 = operation;
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31082,7 +36414,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
+                           template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
 
                      exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
 
@@ -31096,7 +36428,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31105,12 +36441,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "t";
             }
          };
 
@@ -31131,9 +36468,6 @@ namespace exprtk
                const details::operator_type o0 = operation;
                const details::operator_type o1 = voc->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
                expression_node_ptr result = error_node();
@@ -31145,7 +36479,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
+                           template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
 
                      exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
 
@@ -31159,7 +36493,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31168,12 +36506,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)";
             }
          };
 
@@ -31194,9 +36533,6 @@ namespace exprtk
                const details::operator_type o0 = voc->operation();
                const details::operator_type o1 = operation;
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
 
                expression_node_ptr result = error_node();
@@ -31208,7 +36544,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
+                           template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
 
                      exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
 
@@ -31222,7 +36558,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31231,12 +36571,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "t";
             }
          };
 
@@ -31257,9 +36598,6 @@ namespace exprtk
                const details::operator_type o0 = operation;
                const details::operator_type o1 = cov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
                expression_node_ptr result = error_node();
@@ -31285,7 +36623,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31294,12 +36636,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)";
             }
          };
 
@@ -31320,9 +36663,6 @@ namespace exprtk
                const details::operator_type o0 = cov->operation();
                const details::operator_type o1 = operation;
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
 
                expression_node_ptr result = error_node();
@@ -31348,7 +36688,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31357,12 +36701,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "t";
             }
          };
 
@@ -31383,9 +36728,6 @@ namespace exprtk
                const details::operator_type o0 = operation;
                const details::operator_type o1 = vov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31412,7 +36754,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31420,12 +36766,14 @@ namespace exprtk
                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
             }
 
-            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)";
             }
          };
 
@@ -31446,9 +36794,6 @@ namespace exprtk
                const details::operator_type o0 = cov->operation();
                const details::operator_type o1 = operation;
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31528,7 +36873,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31537,12 +36886,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "t";
             }
          };
 
@@ -31563,9 +36913,6 @@ namespace exprtk
                const details::operator_type o0 = operation;
                const details::operator_type o1 = voc->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31645,7 +36992,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31654,19 +37005,22 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)";
             }
          };
 
          struct synthesize_cocov_expression0
          {
             typedef typename cocov_t::type0 node_type;
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            static inline expression_node_ptr process(expression_generator<Type>&,
+                                                      const details::operator_type&,
+                                                      expression_node_ptr (&)[2])
             {
                // (c0 o0 c1) o1 (v) - Not possible.
                return error_node();
@@ -31690,9 +37044,6 @@ namespace exprtk
                const details::operator_type o0 = operation;
                const details::operator_type o1 = cov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31772,7 +37123,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31780,12 +37135,14 @@ namespace exprtk
                   return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
             }
 
-            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)";
             }
          };
 
@@ -31806,9 +37163,6 @@ namespace exprtk
                const details::operator_type o0 = voc->operation();
                const details::operator_type o1 = operation;
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31896,7 +37250,11 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -31905,12 +37263,13 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
-                                         const details::operator_type o0, const details::operator_type o1)
+                                         const details::operator_type o0,
+                                         const details::operator_type o1)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "t";
             }
          };
 
@@ -31918,7 +37277,9 @@ namespace exprtk
          {
             typedef typename vococ_t::type0 node_type;
 
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            static inline expression_node_ptr process(expression_generator<Type>&,
+                                                      const details::operator_type&,
+                                                      expression_node_ptr (&)[2])
             {
                // (v) o0 (c0 o1 c1) - Not possible.
                exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
@@ -31950,10 +37311,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = vov1->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -31966,7 +37323,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
+                           template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
 
                      exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
 
@@ -31977,7 +37334,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
+                           template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
 
                      exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
 
@@ -31988,7 +37345,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
+                           template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
 
                      exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
 
@@ -31999,7 +37356,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
+                           template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
 
                      exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
 
@@ -32010,7 +37367,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
+                           template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
 
                      exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
 
@@ -32024,7 +37381,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32040,10 +37402,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32071,10 +37433,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = voc->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32087,7 +37445,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
+                           template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
 
                      exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
 
@@ -32098,7 +37456,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
+                           template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
 
                      exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
 
@@ -32112,7 +37470,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32128,10 +37491,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32159,10 +37522,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = cov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32175,7 +37534,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
+                           template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
 
                      exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
 
@@ -32186,7 +37545,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
+                           template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
 
                      exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
 
@@ -32200,7 +37559,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32216,10 +37580,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32247,10 +37611,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = vov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32263,7 +37623,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
+                           template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
 
                      exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
 
@@ -32274,7 +37634,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
+                           template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
 
                      exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
 
@@ -32288,7 +37648,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32304,10 +37669,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32335,10 +37700,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = vov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32351,7 +37712,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
+                           template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
 
                      exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
 
@@ -32362,7 +37723,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
+                           template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
 
                      exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
 
@@ -32376,7 +37737,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32392,10 +37758,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32423,10 +37789,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = cov1->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32439,7 +37801,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
 
                      exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
 
@@ -32450,7 +37812,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
 
                      exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
 
@@ -32461,7 +37823,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
 
                      exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
 
@@ -32472,7 +37834,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
 
@@ -32483,7 +37845,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
 
@@ -32494,7 +37856,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
 
@@ -32505,7 +37867,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
 
                      exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
 
@@ -32516,7 +37878,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
 
@@ -32527,7 +37889,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
 
@@ -32569,7 +37931,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32585,10 +37952,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32616,10 +37983,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = voc1->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32632,7 +37995,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
 
                      exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
 
@@ -32643,7 +38006,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
 
                      exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
 
@@ -32654,7 +38017,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
 
                      exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
 
@@ -32665,7 +38028,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
 
@@ -32676,7 +38039,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
 
@@ -32687,7 +38050,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
 
@@ -32698,7 +38061,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
 
                      exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
 
@@ -32709,7 +38072,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
 
@@ -32720,7 +38083,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
 
@@ -32731,7 +38094,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
+                           template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
 
                      exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
 
@@ -32742,7 +38105,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf4ext_expression::
-                           template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
+                           template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
 
                      exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
 
@@ -32770,7 +38133,7 @@ namespace exprtk
 
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
 
                      exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
 
@@ -32798,7 +38161,7 @@ namespace exprtk
 
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
+                           template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result);
 
                      exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
 
@@ -32812,7 +38175,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -32828,10 +38196,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -32859,10 +38227,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = voc->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -32875,7 +38239,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
 
                      exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
 
@@ -32886,7 +38250,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
 
                      exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
 
@@ -32897,7 +38261,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
 
                      exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
 
@@ -32908,7 +38272,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
 
@@ -32919,7 +38283,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
 
@@ -32930,7 +38294,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
 
                      exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
 
@@ -32941,7 +38305,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
 
@@ -32952,7 +38316,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
 
@@ -32963,7 +38327,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
 
@@ -32991,7 +38355,7 @@ namespace exprtk
 
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
 
                      exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
 
@@ -33005,7 +38369,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -33021,10 +38390,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -33052,10 +38421,6 @@ namespace exprtk
                const details::operator_type o1 = operation;
                const details::operator_type o2 = cov->operation();
 
-               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
-               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
-
                details::free_node(*(expr_gen.node_allocator_),branch[0]);
                details::free_node(*(expr_gen.node_allocator_),branch[1]);
 
@@ -33068,7 +38433,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
 
                      exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
 
@@ -33079,7 +38444,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
 
                      exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
 
@@ -33090,7 +38455,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
+                           template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
 
                      exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
 
@@ -33101,7 +38466,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
 
@@ -33112,7 +38477,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
 
@@ -33123,7 +38488,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
 
                      exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
 
@@ -33134,7 +38499,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
 
                      exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
 
@@ -33145,7 +38510,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
 
                      exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
 
@@ -33156,7 +38521,7 @@ namespace exprtk
                   {
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
+                           template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
 
                      exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
 
@@ -33183,7 +38548,7 @@ namespace exprtk
 
                      const bool synthesis_result =
                         synthesize_sf3ext_expression::
-                           template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
+                           template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
 
                      exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
 
@@ -33197,7 +38562,12 @@ namespace exprtk
 
                if (synthesis_result)
                   return result;
-               else if (!expr_gen.valid_operator(o0,f0))
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
                else if (!expr_gen.valid_operator(o1,f1))
                   return error_node();
@@ -33213,10 +38583,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "t)" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t)";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "t)" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -33253,14 +38623,18 @@ namespace exprtk
 
                expression_node_ptr result = error_node();
 
-               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+               const bool synthesis_result =
+                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
+                     (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
+
+               if (synthesis_result)
                   return result;
                else if (!expr_gen.valid_operator(o0,f0))
                   return error_node();
 
                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
 
-               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
             }
 
             static inline std::string id(expression_generator<Type>& expr_gen,
@@ -33269,10 +38643,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33329,10 +38703,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33389,10 +38763,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33449,10 +38823,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33510,10 +38884,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33571,10 +38945,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33631,10 +39005,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33691,10 +39065,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33751,10 +39125,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"  << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "(t" << expr_gen.to_str(o2)
-                         << "t))";
+                  << "t"  << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "(t" << expr_gen.to_str(o2)
+                  << "t))";
             }
          };
 
@@ -33811,10 +39185,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -33871,10 +39245,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -33931,10 +39305,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -33991,10 +39365,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -34052,10 +39426,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
         };
 
@@ -34113,10 +39487,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -34173,10 +39547,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
@@ -34234,17 +39608,19 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "t"   << expr_gen.to_str(o0)
-                         << "((t" << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t)";
+                  << "t"   << expr_gen.to_str(o0)
+                  << "((t" << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t)";
             }
          };
 
          struct synthesize_vococov_expression2
          {
             typedef typename vococov_t::type2 node_type;
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            static inline expression_node_ptr process(expression_generator<Type>&,
+                                                      const details::operator_type&,
+                                                      expression_node_ptr (&)[2])
             {
                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
                exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
@@ -34252,7 +39628,9 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>&,
-                                         const details::operator_type, const details::operator_type, const details::operator_type)
+                                         const details::operator_type,
+                                         const details::operator_type,
+                                         const details::operator_type)
             {
                return "INVALID";
             }
@@ -34311,10 +39689,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34372,10 +39750,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34432,10 +39810,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34492,10 +39870,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34552,10 +39930,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34612,10 +39990,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34673,10 +40051,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34734,10 +40112,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34794,10 +40172,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "((t" << expr_gen.to_str(o0)
-                         << "t)"  << expr_gen.to_str(o1)
-                         << "t)"  << expr_gen.to_str(o2)
-                         << "t";
+                  << "((t" << expr_gen.to_str(o0)
+                  << "t)"  << expr_gen.to_str(o1)
+                  << "t)"  << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34854,10 +40232,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34915,10 +40293,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -34975,10 +40353,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -35034,10 +40412,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -35094,10 +40472,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -35154,10 +40532,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -35215,10 +40593,10 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
@@ -35276,17 +40654,19 @@ namespace exprtk
                                          const details::operator_type o2)
             {
                return details::build_string()
-                         << "(t" << expr_gen.to_str(o0)
-                         << "(t" << expr_gen.to_str(o1)
-                         << "t)" << expr_gen.to_str(o2)
-                         << "t";
+                  << "(t" << expr_gen.to_str(o0)
+                  << "(t" << expr_gen.to_str(o1)
+                  << "t)" << expr_gen.to_str(o2)
+                  << "t";
             }
          };
 
          struct synthesize_vococov_expression4
          {
             typedef typename vococov_t::type4 node_type;
-            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            static inline expression_node_ptr process(expression_generator<Type>&,
+                                                      const details::operator_type&,
+                                                      expression_node_ptr (&)[2])
             {
                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
                exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
@@ -35294,7 +40674,9 @@ namespace exprtk
             }
 
             static inline std::string id(expression_generator<Type>&,
-                                         const details::operator_type, const details::operator_type, const details::operator_type)
+                                         const details::operator_type,
+                                         const details::operator_type,
+                                         const details::operator_type)
             {
                return "INVALID";
             }
@@ -35377,16 +40759,16 @@ namespace exprtk
 
          #ifndef exprtk_disable_string_capabilities
 
-         #define string_opr_switch_statements          \
-         case_stmt(details::  e_lt ,details::   lt_op) \
-         case_stmt(details:: e_lte ,details::  lte_op) \
-         case_stmt(details::  e_gt ,details::   gt_op) \
-         case_stmt(details:: e_gte ,details::  gte_op) \
-         case_stmt(details::  e_eq ,details::   eq_op) \
-         case_stmt(details::  e_ne ,details::   ne_op) \
-         case_stmt(details::e_in   ,details::   in_op) \
-         case_stmt(details::e_like ,details:: like_op) \
-         case_stmt(details::e_ilike,details::ilike_op) \
+         #define string_opr_switch_statements            \
+         case_stmt(details::e_lt    , details::lt_op   ) \
+         case_stmt(details::e_lte   , details::lte_op  ) \
+         case_stmt(details::e_gt    , details::gt_op   ) \
+         case_stmt(details::e_gte   , details::gte_op  ) \
+         case_stmt(details::e_eq    , details::eq_op   ) \
+         case_stmt(details::e_ne    , details::ne_op   ) \
+         case_stmt(details::e_in    , details::in_op   ) \
+         case_stmt(details::e_like  , details::like_op ) \
+         case_stmt(details::e_ilike , details::ilike_op) \
 
          template <typename T0, typename T1>
          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
@@ -35395,7 +40777,7 @@ namespace exprtk
          {
             switch (opr)
             {
-               #define case_stmt(op0,op1)                                                                       \
+               #define case_stmt(op0, op1)                                                                      \
                case op0 : return node_allocator_->                                                              \
                              allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
                                 (s0, s1, rp0);                                                                  \
@@ -35413,7 +40795,7 @@ namespace exprtk
          {
             switch (opr)
             {
-               #define case_stmt(op0,op1)                                                                       \
+               #define case_stmt(op0, op1)                                                                      \
                case op0 : return node_allocator_->                                                              \
                              allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
                                 (s0, s1, rp1);                                                                  \
@@ -35431,7 +40813,7 @@ namespace exprtk
          {
             switch (opr)
             {
-               #define case_stmt(op0,op1)                                                                         \
+               #define case_stmt(op0, op1)                                                                        \
                case op0 : return node_allocator_->                                                                \
                              allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
                                 (s0, s1, rp0, rp1);                                                               \
@@ -35447,7 +40829,7 @@ namespace exprtk
          {
             switch (opr)
             {
-               #define case_stmt(op0,op1)                                                                  \
+               #define case_stmt(op0, op1)                                                                 \
                case op0 : return node_allocator_->                                                         \
                              allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
 
@@ -35473,7 +40855,7 @@ namespace exprtk
 
             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
 
-            free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[0]);
 
             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
          }
@@ -35486,7 +40868,7 @@ namespace exprtk
 
             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
 
-            free_node(*node_allocator_,branch[1]);
+            details::free_node(*node_allocator_,branch[1]);
 
             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
          }
@@ -35499,7 +40881,7 @@ namespace exprtk
 
             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
 
-            free_node(*node_allocator_,branch[1]);
+            details::free_node(*node_allocator_,branch[1]);
 
             return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
          }
@@ -35533,7 +40915,7 @@ namespace exprtk
          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
             std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-            std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+            std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
 
             details::free_node(*node_allocator_,branch[0]);
 
@@ -35542,9 +40924,9 @@ namespace exprtk
 
          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
-            std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
-            std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();
-            range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();
+            std::string  s0  = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
+            std::string& s1  = static_cast<details::string_range_node<Type>*  >(branch[1])->ref  ();
+            range_t      rp1 = static_cast<details::string_range_node<Type>*  >(branch[1])->range();
 
             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
 
@@ -35556,9 +40938,9 @@ namespace exprtk
 
          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
-            std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();
+            std::string&  s0 = static_cast<details::string_range_node<Type>*  >(branch[0])->ref  ();
             std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
-            range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();
+            range_t      rp0 = static_cast<details::string_range_node<Type>*  >(branch[0])->range();
 
             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
 
@@ -35570,9 +40952,9 @@ namespace exprtk
 
          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
-            std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();
+            std::string&  s0 = static_cast<details::string_range_node<Type>*      >(branch[0])->ref  ();
             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
-            range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();
+            range_t      rp0 = static_cast<details::string_range_node<Type>*      >(branch[0])->range();
             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
 
             static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
@@ -35617,14 +40999,14 @@ namespace exprtk
 
          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
-            const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();
+            const std::string s0 = static_cast<details::string_literal_node<Type>*    >(branch[0])->str  ();
                   std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
             range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
 
-            free_node(*node_allocator_,branch[0]);
-            free_node(*node_allocator_,branch[1]);
+            details::free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[1]);
 
             return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
          }
@@ -35632,12 +41014,12 @@ namespace exprtk
          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
             std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
-            std::string&  s1 = static_cast<details::stringvar_node<Type>*>         (branch[1])->ref  ();
+            std::string&  s1 = static_cast<details::stringvar_node<Type>*         >(branch[1])->ref  ();
             range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
 
-            free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[0]);
 
             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
          }
@@ -35645,15 +41027,15 @@ namespace exprtk
          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
             const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
-                  std::string& s1 = static_cast<details::string_range_node<Type>*>      (branch[1])->ref  ();
+                  std::string& s1 = static_cast<details::string_range_node<Type>*      >(branch[1])->ref  ();
             const range_t     rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
-            const range_t     rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();
+            const range_t     rp1 = static_cast<details::string_range_node<Type>*      >(branch[1])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
             static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
 
-            free_node(*node_allocator_,branch[0]);
-            free_node(*node_allocator_,branch[1]);
+            details::free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[1]);
 
             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
          }
@@ -35661,7 +41043,7 @@ namespace exprtk
          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
          {
             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
-            const std::string s1 = static_cast<details::string_literal_node<Type>*>    (branch[1])->str  ();
+            const std::string s1 = static_cast<details::string_literal_node<Type>*    >(branch[1])->str  ();
             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
 
             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
@@ -35690,7 +41072,7 @@ namespace exprtk
          {
             switch (opr)
             {
-               #define case_stmt(op0,op1)                                                       \
+               #define case_stmt(op0, op1)                                                      \
                case op0 : return node_allocator_->                                              \
                              allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
                                 (opr, branch[0], branch[1]);                                    \
@@ -35700,6 +41082,8 @@ namespace exprtk
                default : return error_node();
             }
          }
+
+         #undef string_opr_switch_statements
          #endif
 
          #ifndef exprtk_disable_string_capabilities
@@ -35752,28 +41136,28 @@ namespace exprtk
             }
             else if (b0_is_s)
             {
-                    if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
+               if      (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
                else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
                else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
                else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
             }
             else if (b0_is_cs)
             {
-                    if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
+               if      (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
             }
             else if (b0_is_sr)
             {
-                    if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
+               if      (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
             }
             else if (b0_is_csr)
             {
-                    if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
+               if      (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
@@ -35837,7 +41221,7 @@ namespace exprtk
                     )
             {
                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+               std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
 
                typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
@@ -35853,9 +41237,9 @@ namespace exprtk
                             details::is_string_node(branch[2])
                     )
             {
-               std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+               std::string&  s0 = static_cast<details::stringvar_node<Type>*     >(branch[0])->ref();
                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
-               std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
+               std::string&  s2 = static_cast<details::stringvar_node<Type>*     >(branch[2])->ref();
 
                typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
 
@@ -35869,8 +41253,8 @@ namespace exprtk
                       details::is_const_string_node(branch[2])
                     )
             {
-               std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
-               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+               std::string& s0 = static_cast<details::stringvar_node<Type>*     >(branch[0])->ref();
+               std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
 
                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
@@ -35886,8 +41270,8 @@ namespace exprtk
                     )
             {
                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
-               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
-               std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
+               std::string& s1 = static_cast<details::stringvar_node<Type>*     >(branch[1])->ref();
+               std::string& s2 = static_cast<details::stringvar_node<Type>*     >(branch[2])->ref();
 
                typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
 
@@ -36033,11 +41417,22 @@ namespace exprtk
 
                   return node_allocator_->allocate<literal_node_t>(v);
                }
-               else
+
+               if (expression_point && expression_point->valid())
+               {
                   return expression_point;
+               }
+
+               parser_->set_error(parser_error::make_error(
+                  parser_error::e_parser,
+                  token_t(),
+                  "ERR276 - Failed to synthesize node: NodeType",
+                  exprtk_error_location));
+
+               details::free_node(*node_allocator_, expression_point);
             }
-            else
-               return error_node();
+
+            return error_node();
          }
 
          template <typename NodeType, std::size_t N>
@@ -36088,7 +41483,7 @@ namespace exprtk
          sf3_map_t*               sf3_map_;
          sf4_map_t*               sf4_map_;
          parser_t*                parser_;
-      };
+      }; // class expression_generator
 
       inline void set_error(const parser_error::type& error_type)
       {
@@ -36117,8 +41512,11 @@ namespace exprtk
          {
             scope_element& se = sem_.get_element(i);
 
+            exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str()));
+
             if (
                  (scope_element::e_variable == se.type) ||
+                 (scope_element::e_literal  == se.type) ||
                  (scope_element::e_vecelem  == se.type)
                )
             {
@@ -36178,48 +41576,48 @@ namespace exprtk
 
       inline void load_unary_operations_map(unary_op_map_t& m)
       {
-         #define register_unary_op(Op,UnaryFunctor)             \
+         #define register_unary_op(Op, UnaryFunctor)            \
          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
 
-         register_unary_op(details::  e_abs, details::  abs_op)
-         register_unary_op(details:: e_acos, details:: acos_op)
-         register_unary_op(details::e_acosh, details::acosh_op)
-         register_unary_op(details:: e_asin, details:: asin_op)
-         register_unary_op(details::e_asinh, details::asinh_op)
-         register_unary_op(details::e_atanh, details::atanh_op)
-         register_unary_op(details:: e_ceil, details:: ceil_op)
-         register_unary_op(details::  e_cos, details::  cos_op)
-         register_unary_op(details:: e_cosh, details:: cosh_op)
-         register_unary_op(details::  e_exp, details::  exp_op)
-         register_unary_op(details::e_expm1, details::expm1_op)
-         register_unary_op(details::e_floor, details::floor_op)
-         register_unary_op(details::  e_log, details::  log_op)
-         register_unary_op(details::e_log10, details::log10_op)
-         register_unary_op(details:: e_log2, details:: log2_op)
-         register_unary_op(details::e_log1p, details::log1p_op)
-         register_unary_op(details::  e_neg, details::  neg_op)
-         register_unary_op(details::  e_pos, details::  pos_op)
-         register_unary_op(details::e_round, details::round_op)
-         register_unary_op(details::  e_sin, details::  sin_op)
-         register_unary_op(details:: e_sinc, details:: sinc_op)
-         register_unary_op(details:: e_sinh, details:: sinh_op)
-         register_unary_op(details:: e_sqrt, details:: sqrt_op)
-         register_unary_op(details::  e_tan, details::  tan_op)
-         register_unary_op(details:: e_tanh, details:: tanh_op)
-         register_unary_op(details::  e_cot, details::  cot_op)
-         register_unary_op(details::  e_sec, details::  sec_op)
-         register_unary_op(details::  e_csc, details::  csc_op)
-         register_unary_op(details::  e_r2d, details::  r2d_op)
-         register_unary_op(details::  e_d2r, details::  d2r_op)
-         register_unary_op(details::  e_d2g, details::  d2g_op)
-         register_unary_op(details::  e_g2d, details::  g2d_op)
-         register_unary_op(details:: e_notl, details:: notl_op)
-         register_unary_op(details::  e_sgn, details::  sgn_op)
-         register_unary_op(details::  e_erf, details::  erf_op)
-         register_unary_op(details:: e_erfc, details:: erfc_op)
-         register_unary_op(details:: e_ncdf, details:: ncdf_op)
-         register_unary_op(details:: e_frac, details:: frac_op)
-         register_unary_op(details::e_trunc, details::trunc_op)
+         register_unary_op(details::e_abs   , details::abs_op  )
+         register_unary_op(details::e_acos  , details::acos_op )
+         register_unary_op(details::e_acosh , details::acosh_op)
+         register_unary_op(details::e_asin  , details::asin_op )
+         register_unary_op(details::e_asinh , details::asinh_op)
+         register_unary_op(details::e_atanh , details::atanh_op)
+         register_unary_op(details::e_ceil  , details::ceil_op )
+         register_unary_op(details::e_cos   , details::cos_op  )
+         register_unary_op(details::e_cosh  , details::cosh_op )
+         register_unary_op(details::e_exp   , details::exp_op  )
+         register_unary_op(details::e_expm1 , details::expm1_op)
+         register_unary_op(details::e_floor , details::floor_op)
+         register_unary_op(details::e_log   , details::log_op  )
+         register_unary_op(details::e_log10 , details::log10_op)
+         register_unary_op(details::e_log2  , details::log2_op )
+         register_unary_op(details::e_log1p , details::log1p_op)
+         register_unary_op(details::e_neg   , details::neg_op  )
+         register_unary_op(details::e_pos   , details::pos_op  )
+         register_unary_op(details::e_round , details::round_op)
+         register_unary_op(details::e_sin   , details::sin_op  )
+         register_unary_op(details::e_sinc  , details::sinc_op )
+         register_unary_op(details::e_sinh  , details::sinh_op )
+         register_unary_op(details::e_sqrt  , details::sqrt_op )
+         register_unary_op(details::e_tan   , details::tan_op  )
+         register_unary_op(details::e_tanh  , details::tanh_op )
+         register_unary_op(details::e_cot   , details::cot_op  )
+         register_unary_op(details::e_sec   , details::sec_op  )
+         register_unary_op(details::e_csc   , details::csc_op  )
+         register_unary_op(details::e_r2d   , details::r2d_op  )
+         register_unary_op(details::e_d2r   , details::d2r_op  )
+         register_unary_op(details::e_d2g   , details::d2g_op  )
+         register_unary_op(details::e_g2d   , details::g2d_op  )
+         register_unary_op(details::e_notl  , details::notl_op )
+         register_unary_op(details::e_sgn   , details::sgn_op  )
+         register_unary_op(details::e_erf   , details::erf_op  )
+         register_unary_op(details::e_erfc  , details::erfc_op )
+         register_unary_op(details::e_ncdf  , details::ncdf_op )
+         register_unary_op(details::e_frac  , details::frac_op )
+         register_unary_op(details::e_trunc , details::trunc_op)
          #undef register_unary_op
       }
 
@@ -36227,27 +41625,27 @@ namespace exprtk
       {
          typedef typename binary_op_map_t::value_type value_type;
 
-         #define register_binary_op(Op,BinaryFunctor)        \
+         #define register_binary_op(Op, BinaryFunctor)       \
          m.insert(value_type(Op,BinaryFunctor<T>::process)); \
 
-         register_binary_op(details:: e_add, details:: add_op)
-         register_binary_op(details:: e_sub, details:: sub_op)
-         register_binary_op(details:: e_mul, details:: mul_op)
-         register_binary_op(details:: e_div, details:: div_op)
-         register_binary_op(details:: e_mod, details:: mod_op)
-         register_binary_op(details:: e_pow, details:: pow_op)
-         register_binary_op(details::  e_lt, details::  lt_op)
-         register_binary_op(details:: e_lte, details:: lte_op)
-         register_binary_op(details::  e_gt, details::  gt_op)
-         register_binary_op(details:: e_gte, details:: gte_op)
-         register_binary_op(details::  e_eq, details::  eq_op)
-         register_binary_op(details::  e_ne, details::  ne_op)
-         register_binary_op(details:: e_and, details:: and_op)
-         register_binary_op(details::e_nand, details::nand_op)
-         register_binary_op(details::  e_or, details::  or_op)
-         register_binary_op(details:: e_nor, details:: nor_op)
-         register_binary_op(details:: e_xor, details:: xor_op)
-         register_binary_op(details::e_xnor, details::xnor_op)
+         register_binary_op(details::e_add  , details::add_op )
+         register_binary_op(details::e_sub  , details::sub_op )
+         register_binary_op(details::e_mul  , details::mul_op )
+         register_binary_op(details::e_div  , details::div_op )
+         register_binary_op(details::e_mod  , details::mod_op )
+         register_binary_op(details::e_pow  , details::pow_op )
+         register_binary_op(details::e_lt   , details::lt_op  )
+         register_binary_op(details::e_lte  , details::lte_op )
+         register_binary_op(details::e_gt   , details::gt_op  )
+         register_binary_op(details::e_gte  , details::gte_op )
+         register_binary_op(details::e_eq   , details::eq_op  )
+         register_binary_op(details::e_ne   , details::ne_op  )
+         register_binary_op(details::e_and  , details::and_op )
+         register_binary_op(details::e_nand , details::nand_op)
+         register_binary_op(details::e_or   , details::or_op  )
+         register_binary_op(details::e_nor  , details::nor_op )
+         register_binary_op(details::e_xor  , details::xor_op )
+         register_binary_op(details::e_xnor , details::xnor_op)
          #undef register_binary_op
       }
 
@@ -36255,27 +41653,27 @@ namespace exprtk
       {
          typedef typename inv_binary_op_map_t::value_type value_type;
 
-         #define register_binary_op(Op,BinaryFunctor)        \
+         #define register_binary_op(Op, BinaryFunctor)       \
          m.insert(value_type(BinaryFunctor<T>::process,Op)); \
 
-         register_binary_op(details:: e_add, details:: add_op)
-         register_binary_op(details:: e_sub, details:: sub_op)
-         register_binary_op(details:: e_mul, details:: mul_op)
-         register_binary_op(details:: e_div, details:: div_op)
-         register_binary_op(details:: e_mod, details:: mod_op)
-         register_binary_op(details:: e_pow, details:: pow_op)
-         register_binary_op(details::  e_lt, details::  lt_op)
-         register_binary_op(details:: e_lte, details:: lte_op)
-         register_binary_op(details::  e_gt, details::  gt_op)
-         register_binary_op(details:: e_gte, details:: gte_op)
-         register_binary_op(details::  e_eq, details::  eq_op)
-         register_binary_op(details::  e_ne, details::  ne_op)
-         register_binary_op(details:: e_and, details:: and_op)
-         register_binary_op(details::e_nand, details::nand_op)
-         register_binary_op(details::  e_or, details::  or_op)
-         register_binary_op(details:: e_nor, details:: nor_op)
-         register_binary_op(details:: e_xor, details:: xor_op)
-         register_binary_op(details::e_xnor, details::xnor_op)
+         register_binary_op(details::e_add  , details::add_op )
+         register_binary_op(details::e_sub  , details::sub_op )
+         register_binary_op(details::e_mul  , details::mul_op )
+         register_binary_op(details::e_div  , details::div_op )
+         register_binary_op(details::e_mod  , details::mod_op )
+         register_binary_op(details::e_pow  , details::pow_op )
+         register_binary_op(details::e_lt   , details::lt_op  )
+         register_binary_op(details::e_lte  , details::lte_op )
+         register_binary_op(details::e_gt   , details::gt_op  )
+         register_binary_op(details::e_gte  , details::gte_op )
+         register_binary_op(details::e_eq   , details::eq_op  )
+         register_binary_op(details::e_ne   , details::ne_op  )
+         register_binary_op(details::e_and  , details::and_op )
+         register_binary_op(details::e_nand , details::nand_op)
+         register_binary_op(details::e_or   , details::or_op  )
+         register_binary_op(details::e_nor  , details::nor_op )
+         register_binary_op(details::e_xor  , details::xor_op )
+         register_binary_op(details::e_xnor , details::xnor_op)
          #undef register_binary_op
       }
 
@@ -36368,8 +41766,8 @@ namespace exprtk
 
    private:
 
-      parser(const parser<T>&);
-      parser<T>& operator=(const parser<T>&);
+      parser(const parser<T>&) exprtk_delete;
+      parser<T>& operator=(const parser<T>&) exprtk_delete;
 
       settings_store settings_;
       expression_generator<T> expression_generator_;
@@ -36391,6 +41789,10 @@ namespace exprtk
       sf4_map_t sf4_map_;
       std::string synthesis_error_;
       scope_element_manager sem_;
+      std::vector<state_t> current_state_stack_;
+
+      immutable_memory_map_t immutable_memory_map_;
+      immutable_symtok_map_t immutable_symtok_map_;
 
       lexer::helper::helper_assembly helper_assembly_;
 
@@ -36399,15 +41801,19 @@ namespace exprtk
       lexer::helper::operator_joiner            operator_joiner_3_;
       lexer::helper::symbol_replacer            symbol_replacer_;
       lexer::helper::bracket_checker            bracket_checker_;
-      lexer::helper::numeric_checker            numeric_checker_;
+      lexer::helper::numeric_checker<T>         numeric_checker_;
       lexer::helper::sequence_validator         sequence_validator_;
       lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
 
-      loop_runtime_check_ptr loop_runtime_check_;
+      loop_runtime_check_ptr          loop_runtime_check_;
+      vector_access_runtime_check_ptr vector_access_runtime_check_;
+      compilation_check_ptr           compilation_check_ptr_;
+      assert_check_ptr                assert_check_;
+      std::set<std::string>           assert_ids_;
 
       template <typename ParserType>
       friend void details::disable_type_checking(ParserType& p);
-   };
+   }; // class parser
 
    namespace details
    {
@@ -36415,22 +41821,24 @@ namespace exprtk
       struct collector_helper
       {
          typedef exprtk::symbol_table<T> symbol_table_t;
-         typedef exprtk::expression<T>     expression_t;
-         typedef exprtk::parser<T>             parser_t;
+         typedef exprtk::expression<T>   expression_t;
+         typedef exprtk::parser<T>       parser_t;
          typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
          typedef typename parser_t::unknown_symbol_resolver usr_t;
 
-         struct resolve_as_vector : public parser_t::unknown_symbol_resolver
+         struct resolve_as_vector : public usr_t
          {
             typedef exprtk::parser<T> parser_t;
 
+            using usr_t::process;
+
             resolve_as_vector()
             : usr_t(usr_t::e_usrmode_extended)
             {}
 
             virtual bool process(const std::string& unknown_symbol,
                                  symbol_table_t& symbol_table,
-                                 std::string&)
+                                 std::string&) exprtk_override
             {
                static T v[1];
                symbol_table.add_vector(unknown_symbol,v);
@@ -36642,7 +42050,9 @@ namespace exprtk
       const symbol_table<T>& sym_table = e.get_symbol_table();
 
       if (!sym_table.valid())
+      {
          return std::numeric_limits<T>::quiet_NaN();
+      }
 
       details::variable_node<T>* var = sym_table.get_variable(variable_name);
 
@@ -36655,8 +42065,8 @@ namespace exprtk
 
          return result;
       }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
+
+      return std::numeric_limits<T>::quiet_NaN();
    }
 
    template <typename T>
@@ -36669,9 +42079,9 @@ namespace exprtk
 
       x = x_init + _2h;
       const T y0 = e.value();
-      x = x_init +   h;
+      x = x_init + h;
       const T y1 = e.value();
-      x = x_init -   h;
+      x = x_init - h;
       const T y2 = e.value();
       x = x_init - _2h;
       const T y3 = e.value();
@@ -36691,9 +42101,9 @@ namespace exprtk
       const T y = e.value();
       x = x_init + _2h;
       const T y0 = e.value();
-      x = x_init +   h;
+      x = x_init + h;
       const T y1 = e.value();
-      x = x_init -   h;
+      x = x_init - h;
       const T y2 = e.value();
       x = x_init - _2h;
       const T y3 = e.value();
@@ -36712,9 +42122,9 @@ namespace exprtk
 
       x = x_init + _2h;
       const T y0 = e.value();
-      x = x_init +   h;
+      x = x_init + h;
       const T y1 = e.value();
-      x = x_init -   h;
+      x = x_init - h;
       const T y2 = e.value();
       x = x_init - _2h;
       const T y3 = e.value();
@@ -36746,8 +42156,8 @@ namespace exprtk
 
          return result;
       }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
+
+      return std::numeric_limits<T>::quiet_NaN();
    }
 
    template <typename T>
@@ -36773,8 +42183,8 @@ namespace exprtk
 
          return result;
       }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
+
+      return std::numeric_limits<T>::quiet_NaN();
    }
 
    template <typename T>
@@ -36800,8 +42210,8 @@ namespace exprtk
 
          return result;
       }
-      else
-         return std::numeric_limits<T>::quiet_NaN();
+
+      return std::numeric_limits<T>::quiet_NaN();
    }
 
    /*
@@ -37086,79 +42496,92 @@ namespace exprtk
       #define poly_rtrn(NN) \
       return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
 
-      inline virtual T operator() (const T& x, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1,
+                                   const T& c0) exprtk_override
       {
          poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2,
+                                   const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3,
+                                   const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4,
+                                   const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5,
+                                   const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6,
+                                   const T& c5, const T& c4, const T& c3, const T& c2, const T& c1,
+                                   const T& c0) exprtk_override
       {
          poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7,
+                                   const T& c6, const T& c5, const T& c4, const T& c3, const T& c2,
+                                   const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8,
+                                   const T& c7, const T& c6, const T& c5, const T& c4, const T& c3,
+                                   const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
-      inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9,
+                                   const T& c8, const T& c7, const T& c6, const T& c5, const T& c4,
+                                   const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
       {
          poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
       }
 
       #undef poly_rtrn
 
-      inline virtual T operator() ()
+      inline virtual T operator() () exprtk_override
       {
          return std::numeric_limits<T>::quiet_NaN();
       }
 
-      inline virtual T operator() (const T&)
+      inline virtual T operator() (const T&) exprtk_override
       {
          return std::numeric_limits<T>::quiet_NaN();
       }
 
-      inline virtual T operator() (const T&, const T&)
+      inline virtual T operator() (const T&, const T&) exprtk_override
       {
          return std::numeric_limits<T>::quiet_NaN();
       }
@@ -37185,15 +42608,15 @@ namespace exprtk
 
          function(const std::string& name,
                   const std::string& expression)
-         : name_(name),
-           expression_(expression)
+         : name_(name)
+         , expression_(expression)
          {}
 
          function(const std::string& name,
                   const std::string& expression,
                   const std::string& v0)
-         : name_(name),
-           expression_(expression)
+         : name_(name)
+         , expression_(expression)
          {
             v_.push_back(v0);
          }
@@ -37201,8 +42624,8 @@ namespace exprtk
          function(const std::string& name,
                   const std::string& expression,
                   const std::string& v0, const std::string& v1)
-         : name_(name),
-           expression_(expression)
+         : name_(name)
+         , expression_(expression)
          {
             v_.push_back(v0); v_.push_back(v1);
          }
@@ -37211,8 +42634,8 @@ namespace exprtk
                   const std::string& expression,
                   const std::string& v0, const std::string& v1,
                   const std::string& v2)
-         : name_(name),
-           expression_(expression)
+         : name_(name)
+         , expression_(expression)
          {
             v_.push_back(v0); v_.push_back(v1);
             v_.push_back(v2);
@@ -37222,8 +42645,8 @@ namespace exprtk
                   const std::string& expression,
                   const std::string& v0, const std::string& v1,
                   const std::string& v2, const std::string& v3)
-         : name_(name),
-           expression_(expression)
+         : name_(name)
+         , expression_(expression)
          {
             v_.push_back(v0); v_.push_back(v1);
             v_.push_back(v2); v_.push_back(v3);
@@ -37234,8 +42657,8 @@ namespace exprtk
                   const std::string& v0, const std::string& v1,
                   const std::string& v2, const std::string& v3,
                   const std::string& v4)
-         : name_(name),
-           expression_(expression)
+         : name_(name)
+         , expression_(expression)
          {
             v_.push_back(v0); v_.push_back(v1);
             v_.push_back(v2); v_.push_back(v3);
@@ -37260,6 +42683,50 @@ namespace exprtk
             return (*this);
          }
 
+         inline function& vars(const std::string& v0,
+                               const std::string& v1)
+         {
+            v_.push_back(v0);
+            v_.push_back(v1);
+            return (*this);
+         }
+
+         inline function& vars(const std::string& v0,
+                               const std::string& v1,
+                               const std::string& v2)
+         {
+            v_.push_back(v0);
+            v_.push_back(v1);
+            v_.push_back(v2);
+            return (*this);
+         }
+
+         inline function& vars(const std::string& v0,
+                               const std::string& v1,
+                               const std::string& v2,
+                               const std::string& v3)
+         {
+            v_.push_back(v0);
+            v_.push_back(v1);
+            v_.push_back(v2);
+            v_.push_back(v3);
+            return (*this);
+         }
+
+         inline function& vars(const std::string& v0,
+                               const std::string& v1,
+                               const std::string& v2,
+                               const std::string& v3,
+                               const std::string& v4)
+         {
+            v_.push_back(v0);
+            v_.push_back(v1);
+            v_.push_back(v2);
+            v_.push_back(v3);
+            v_.push_back(v4);
+            return (*this);
+         }
+
          std::string name_;
          std::string expression_;
          std::deque<std::string> v_;
@@ -37269,19 +42736,21 @@ namespace exprtk
 
       struct base_func : public exprtk::ifunction<T>
       {
-         typedef const T&                       type;
-         typedef exprtk::ifunction<T>     function_t;
-         typedef std::vector<T*>            varref_t;
-         typedef std::vector<T>                var_t;
+         typedef const T&                  type;
+         typedef exprtk::ifunction<T>      function_t;
+         typedef std::vector<T*>           varref_t;
+         typedef std::vector<T>            var_t;
+         typedef std::vector<std::string>  str_t;
          typedef std::pair<T*,std::size_t> lvarref_t;
          typedef std::vector<lvarref_t>    lvr_vec_t;
+         typedef std::vector<std::string*> lstr_vec_t;
 
          using exprtk::ifunction<T>::operator();
 
          base_func(const std::size_t& pc = 0)
-         : exprtk::ifunction<T>(pc),
-           local_var_stack_size(0),
-           stack_depth(0)
+         : exprtk::ifunction<T>(pc)
+         , local_var_stack_size(0)
+         , stack_depth(0)
          {
             v.resize(pc);
          }
@@ -37289,57 +42758,80 @@ namespace exprtk
          virtual ~base_func()
          {}
 
+         #define exprtk_assign(Index) \
+         (*v[Index]) = v##Index;      \
+
          inline void update(const T& v0)
          {
-            (*v[0]) = v0;
+            exprtk_assign(0)
          }
 
          inline void update(const T& v0, const T& v1)
          {
-            (*v[0]) = v0; (*v[1]) = v1;
+            exprtk_assign(0) exprtk_assign(1)
          }
 
          inline void update(const T& v0, const T& v1, const T& v2)
          {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2;
+            exprtk_assign(0) exprtk_assign(1)
+            exprtk_assign(2)
          }
 
          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
          {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2; (*v[3]) = v3;
+            exprtk_assign(0) exprtk_assign(1)
+            exprtk_assign(2) exprtk_assign(3)
          }
 
          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
          {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2; (*v[3]) = v3;
-            (*v[4]) = v4;
+            exprtk_assign(0) exprtk_assign(1)
+            exprtk_assign(2) exprtk_assign(3)
+            exprtk_assign(4)
          }
 
          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
          {
-            (*v[0]) = v0; (*v[1]) = v1;
-            (*v[2]) = v2; (*v[3]) = v3;
-            (*v[4]) = v4; (*v[5]) = v5;
+            exprtk_assign(0) exprtk_assign(1)
+            exprtk_assign(2) exprtk_assign(3)
+            exprtk_assign(4) exprtk_assign(5)
          }
 
+         #ifdef exprtk_assign
+         #undef exprtk_assign
+         #endif
+
          inline function_t& setup(expression_t& expr)
          {
             expression = expr;
 
-            typedef typename expression_t::control_block::local_data_list_t ldl_t;
+            typedef typename expression_t::control_block  ctrlblk_t;
+            typedef typename ctrlblk_t::local_data_list_t ldl_t;
+            typedef typename ctrlblk_t::data_type         data_t;
+            typedef typename ldl_t::value_type            ldl_value_type;
 
             const ldl_t ldl = expr.local_data_list();
 
-            std::vector<std::size_t> index_list;
+            std::vector<std::pair<std::size_t,data_t> > index_list;
 
             for (std::size_t i = 0; i < ldl.size(); ++i)
             {
+               exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n",
+                             static_cast<int>(i),
+                             expression_t::control_block::to_str(ldl[i].type).c_str(),
+                             static_cast<int>(ldl[i].size)));
+
+               switch (ldl[i].type)
+               {
+                  case ctrlblk_t::e_unknown   : continue;
+                  case ctrlblk_t::e_expr      : continue;
+                  case ctrlblk_t::e_vecholder : continue;
+                  default                     : break;
+               }
+
                if (ldl[i].size)
                {
-                  index_list.push_back(i);
+                  index_list.push_back(std::make_pair(i,ldl[i].type));
                }
             }
 
@@ -37347,19 +42839,34 @@ namespace exprtk
 
             for (std::size_t i = 0; i < index_list.size(); ++i)
             {
-               const std::size_t index = index_list[i];
+               const std::size_t index         = index_list[i].first;
+               const ldl_value_type& local_var = ldl[index];
+
+               assert(local_var.pointer);
 
                if (i < (index_list.size() - v.size()))
                {
-                  lv.push_back(
-                        std::make_pair(
-                           reinterpret_cast<T*>(ldl[index].pointer),
-                           ldl[index].size));
+                  if (local_var.type == ctrlblk_t::e_string)
+                  {
+                     local_str_vars.push_back(
+                        reinterpret_cast<std::string*>(local_var.pointer));
+                  }
+                  else if (
+                            (local_var.type == ctrlblk_t::e_data   ) ||
+                            (local_var.type == ctrlblk_t::e_vecdata)
+                          )
+                  {
+                     local_vars.push_back(std::make_pair(
+                        reinterpret_cast<T*>(local_var.pointer),
+                        local_var.size));
 
-                  local_var_stack_size += ldl[index].size;
+                     local_var_stack_size += local_var.size;
+                  }
                }
                else
-                  v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
+               {
+                  v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer);
+               }
             }
 
             clear_stack();
@@ -37375,14 +42882,21 @@ namespace exprtk
                {
                   var_t var_stack(v.size(),T(0));
                   copy(v,var_stack);
-                  param_stack.push_back(var_stack);
+                  input_params_stack.push_back(var_stack);
+               }
+
+               if (!local_vars.empty())
+               {
+                  var_t local_vec_frame(local_var_stack_size,T(0));
+                  copy(local_vars,local_vec_frame);
+                  local_var_stack.push_back(local_vec_frame);
                }
 
-               if (!lv.empty())
+               if (!local_str_vars.empty())
                {
-                  var_t local_var_stack(local_var_stack_size,T(0));
-                  copy(lv,local_var_stack);
-                  local_stack.push_back(local_var_stack);
+                  str_t local_str_frame(local_str_vars.size());
+                  copy(local_str_vars,local_str_frame);
+                  local_str_stack.push_back(local_str_frame);
                }
             }
          }
@@ -37393,14 +42907,20 @@ namespace exprtk
             {
                if (!v.empty())
                {
-                  copy(param_stack.back(),v);
-                  param_stack.pop_back();
+                  copy(input_params_stack.back(), v);
+                  input_params_stack.pop_back();
+               }
+
+               if (!local_vars.empty())
+               {
+                  copy(local_var_stack.back(), local_vars);
+                  local_var_stack.pop_back();
                }
 
-               if (!lv.empty())
+               if (!local_str_vars.empty())
                {
-                  copy(local_stack.back(),lv);
-                  local_stack.pop_back();
+                  copy(local_str_stack.back(), local_str_vars);
+                  local_str_stack.pop_back();
                }
             }
          }
@@ -37413,6 +42933,14 @@ namespace exprtk
             }
          }
 
+         void copy(const lstr_vec_t& src_v, str_t& dest_v)
+         {
+            for (std::size_t i = 0; i < src_v.size(); ++i)
+            {
+               dest_v[i] = (*src_v[i]);
+            }
+         }
+
          void copy(const var_t& src_v, varref_t& dest_v)
          {
             for (std::size_t i = 0; i < src_v.size(); ++i)
@@ -37445,9 +42973,12 @@ namespace exprtk
             typename var_t::const_iterator itr = src_v.begin();
             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
 
-            for (std::size_t i = 0; i < src_v.size(); ++i)
+            for (std::size_t i = 0; i < dest_v.size(); ++i)
             {
-               lvarref_t vr = dest_v[i];
+               lvarref_t& vr = dest_v[i];
+
+               assert(vr.first != 0);
+               assert(vr.second > 0);
 
                if (1 == vr.second)
                   (*vr.first) = *itr++;
@@ -37459,6 +42990,16 @@ namespace exprtk
             }
          }
 
+         void copy(const str_t& src_str, lstr_vec_t& dest_str)
+         {
+            assert(src_str.size() == dest_str.size());
+
+            for (std::size_t i = 0; i < dest_str.size(); ++i)
+            {
+               *dest_str[i] = src_str[i];
+            }
+         }
+
          inline void clear_stack()
          {
             for (std::size_t i = 0; i < v.size(); ++i)
@@ -37472,29 +43013,19 @@ namespace exprtk
             return e.value();
          }
 
-         expression_t expression;
-         varref_t v;
-         lvr_vec_t lv;
-         std::size_t local_var_stack_size;
-         std::size_t stack_depth;
-         std::deque<var_t> param_stack;
-         std::deque<var_t> local_stack;
+         expression_t      expression;
+         varref_t          v;
+         lvr_vec_t         local_vars;
+         lstr_vec_t        local_str_vars;
+         std::size_t       local_var_stack_size;
+         std::size_t       stack_depth;
+         std::deque<var_t> input_params_stack;
+         std::deque<var_t> local_var_stack;
+         std::deque<str_t> local_str_stack;
       };
 
       typedef std::map<std::string,base_func*> funcparam_t;
 
-      struct func_0param : public base_func
-      {
-         using exprtk::ifunction<T>::operator();
-
-         func_0param() : base_func(0) {}
-
-         inline T operator() ()
-         {
-            return this->value(base_func::expression);
-         }
-      };
-
       typedef const T& type;
 
       template <typename BaseFuncType>
@@ -37515,8 +43046,21 @@ namespace exprtk
 
       private:
 
-         scoped_bft(scoped_bft&);
-         scoped_bft& operator=(scoped_bft&);
+         scoped_bft(const scoped_bft&) exprtk_delete;
+         scoped_bft& operator=(const scoped_bft&) exprtk_delete;
+      };
+
+      struct func_0param : public base_func
+      {
+         using exprtk::ifunction<T>::operator();
+
+         func_0param() : base_func(0) {}
+
+         inline T operator() () exprtk_override
+         {
+            scoped_bft<func_0param> sb(*this);
+            return this->value(base_func::expression);
+         }
       };
 
       struct func_1param : public base_func
@@ -37525,7 +43069,7 @@ namespace exprtk
 
          func_1param() : base_func(1) {}
 
-         inline T operator() (type v0)
+         inline T operator() (type v0) exprtk_override
          {
             scoped_bft<func_1param> sb(*this);
             base_func::update(v0);
@@ -37539,7 +43083,7 @@ namespace exprtk
 
          func_2param() : base_func(2) {}
 
-         inline T operator() (type v0, type v1)
+         inline T operator() (type v0, type v1) exprtk_override
          {
             scoped_bft<func_2param> sb(*this);
             base_func::update(v0, v1);
@@ -37553,7 +43097,7 @@ namespace exprtk
 
          func_3param() : base_func(3) {}
 
-         inline T operator() (type v0, type v1, type v2)
+         inline T operator() (type v0, type v1, type v2) exprtk_override
          {
             scoped_bft<func_3param> sb(*this);
             base_func::update(v0, v1, v2);
@@ -37567,7 +43111,7 @@ namespace exprtk
 
          func_4param() : base_func(4) {}
 
-         inline T operator() (type v0, type v1, type v2, type v3)
+         inline T operator() (type v0, type v1, type v2, type v3) exprtk_override
          {
             scoped_bft<func_4param> sb(*this);
             base_func::update(v0, v1, v2, v3);
@@ -37581,7 +43125,7 @@ namespace exprtk
 
          func_5param() : base_func(5) {}
 
-         inline T operator() (type v0, type v1, type v2, type v3, type v4)
+         inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override
          {
             scoped_bft<func_5param> sb(*this);
             base_func::update(v0, v1, v2, v3, v4);
@@ -37595,7 +43139,7 @@ namespace exprtk
 
          func_6param() : base_func(6) {}
 
-         inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
+         inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override
          {
             scoped_bft<func_6param> sb(*this);
             base_func::update(v0, v1, v2, v3, v4, v5);
@@ -37622,14 +43166,14 @@ namespace exprtk
          return result;
       }
 
-      #define def_fp_retval(N)                               \
-      struct func_##N##param_retval : public func_##N##param \
-      {                                                      \
-         inline T value(expression_t& e)                     \
-         {                                                   \
-            return return_value(e);                          \
-         }                                                   \
-      };                                                     \
+      #define def_fp_retval(N)                                            \
+      struct func_##N##param_retval exprtk_final : public func_##N##param \
+      {                                                                   \
+         inline T value(expression_t& e) exprtk_override                  \
+         {                                                                \
+            return return_value(e);                                       \
+         }                                                                \
+      };                                                                  \
 
       def_fp_retval(0)
       def_fp_retval(1)
@@ -37639,6 +43183,8 @@ namespace exprtk
       def_fp_retval(5)
       def_fp_retval(6)
 
+      #undef def_fp_retval
+
       template <typename Allocator,
                 template <typename, typename> class Sequence>
       inline bool add(const std::string& name,
@@ -37661,7 +43207,7 @@ namespace exprtk
             remove(name, var_list.size());
          }
 
-         if (compile_expression(name,expression,var_list))
+         if (compile_expression(name, expression, var_list))
          {
             const std::size_t n = var_list.size();
 
@@ -37681,16 +43227,20 @@ namespace exprtk
    public:
 
       function_compositor()
-      : parser_(settings_t::compile_all_opts +
-                settings_t::e_disable_zero_return),
-        fp_map_(7)
+      : parser_(settings_t::default_compile_all_opts +
+                settings_t::e_disable_zero_return)
+      , fp_map_(7)
+      , load_variables_(false)
+      , load_vectors_(false)
       {}
 
-      function_compositor(const symbol_table_t& st)
-      : symbol_table_(st),
-        parser_(settings_t::compile_all_opts +
-                settings_t::e_disable_zero_return),
-        fp_map_(7)
+      explicit function_compositor(const symbol_table_t& st)
+      : symbol_table_(st)
+      , parser_(settings_t::default_compile_all_opts +
+                settings_t::e_disable_zero_return)
+      , fp_map_(7)
+      , load_variables_(false)
+      , load_vectors_(false)
       {}
 
      ~function_compositor()
@@ -37713,6 +43263,46 @@ namespace exprtk
          auxiliary_symtab_list_.push_back(&symtab);
       }
 
+      void load_variables(const bool load = true)
+      {
+         load_variables_ = load;
+      }
+
+      void load_vectors(const bool load = true)
+      {
+         load_vectors_ = load;
+      }
+
+      inline void register_loop_runtime_check(loop_runtime_check& lrtchk)
+      {
+         parser_.register_loop_runtime_check(lrtchk);
+      }
+
+      inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk)
+      {
+         parser_.register_vector_access_runtime_check(vartchk);
+      }
+
+      inline void register_compilation_timeout_check(compilation_check& compchk)
+      {
+         parser_.register_compilation_timeout_check(compchk);
+      }
+
+      inline void clear_loop_runtime_check()
+      {
+         parser_.clear_loop_runtime_check();
+      }
+
+      inline void clear_vector_access_runtime_check()
+      {
+         parser_.clear_vector_access_runtime_check();
+      }
+
+      inline void clear_compilation_timeout_check()
+      {
+         parser_.clear_compilation_timeout_check();
+      }
+
       void clear()
       {
          symbol_table_.clear();
@@ -37731,6 +43321,10 @@ namespace exprtk
 
             fp_map_[i].clear();
          }
+
+         clear_loop_runtime_check         ();
+         clear_vector_access_runtime_check();
+         clear_compilation_timeout_check  ();
       }
 
       inline bool add(const function& f, const bool override = false)
@@ -37738,6 +43332,31 @@ namespace exprtk
          return add(f.name_, f.expression_, f.v_,override);
       }
 
+      inline std::string error() const
+      {
+         if (!error_list_.empty())
+         {
+            return error_list_[0].diagnostic;
+         }
+         else
+            return std::string("No Error");
+      }
+
+      inline std::size_t error_count() const
+      {
+         return error_list_.size();
+      }
+
+      inline parser_error::type get_error(const std::size_t& index) const
+      {
+         if (index < error_list_.size())
+         {
+            return error_list_[index];
+         }
+
+         throw std::invalid_argument("compositor::get_error() - Invalid error index specified");
+      }
+
    private:
 
       template <typename Allocator,
@@ -37753,8 +43372,30 @@ namespace exprtk
          local_symbol_table.load_from(symbol_table_);
          local_symbol_table.add_constants();
 
+         if (load_variables_)
+         {
+            local_symbol_table.load_variables_from(symbol_table_);
+         }
+
+         if (load_vectors_)
+         {
+            local_symbol_table.load_vectors_from(symbol_table_);
+         }
+
+         error_list_.clear();
+
          if (!valid(name,input_var_list.size()))
+         {
+            parser_error::type error =
+               parser_error::make_error(
+                  parser_error::e_parser,
+                  lexer::token(),
+                  "ERR277 - Function '" + name + "' is an invalid overload",
+                  exprtk_error_location);
+
+            error_list_.push_back(error);
             return false;
+         }
 
          if (!forward(name,
                       input_var_list.size(),
@@ -37786,18 +43427,22 @@ namespace exprtk
 
          if (!parser_.compile(mod_expression,compiled_expression))
          {
-            exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
-            exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
+            exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str()));
+            exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str()));
 
             remove(name,input_var_list.size());
 
+            for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index)
+            {
+               error_list_.push_back(parser_.get_error(err_index));
+            }
+
             return false;
          }
 
          if (!return_present && parser_.dec().return_present())
          {
             remove(name,input_var_list.size());
-
             return compile_expression(name, expression, input_var_list, true);
          }
 
@@ -37918,206 +43563,14 @@ namespace exprtk
       std::map<std::string,expression_t> expr_map_;
       std::vector<funcparam_t> fp_map_;
       std::vector<symbol_table_t*> auxiliary_symtab_list_;
-   };
-
-   template <typename T>
-   inline bool pgo_primer()
-   {
-      static const std::string expression_list[] =
-             {
-                "(y + x)",
-                "2 * (y + x)",
-                "(2 * y + 2 * x)",
-                "(y + x / y) * (x - y / x)",
-                "x / ((x + y) * (x - y)) / y",
-                "1 - ((x * y) + (y / x)) - 3",
-                "sin(2 * x) + cos(pi / y)",
-                "1 - sin(2 * x) + cos(pi / y)",
-                "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
-                "(x^2 / sin(2 * pi / y)) -x / 2",
-                "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
-                "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
-                "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
-                "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
-                "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
-                "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
-                "(yy + xx)",
-                "2 * (yy + xx)",
-                "(2 * yy + 2 * xx)",
-                "(yy + xx / yy) * (xx - yy / xx)",
-                "xx / ((xx + yy) * (xx - yy)) / yy",
-                "1 - ((xx * yy) + (yy / xx)) - 3",
-                "sin(2 * xx) + cos(pi / yy)",
-                "1 - sin(2 * xx) + cos(pi / yy)",
-                "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
-                "(xx^2 / sin(2 * pi / yy)) -xx / 2",
-                "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
-                "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
-                "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
-                "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
-                "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
-                "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
-                "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
-                "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
-                "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
-                "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
-                "(x + 2) * 3", "x + (2 * 3)",
-                "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
-                "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
-                "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
-                "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
-                "2 + (x * (y / 3))", "x + (2 * (3 / y))",
-                "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
-                "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
-                "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
-                "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
-                "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
-                "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
-                "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
-                "((x + (2 * 3)) / y)",
-                "(xx + yy) * zz", "xx + (yy * zz)",
-                "(xx + yy) * 7", "xx + (yy * 7)",
-                "(xx + 7) * yy", "xx + (7 * yy)",
-                "(7 + xx) * yy", "7 + (xx * yy)",
-                "(2 + x) * 3", "2 + (x * 3)",
-                "(2 + 3) * x", "2 + (3 * x)",
-                "(x + 2) * 3", "x + (2 * 3)",
-                "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
-                "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
-                "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
-                "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
-                "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
-                "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
-                "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
-                "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
-                "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
-                "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
-                "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
-                "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
-                "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
-                "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
-                "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
-                "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
-                "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
-                "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
-                "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
-                "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
-                "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
-                "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
-                "((xx + (2 * 3)) / yy)"
-             };
-
-      static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
-
-      T  x = T(0);
-      T  y = T(0);
-      T  z = T(0);
-      T  w = T(0);
-      T xx = T(0);
-      T yy = T(0);
-      T zz = T(0);
-      T ww = T(0);
-
-      exprtk::symbol_table<T> symbol_table;
-      symbol_table.add_constants();
-      symbol_table.add_variable( "x", x);
-      symbol_table.add_variable( "y", y);
-      symbol_table.add_variable( "z", z);
-      symbol_table.add_variable( "w", w);
-      symbol_table.add_variable("xx",xx);
-      symbol_table.add_variable("yy",yy);
-      symbol_table.add_variable("zz",zz);
-      symbol_table.add_variable("ww",ww);
-
-      typedef typename std::deque<exprtk::expression<T> > expr_list_t;
-      expr_list_t expr_list;
-
-      const std::size_t rounds = 50;
-
-      {
-         for (std::size_t r = 0; r < rounds; ++r)
-         {
-            expr_list.clear();
-            exprtk::parser<T> parser;
-
-            for (std::size_t i = 0; i < expression_list_size; ++i)
-            {
-               exprtk::expression<T> expression;
-               expression.register_symbol_table(symbol_table);
-
-               if (!parser.compile(expression_list[i],expression))
-               {
-                  return false;
-               }
-
-               expr_list.push_back(expression);
-            }
-         }
-      }
-
-      struct execute
-      {
-         static inline T process(T& x, T& y, expression<T>& expression)
-         {
-            static const T lower_bound = T(-20);
-            static const T upper_bound = T(+20);
-            static const T delta       = T(0.1);
-
-            T total = T(0);
-
-            for (x = lower_bound; x <= upper_bound; x += delta)
-            {
-               for (y = lower_bound; y <= upper_bound; y += delta)
-               {
-                  total += expression.value();
-               }
-            }
-
-            return total;
-         }
-      };
-
-      for (std::size_t i = 0; i < expr_list.size(); ++i)
-      {
-         execute::process( x,  y, expr_list[i]);
-         execute::process(xx, yy, expr_list[i]);
-      }
-
-      {
-         for (std::size_t i = 0; i < 10000; ++i)
-         {
-            const T v = T(123.456 + i);
-
-            if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
-               return false;
-
-            #define else_stmt(N)                                                                                                           \
-            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
-               return false;                                                                                                               \
-
-            else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
-            else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
-            else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
-            else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
-            else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
-            else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
-            else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
-            else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
-            else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
-            else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
-            else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
-            else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
-            else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
-            else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
-            else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
-         }
-      }
+      std::deque<parser_error::type> error_list_;
+      bool load_variables_;
+      bool load_vectors_;
+   }; // class function_compositor
 
-      return true;
-   }
-}
+} // namespace exprtk
 
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
 #   ifndef NOMINMAX
 #      define NOMINMAX
 #   endif
@@ -38138,9 +43591,11 @@ namespace exprtk
    {
    public:
 
-      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+      #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
       timer()
       : in_use_(false)
+      , start_time_{ {0, 0} }
+      , stop_time_ { {0, 0} }
       {
          QueryPerformanceFrequency(&clock_frequency_);
       }
@@ -38169,6 +43624,7 @@ namespace exprtk
       {
          start_time_.tv_sec  = 0;
          start_time_.tv_usec = 0;
+
          stop_time_.tv_sec   = 0;
          stop_time_.tv_usec  = 0;
       }
@@ -38217,7 +43673,7 @@ namespace exprtk
 
       bool in_use_;
 
-      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+      #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
          LARGE_INTEGER start_time_;
          LARGE_INTEGER stop_time_;
          LARGE_INTEGER clock_frequency_;
@@ -38227,6 +43683,17 @@ namespace exprtk
       #endif
    };
 
+   template <typename T>
+   struct type_defs
+   {
+      typedef symbol_table<T>         symbol_table_t;
+      typedef expression<T>           expression_t;
+      typedef parser<T>               parser_t;
+      typedef parser_error::type      error_t;
+      typedef function_compositor<T>  compositor_t;
+      typedef typename compositor_t::function function_t;
+   };
+
 } // namespace exprtk
 
 #ifndef exprtk_disable_rtl_io
@@ -38239,7 +43706,23 @@ namespace exprtk
                              const T v,
                              exprtk::details::numeric::details::real_type_tag)
       {
-         printf(fmt.c_str(),v);
+         #if defined(__clang__)
+            #pragma clang diagnostic push
+            #pragma clang diagnostic ignored "-Wformat-nonliteral"
+         #elif defined(__GNUC__) || defined(__GNUG__)
+            #pragma GCC diagnostic push
+            #pragma GCC diagnostic ignored "-Wformat-nonliteral"
+         #elif defined(_MSC_VER)
+         #endif
+
+         printf(fmt.c_str(), v);
+
+         #if defined(__clang__)
+            #pragma clang diagnostic pop
+         #elif defined(__GNUC__) || defined(__GNUG__)
+            #pragma GCC diagnostic pop
+         #elif defined(_MSC_VER)
+         #endif
       }
 
       template <typename T>
@@ -38299,19 +43782,19 @@ namespace exprtk
    } // namespace exprtk::rtl::io::details
 
    template <typename T>
-   struct print : public exprtk::igeneric_function<T>
+   struct print exprtk_final : public exprtk::igeneric_function<T>
    {
       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
 
       using exprtk::igeneric_function<T>::operator();
 
-      print(const std::string& scalar_format = "%10.5f")
+      explicit print(const std::string& scalar_format = "%10.5f")
       : scalar_format_(scalar_format)
       {
          exprtk::enable_zero_parameters(*this);
       }
 
-      inline T operator() (parameter_list_t parameters)
+      inline T operator() (parameter_list_t parameters) exprtk_override
       {
          details::print_impl<T>::process(scalar_format_,parameters);
          return T(0);
@@ -38321,19 +43804,19 @@ namespace exprtk
    };
 
    template <typename T>
-   struct println : public exprtk::igeneric_function<T>
+   struct println exprtk_final : public exprtk::igeneric_function<T>
    {
       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
 
       using exprtk::igeneric_function<T>::operator();
 
-      println(const std::string& scalar_format = "%10.5f")
+      explicit println(const std::string& scalar_format = "%10.5f")
       : scalar_format_(scalar_format)
       {
          exprtk::enable_zero_parameters(*this);
       }
 
-      inline T operator() (parameter_list_t parameters)
+      inline T operator() (parameter_list_t parameters) exprtk_override
       {
          details::print_impl<T>::process(scalar_format_,parameters);
          printf("\n");
@@ -38351,7 +43834,7 @@ namespace exprtk
 
       bool register_package(exprtk::symbol_table<T>& symtab)
       {
-         #define exprtk_register_function(FunctionName,FunctionType)              \
+         #define exprtk_register_function(FunctionName, FunctionType)             \
          if (!symtab.add_function(FunctionName,FunctionType))                     \
          {                                                                        \
             exprtk_debug((                                                        \
@@ -38360,7 +43843,7 @@ namespace exprtk
             return false;                                                         \
          }                                                                        \
 
-         exprtk_register_function("print"  ,  p)
+         exprtk_register_function("print"  , p )
          exprtk_register_function("println", pl)
          #undef exprtk_register_function
 
@@ -38379,6 +43862,9 @@ namespace exprtk
 {
    namespace rtl { namespace io { namespace file { namespace details
    {
+      using ::exprtk::details::char_ptr;
+      using ::exprtk::details::char_cptr;
+
       enum file_mode
       {
          e_error = 0,
@@ -38390,9 +43876,9 @@ namespace exprtk
       struct file_descriptor
       {
          file_descriptor(const std::string& fname, const std::string& access)
-         : stream_ptr(0),
-           mode(get_file_mode(access)),
-           file_name(fname)
+         : stream_ptr(0)
+         , mode(get_file_mode(access))
+         , file_name(fname)
          {}
 
          void*       stream_ptr;
@@ -38412,8 +43898,8 @@ namespace exprtk
 
                   return false;
                }
-               else
-                  stream_ptr = stream;
+
+               stream_ptr = stream;
 
                return true;
             }
@@ -38428,8 +43914,8 @@ namespace exprtk
 
                   return false;
                }
-               else
-                  stream_ptr = stream;
+
+               stream_ptr = stream;
 
                return true;
             }
@@ -38444,13 +43930,13 @@ namespace exprtk
 
                   return false;
                }
-               else
-                  stream_ptr = stream;
+
+               stream_ptr = stream;
 
                return true;
             }
-            else
-               return false;
+
+            return false;
          }
 
          template <typename Stream, typename Ptr>
@@ -38487,11 +43973,11 @@ namespace exprtk
             switch (mode)
             {
                case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
-                                 write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
+                                 write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
                               break;
 
                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
-                                 write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
+                                 write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
                               break;
 
                default      : return false;
@@ -38506,11 +43992,11 @@ namespace exprtk
             switch (mode)
             {
                case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
-                                 read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
+                                 read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
                               break;
 
                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
-                                 read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
+                                 read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
                               break;
 
                default      : return false;
@@ -38574,11 +44060,12 @@ namespace exprtk
       template <typename T>
       file_descriptor* make_handle(T v)
       {
-         file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
+         const std::size_t fd_size    = sizeof(details::file_descriptor*);
+         details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
 
-         std::memcpy(reinterpret_cast<char*>(&fd),
-                     reinterpret_cast<const char*>(&v),
-                     sizeof(fd));
+         std::memcpy(reinterpret_cast<char_ptr >(&fd),
+                     reinterpret_cast<char_cptr>(&v ),
+                     fd_size);
          return fd;
       }
 
@@ -38596,12 +44083,13 @@ namespace exprtk
          #ifdef _MSC_VER
          #pragma warning(pop)
          #endif
+         assert(sizeof(T) <= sizeof(void*));
       }
 
    } // namespace exprtk::rtl::io::file::details
 
    template <typename T>
-   class open : public exprtk::igeneric_function<T>
+   class open exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -38610,26 +44098,28 @@ namespace exprtk
       typedef typename igfun_t::generic_type        generic_type;
       typedef typename generic_type::string_view    string_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       open()
       : exprtk::igeneric_function<T>("S|SS")
       { details::perform_check<T>(); }
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
-         std::string file_name = to_str(string_t(parameters[0]));
-         std::string access;
+         const std::string file_name = to_str(string_t(parameters[0]));
 
          if (file_name.empty())
+         {
             return T(0);
+         }
 
-         if (0 == ps_index)
-            access = "r";
-         else if (0 == string_t(parameters[1]).size())
+         if ((1 == ps_index) && (0 == string_t(parameters[1]).size()))
+         {
             return T(0);
-         else
-            access = to_str(string_t(parameters[1]));
+         }
+
+         const std::string access =
+            (0 == ps_index) ? "r" : to_str(string_t(parameters[1]));
 
          details::file_descriptor* fd = new details::file_descriptor(file_name,access);
 
@@ -38637,9 +44127,11 @@ namespace exprtk
          {
             T t = T(0);
 
+            const std::size_t fd_size = sizeof(details::file_descriptor*);
+
             std::memcpy(reinterpret_cast<char*>(&t ),
                         reinterpret_cast<char*>(&fd),
-                        sizeof(fd));
+                        fd_size);
             return t;
          }
          else
@@ -38651,7 +44143,7 @@ namespace exprtk
    };
 
    template <typename T>
-   struct close : public exprtk::ifunction<T>
+   struct close exprtk_final : public exprtk::ifunction<T>
    {
       using exprtk::ifunction<T>::operator();
 
@@ -38659,7 +44151,7 @@ namespace exprtk
       : exprtk::ifunction<T>(1)
       { details::perform_check<T>(); }
 
-      inline T operator() (const T& v)
+      inline T operator() (const T& v) exprtk_override
       {
          details::file_descriptor* fd = details::make_handle(v);
 
@@ -38673,7 +44165,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class write : public exprtk::igeneric_function<T>
+   class write exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -38684,42 +44176,42 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       write()
       : igfun_t("TS|TST|TV|TVT")
       { details::perform_check<T>(); }
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
 
-         std::size_t amount = 0;
-
          switch (ps_index)
          {
             case 0  : {
                          const string_t buffer(parameters[1]);
-                         amount = buffer.size();
+                         const std::size_t amount = buffer.size();
                          return T(fd->write(buffer, amount) ? 1 : 0);
                       }
 
             case 1  : {
                          const string_t buffer(parameters[1]);
-                         amount = std::min(buffer.size(),
+                         const std::size_t amount =
+                                  std::min(buffer.size(),
                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
                          return T(fd->write(buffer, amount) ? 1 : 0);
                       }
 
             case 2  : {
                          const vector_t vec(parameters[1]);
-                         amount = vec.size();
+                         const std::size_t amount = vec.size();
                          return T(fd->write(vec, amount) ? 1 : 0);
                       }
 
             case 3  : {
                          const vector_t vec(parameters[1]);
-                         amount = std::min(vec.size(),
+                         const std::size_t amount =
+                                  std::min(vec.size(),
                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
                          return T(fd->write(vec, amount) ? 1 : 0);
                       }
@@ -38730,7 +44222,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class read : public exprtk::igeneric_function<T>
+   class read exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -38741,42 +44233,42 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       read()
       : igfun_t("TS|TST|TV|TVT")
       { details::perform_check<T>(); }
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
 
-         std::size_t amount = 0;
-
          switch (ps_index)
          {
             case 0  : {
                          string_t buffer(parameters[1]);
-                         amount = buffer.size();
+                         const std::size_t amount = buffer.size();
                          return T(fd->read(buffer,amount) ? 1 : 0);
                       }
 
             case 1  : {
                          string_t buffer(parameters[1]);
-                         amount = std::min(buffer.size(),
+                         const std::size_t amount =
+                                  std::min(buffer.size(),
                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
                          return T(fd->read(buffer,amount) ? 1 : 0);
                       }
 
             case 2  : {
                          vector_t vec(parameters[1]);
-                         amount = vec.size();
+                         const std::size_t amount = vec.size();
                          return T(fd->read(vec,amount) ? 1 : 0);
                       }
 
             case 3  : {
                          vector_t vec(parameters[1]);
-                         amount = std::min(vec.size(),
+                         const std::size_t amount =
+                                  std::min(vec.size(),
                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
                          return T(fd->read(vec,amount) ? 1 : 0);
                       }
@@ -38787,7 +44279,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class getline : public exprtk::igeneric_function<T>
+   class getline exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -38797,14 +44289,13 @@ namespace exprtk
       typedef typename generic_type::string_view    string_t;
       typedef typename generic_type::scalar_view    scalar_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       getline()
       : igfun_t("T",igfun_t::e_rtrn_string)
       { details::perform_check<T>(); }
 
-      inline T operator() (std::string& result,
-                           parameter_list_t parameters)
+      inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override
       {
          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
          return T(fd->getline(result) ? 1 : 0);
@@ -38812,7 +44303,7 @@ namespace exprtk
    };
 
    template <typename T>
-   struct eof : public exprtk::ifunction<T>
+   struct eof exprtk_final : public exprtk::ifunction<T>
    {
       using exprtk::ifunction<T>::operator();
 
@@ -38820,10 +44311,9 @@ namespace exprtk
       : exprtk::ifunction<T>(1)
       { details::perform_check<T>(); }
 
-      inline T operator() (const T& v)
+      inline T operator() (const T& v) exprtk_override
       {
          details::file_descriptor* fd = details::make_handle(v);
-
          return (fd->eof() ? T(1) : T(0));
       }
    };
@@ -38840,7 +44330,7 @@ namespace exprtk
 
       bool register_package(exprtk::symbol_table<T>& symtab)
       {
-         #define exprtk_register_function(FunctionName,FunctionType)                    \
+         #define exprtk_register_function(FunctionName, FunctionType)                   \
          if (!symtab.add_function(FunctionName,FunctionType))                           \
          {                                                                              \
             exprtk_debug((                                                              \
@@ -38849,12 +44339,12 @@ namespace exprtk
             return false;                                                               \
          }                                                                              \
 
-         exprtk_register_function("open"   ,o)
-         exprtk_register_function("close"  ,c)
-         exprtk_register_function("write"  ,w)
-         exprtk_register_function("read"   ,r)
-         exprtk_register_function("getline",g)
-         exprtk_register_function("eof"    ,e)
+         exprtk_register_function("open"    , o)
+         exprtk_register_function("close"   , c)
+         exprtk_register_function("write"   , w)
+         exprtk_register_function("read"    , r)
+         exprtk_register_function("getline" , g)
+         exprtk_register_function("eof"     , e)
          #undef exprtk_register_function
 
          return true;
@@ -38933,44 +44423,61 @@ namespace exprtk
    } // namespace exprtk::rtl::details
 
    template <typename T>
-   class all_true : public exprtk::igeneric_function<T>
+   class all_true exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
       typedef typename exprtk::igeneric_function<T> igfun_t;
       typedef typename igfun_t::parameter_list_t    parameter_list_t;
       typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       all_true()
-      : exprtk::igeneric_function<T>("V|VTT")
+      : exprtk::igeneric_function<T>("V|VTT|T*")
         /*
            Overloads:
            0. V   - vector
            1. VTT - vector, r0, r1
+           2. T*  - T....T
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
-         const vector_t vec(parameters[0]);
+         if (2 == ps_index)
+         {
+            for (std::size_t i = 0; i < parameters.size(); ++i)
+            {
+               if (scalar_t(parameters[i])() == T(0))
+               {
+                  return T(0);
+               }
+            }
+         }
+         else
+         {
+            const vector_t vec(parameters[0]);
 
-         std::size_t r0 = 0;
-         std::size_t r1 = vec.size() - 1;
+            std::size_t r0 = 0;
+            std::size_t r1 = vec.size() - 1;
 
-         if (
-              (1 == ps_index) &&
-              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
-            )
-            return std::numeric_limits<T>::quiet_NaN();
+            if (
+                 (1 == ps_index) &&
+                 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+               )
+            {
+               return std::numeric_limits<T>::quiet_NaN();
+            }
 
-         for (std::size_t i = r0; i <= r1; ++i)
-         {
-            if (vec[i] == T(0))
+            for (std::size_t i = r0; i <= r1; ++i)
             {
-               return T(0);
+               if (vec[i] == T(0))
+               {
+                  return T(0);
+               }
             }
          }
 
@@ -38979,44 +44486,61 @@ namespace exprtk
    };
 
    template <typename T>
-   class all_false : public exprtk::igeneric_function<T>
+   class all_false exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
       typedef typename exprtk::igeneric_function<T> igfun_t;
       typedef typename igfun_t::parameter_list_t    parameter_list_t;
       typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       all_false()
-      : exprtk::igeneric_function<T>("V|VTT")
+      : exprtk::igeneric_function<T>("V|VTT|T*")
         /*
            Overloads:
            0. V   - vector
            1. VTT - vector, r0, r1
+           2. T*  - T....T
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
-         const vector_t vec(parameters[0]);
+         if (2 == ps_index)
+         {
+            for (std::size_t i = 0; i < parameters.size(); ++i)
+            {
+               if (scalar_t(parameters[i])() != T(0))
+               {
+                  return T(0);
+               }
+            }
+         }
+         else
+         {
+            const vector_t vec(parameters[0]);
 
-         std::size_t r0 = 0;
-         std::size_t r1 = vec.size() - 1;
+            std::size_t r0 = 0;
+            std::size_t r1 = vec.size() - 1;
 
-         if (
-              (1 == ps_index) &&
-              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
-            )
-            return std::numeric_limits<T>::quiet_NaN();
+            if (
+                 (1 == ps_index) &&
+                 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+               )
+            {
+               return std::numeric_limits<T>::quiet_NaN();
+            }
 
-         for (std::size_t i = r0; i <= r1; ++i)
-         {
-            if (vec[i] != T(0))
+            for (std::size_t i = r0; i <= r1; ++i)
             {
-               return T(0);
+               if (vec[i] != T(0))
+               {
+                  return T(0);
+               }
             }
          }
 
@@ -39025,44 +44549,61 @@ namespace exprtk
    };
 
    template <typename T>
-   class any_true : public exprtk::igeneric_function<T>
+   class any_true exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
       typedef typename exprtk::igeneric_function<T> igfun_t;
       typedef typename igfun_t::parameter_list_t    parameter_list_t;
       typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       any_true()
-      : exprtk::igeneric_function<T>("V|VTT")
+      : exprtk::igeneric_function<T>("V|VTT|T*")
         /*
            Overloads:
            0. V   - vector
            1. VTT - vector, r0, r1
+           2. T*  - T....T
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
-         const vector_t vec(parameters[0]);
+         if (2 == ps_index)
+         {
+            for (std::size_t i = 0; i < parameters.size(); ++i)
+            {
+               if (scalar_t(parameters[i])() != T(0))
+               {
+                  return T(1);
+               }
+            }
+         }
+         else
+         {
+            const vector_t vec(parameters[0]);
 
-         std::size_t r0 = 0;
-         std::size_t r1 = vec.size() - 1;
+            std::size_t r0 = 0;
+            std::size_t r1 = vec.size() - 1;
 
-         if (
-              (1 == ps_index) &&
-              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
-            )
-            return std::numeric_limits<T>::quiet_NaN();
+            if (
+                 (1 == ps_index) &&
+                 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+               )
+            {
+               return std::numeric_limits<T>::quiet_NaN();
+            }
 
-         for (std::size_t i = r0; i <= r1; ++i)
-         {
-            if (vec[i] != T(0))
+            for (std::size_t i = r0; i <= r1; ++i)
             {
-               return T(1);
+               if (vec[i] != T(0))
+               {
+                  return T(1);
+               }
             }
          }
 
@@ -39071,44 +44612,61 @@ namespace exprtk
    };
 
    template <typename T>
-   class any_false : public exprtk::igeneric_function<T>
+   class any_false exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
       typedef typename exprtk::igeneric_function<T> igfun_t;
       typedef typename igfun_t::parameter_list_t    parameter_list_t;
       typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       any_false()
-      : exprtk::igeneric_function<T>("V|VTT")
+      : exprtk::igeneric_function<T>("V|VTT|T*")
         /*
            Overloads:
            0. V   - vector
            1. VTT - vector, r0, r1
+           2. T*  - T....T
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
-         const vector_t vec(parameters[0]);
+         if (2 == ps_index)
+         {
+            for (std::size_t i = 0; i < parameters.size(); ++i)
+            {
+               if (scalar_t(parameters[i])() == T(0))
+               {
+                  return T(1);
+               }
+            }
+         }
+         else
+         {
+            const vector_t vec(parameters[0]);
 
-         std::size_t r0 = 0;
-         std::size_t r1 = vec.size() - 1;
+            std::size_t r0 = 0;
+            std::size_t r1 = vec.size() - 1;
 
-         if (
-              (1 == ps_index) &&
-              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
-            )
-            return std::numeric_limits<T>::quiet_NaN();
+            if (
+                 (1 == ps_index) &&
+                 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+               )
+            {
+               return std::numeric_limits<T>::quiet_NaN();
+            }
 
-         for (std::size_t i = r0; i <= r1; ++i)
-         {
-            if (vec[i] == T(0))
+            for (std::size_t i = r0; i <= r1; ++i)
             {
-               return T(1);
+               if (vec[i] == T(0))
+               {
+                  return T(1);
+               }
             }
          }
 
@@ -39117,44 +44675,58 @@ namespace exprtk
    };
 
    template <typename T>
-   class count : public exprtk::igeneric_function<T>
+   class count exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
       typedef typename exprtk::igeneric_function<T> igfun_t;
       typedef typename igfun_t::parameter_list_t    parameter_list_t;
       typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       count()
-      : exprtk::igeneric_function<T>("V|VTT")
+      : exprtk::igeneric_function<T>("V|VTT|T*")
         /*
            Overloads:
            0. V   - vector
            1. VTT - vector, r0, r1
+           2. T*  - T....T
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
-         const vector_t vec(parameters[0]);
+         std::size_t cnt = 0;
 
-         std::size_t r0 = 0;
-         std::size_t r1 = vec.size() - 1;
+         if (2 == ps_index)
+         {
+            for (std::size_t i = 0; i < parameters.size(); ++i)
+            {
+               if (scalar_t(parameters[i])() != T(0)) ++cnt;
+            }
+         }
+         else
+         {
+            const vector_t vec(parameters[0]);
 
-         if (
-              (1 == ps_index) &&
-              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
-            )
-            return std::numeric_limits<T>::quiet_NaN();
+            std::size_t r0 = 0;
+            std::size_t r1 = vec.size() - 1;
 
-         std::size_t cnt = 0;
+            if (
+                 (1 == ps_index) &&
+                 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+               )
+            {
+               return std::numeric_limits<T>::quiet_NaN();
+            }
 
-         for (std::size_t i = r0; i <= r1; ++i)
-         {
-            if (vec[i] != T(0)) ++cnt;
+            for (std::size_t i = r0; i <= r1; ++i)
+            {
+               if (vec[i] != T(0)) ++cnt;
+            }
          }
 
          return T(cnt);
@@ -39162,7 +44734,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class copy : public exprtk::igeneric_function<T>
+   class copy exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39172,7 +44744,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       copy()
       : exprtk::igeneric_function<T>("VV|VTTVTT")
@@ -39183,7 +44755,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[0]);
                vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
@@ -39205,14 +44777,17 @@ namespace exprtk
 
          const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
 
-         std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
+         std::copy(
+            x.begin() + xr0,
+            x.begin() + xr0 + n,
+            y.begin() + yr0);
 
          return T(n);
       }
    };
 
    template <typename T>
-   class rol : public exprtk::igeneric_function<T>
+   class rol exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39222,7 +44797,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       rol()
       : exprtk::igeneric_function<T>("VT|VTTT")
@@ -39233,7 +44808,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
@@ -39263,7 +44838,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class ror : public exprtk::igeneric_function<T>
+   class ror exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39273,7 +44848,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       ror()
       : exprtk::igeneric_function<T>("VT|VTTT")
@@ -39284,7 +44859,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
@@ -39301,8 +44876,8 @@ namespace exprtk
             )
             return T(0);
 
-         std::size_t dist  = r1 - r0 + 1;
-         std::size_t shift = (dist - (n % dist)) % dist;
+         const std::size_t dist  = r1 - r0 + 1;
+         const std::size_t shift = (dist - (n % dist)) % dist;
 
          std::rotate(
             vec.begin() + r0,
@@ -39314,7 +44889,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class shift_left : public exprtk::igeneric_function<T>
+   class reverse exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39324,7 +44899,48 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
+
+      reverse()
+      : exprtk::igeneric_function<T>("V|VTT")
+        /*
+           Overloads:
+           0. V   - vector
+           1. VTT - vector, r0, r1
+        */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         vector_t vec(parameters[0]);
+
+         std::size_t r0 = 0;
+         std::size_t r1 = vec.size() - 1;
+
+         if (
+              (1 == ps_index) &&
+              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+            )
+            return T(0);
+
+         std::reverse(vec.begin() + r0, vec.begin() + r1 + 1);
+
+         return T(1);
+      }
+   };
+
+   template <typename T>
+   class shift_left exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
 
       shift_left()
       : exprtk::igeneric_function<T>("VT|VTTT")
@@ -39335,7 +44951,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
@@ -39352,7 +44968,7 @@ namespace exprtk
             )
             return T(0);
 
-         const std::size_t dist  = r1 - r0 + 1;
+         const std::size_t dist = r1 - r0 + 1;
 
          if (n > dist)
             return T(0);
@@ -39362,7 +44978,7 @@ namespace exprtk
             vec.begin() + r0 + n,
             vec.begin() + r1 + 1);
 
-         for (std::size_t i = r1 - n + 1; i <= r1; ++i)
+         for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i)
          {
             vec[i] = T(0);
          }
@@ -39372,7 +44988,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class shift_right : public exprtk::igeneric_function<T>
+   class shift_right exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39382,7 +44998,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       shift_right()
       : exprtk::igeneric_function<T>("VT|VTTT")
@@ -39393,7 +45009,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
@@ -39410,7 +45026,7 @@ namespace exprtk
             )
             return T(0);
 
-         const std::size_t dist  = r1 - r0 + 1;
+         const std::size_t dist = r1 - r0 + 1;
 
          if (n > dist)
             return T(0);
@@ -39432,7 +45048,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class sort : public exprtk::igeneric_function<T>
+   class sort exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39442,7 +45058,7 @@ namespace exprtk
       typedef typename generic_type::string_view    string_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       sort()
       : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
@@ -39455,7 +45071,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
@@ -39480,16 +45096,22 @@ namespace exprtk
          }
 
          if (ascending)
-            std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T>   ());
+            std::sort(
+               vec.begin() + r0,
+               vec.begin() + r1 + 1,
+               std::less<T>());
          else
-            std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
+            std::sort(
+               vec.begin() + r0,
+               vec.begin() + r1 + 1,
+               std::greater<T>());
 
          return T(1);
       }
    };
 
    template <typename T>
-   class nthelement : public exprtk::igeneric_function<T>
+   class nthelement exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39499,7 +45121,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       nthelement()
       : exprtk::igeneric_function<T>("VT|VTTT")
@@ -39510,7 +45132,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
@@ -39522,16 +45144,21 @@ namespace exprtk
             return T(0);
 
          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
+         {
             return std::numeric_limits<T>::quiet_NaN();
+         }
 
-         std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
+         std::nth_element(
+            vec.begin() + r0,
+            vec.begin() + r0 + n ,
+            vec.begin() + r1 + 1);
 
          return T(1);
       }
    };
 
    template <typename T>
-   class iota : public exprtk::igeneric_function<T>
+   class assign exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39541,41 +45168,101 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
+
+      assign()
+      : exprtk::igeneric_function<T>("VT|VTTT|VTTTT")
+        /*
+           Overloads:
+           0. VT    - vector, V
+           1. VTTT  - vector, V, r0, r1
+           2. VTTTT - vector, V, r0, r1, SS
+        */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         vector_t vec(parameters[0]);
+
+         const T assign_value = scalar_t(parameters[1]);
+
+         const std::size_t step_size = (2 != ps_index) ? 1 :
+                                       static_cast<std::size_t>(scalar_t(parameters.back())());
+
+         std::size_t r0 = 0;
+         std::size_t r1 = vec.size() - 1;
+
+         if (
+              ((ps_index == 1) || (ps_index == 2)) &&
+              !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
+            )
+         {
+            return T(0);
+         }
+
+         for (std::size_t i = r0; i <= r1; i += step_size)
+         {
+            vec[i] = assign_value;
+         }
+
+         return T(1);
+      }
+   };
+
+   template <typename T>
+   class iota exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
 
       iota()
-      : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
+      : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT")
         /*
            Overloads:
-           0. VT    - vector, increment
-           1. VTT   - vector, increment, base
-           2. VTTTT - vector, increment, r0, r1
-           3. VTTTT - vector, increment, base, r0, r1
+           0. VTT  - vector, SV, SS
+           1. VT   - vector, SV, SS (+1)
+           2. VTTT - vector, r0, r1, SV, SS
+           3. VTT  - vector, r0, r1, SV, SS (+1)
+
+           Where:
+           1. SV - Start value
+           2. SS - Step size
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          vector_t vec(parameters[0]);
 
-         T increment = scalar_t(parameters[1])();
-         T base      = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
+         const T start_value = (ps_index <= 1) ?
+                               scalar_t(parameters[1]) :
+                               scalar_t(parameters[3]) ;
+
+         const T step_size = ((0 == ps_index) || (2 == ps_index)) ?
+                             scalar_t(parameters.back())() :
+                             T(1) ;
 
          std::size_t r0 = 0;
          std::size_t r1 = vec.size() - 1;
 
-         if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
-            return std::numeric_limits<T>::quiet_NaN();
-         else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
-            return std::numeric_limits<T>::quiet_NaN();
-         else
+         if (
+              ((ps_index == 2) || (ps_index == 3)) &&
+              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+            )
          {
-            long long j = 0;
+            return T(0);
+         }
 
-            for (std::size_t i = r0; i <= r1; ++i, ++j)
-            {
-               vec[i] = base + (increment * j);
-            }
+         for (std::size_t i = r0; i <= r1; ++i)
+         {
+            vec[i] = start_value + ((i - r0) * step_size);
          }
 
          return T(1);
@@ -39583,40 +45270,50 @@ namespace exprtk
    };
 
    template <typename T>
-   class sumk : public exprtk::igeneric_function<T>
+   class sumk exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
       typedef typename exprtk::igeneric_function<T> igfun_t;
       typedef typename igfun_t::parameter_list_t    parameter_list_t;
       typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       sumk()
-      : exprtk::igeneric_function<T>("V|VTT")
+      : exprtk::igeneric_function<T>("V|VTT|VTTT")
         /*
            Overloads:
-           0. V   - vector
-           1. VTT - vector, r0, r1
+           0. V    - vector
+           1. VTT  - vector, r0, r1
+           2. VTTT - vector, r0, r1, stride
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t vec(parameters[0]);
 
+         const std::size_t stride = (2 != ps_index) ? 1 :
+                                    static_cast<std::size_t>(scalar_t(parameters[3])());
+
          std::size_t r0 = 0;
          std::size_t r1 = vec.size() - 1;
 
-         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
+         if (
+              ((1 == ps_index) || (2 == ps_index)) &&
+              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+            )
+         {
             return std::numeric_limits<T>::quiet_NaN();
+         }
 
          T result = T(0);
          T error  = T(0);
 
-         for (std::size_t i = r0; i <= r1; ++i)
+         for (std::size_t i = r0; i <= r1; i += stride)
          {
             details::kahan_sum(result, error, vec[i]);
          }
@@ -39626,7 +45323,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class axpy : public exprtk::igeneric_function<T>
+   class axpy exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39636,7 +45333,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       axpy()
       : exprtk::igeneric_function<T>("TVV|TVVTT")
@@ -39648,7 +45345,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[1]);
                vector_t y(parameters[2]);
@@ -39673,7 +45370,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class axpby : public exprtk::igeneric_function<T>
+   class axpby exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39683,7 +45380,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       axpby()
       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
@@ -39695,7 +45392,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[1]);
                vector_t y(parameters[3]);
@@ -39721,7 +45418,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class axpyz : public exprtk::igeneric_function<T>
+   class axpyz exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39731,7 +45428,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       axpyz()
       : exprtk::igeneric_function<T>("TVVV|TVVVTT")
@@ -39743,7 +45440,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[1]);
          const vector_t y(parameters[2]);
@@ -39752,7 +45449,7 @@ namespace exprtk
          std::size_t r0 = 0;
          std::size_t r1 = std::min(x.size(),y.size()) - 1;
 
-         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
+         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
             return std::numeric_limits<T>::quiet_NaN();
          else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
@@ -39771,7 +45468,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class axpbyz : public exprtk::igeneric_function<T>
+   class axpbyz exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39781,7 +45478,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       axpbyz()
       : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
@@ -39793,7 +45490,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[1]);
          const vector_t y(parameters[3]);
@@ -39802,7 +45499,7 @@ namespace exprtk
          std::size_t r0 = 0;
          std::size_t r1 = std::min(x.size(),y.size()) - 1;
 
-         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
+         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
             return std::numeric_limits<T>::quiet_NaN();
          else if (helper::invalid_range(y, r0, r1))
             return std::numeric_limits<T>::quiet_NaN();
@@ -39822,7 +45519,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class axpbz : public exprtk::igeneric_function<T>
+   class axpbsy exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39832,7 +45529,110 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
+
+      axpbsy()
+      : exprtk::igeneric_function<T>("TVTTV|TVTTVTT")
+        /*
+           y <- ax + by
+           Overloads:
+           0. TVTVV   - a, x(vector), b, shift, y(vector), z(vector)
+           1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
+        */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         const vector_t x(parameters[1]);
+               vector_t y(parameters[4]);
+
+         std::size_t r0 = 0;
+         std::size_t r1 = std::min(x.size(),y.size()) - 1;
+
+         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
+            return std::numeric_limits<T>::quiet_NaN();
+         else if (helper::invalid_range(y, r0, r1))
+            return std::numeric_limits<T>::quiet_NaN();
+
+         const T a = scalar_t(parameters[0])();
+         const T b = scalar_t(parameters[2])();
+
+         const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
+
+         for (std::size_t i = r0; i <= r1; ++i)
+         {
+            y[i] = (a * x[i]) + (b * y[i + s]);
+         }
+
+         return T(1);
+      }
+   };
+
+   template <typename T>
+   class axpbsyz exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
+
+      axpbsyz()
+      : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT")
+        /*
+           z <- ax + by
+           Overloads:
+           0. TVTVV   - a, x(vector), b, shift, y(vector), z(vector)
+           1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
+        */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         const vector_t x(parameters[1]);
+         const vector_t y(parameters[4]);
+               vector_t z(parameters[5]);
+
+         std::size_t r0 = 0;
+         std::size_t r1 = std::min(x.size(),y.size()) - 1;
+
+         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1))
+            return std::numeric_limits<T>::quiet_NaN();
+         else if (helper::invalid_range(y, r0, r1))
+            return std::numeric_limits<T>::quiet_NaN();
+         else if (helper::invalid_range(z, r0, r1))
+            return std::numeric_limits<T>::quiet_NaN();
+
+         const T a = scalar_t(parameters[0])();
+         const T b = scalar_t(parameters[2])();
+
+         const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
+
+         for (std::size_t i = r0; i <= r1; ++i)
+         {
+            z[i] = (a * x[i]) + (b * y[i + s]);
+         }
+
+         return T(1);
+      }
+   };
+
+   template <typename T>
+   class axpbz exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
 
       axpbz()
       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
@@ -39844,7 +45644,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[1]);
                vector_t z(parameters[3]);
@@ -39870,7 +45670,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class dot : public exprtk::igeneric_function<T>
+   class diff exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39880,7 +45680,55 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
+
+      diff()
+      : exprtk::igeneric_function<T>("VV|VVT")
+        /*
+           x_(i - stride) - x_i
+           Overloads:
+           0. VV  - x(vector), y(vector)
+           1. VVT - x(vector), y(vector), stride
+        */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         const vector_t x(parameters[0]);
+               vector_t y(parameters[1]);
+
+         const std::size_t r0 = 0;
+         const std::size_t r1 = std::min(x.size(),y.size()) - 1;
+
+         const std::size_t stride = (1 != ps_index) ? 1 :
+                                    std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])()));
+
+         for (std::size_t i = 0; i < stride; ++i)
+         {
+            y[i] = std::numeric_limits<T>::quiet_NaN();
+         }
+
+         for (std::size_t i = (r0 + stride); i <= r1; ++i)
+         {
+            y[i] = x[i] - x[i - stride];
+         }
+
+         return T(1);
+      }
+   };
+
+   template <typename T>
+   class dot exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
 
       dot()
       : exprtk::igeneric_function<T>("VV|VVTT")
@@ -39891,7 +45739,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[0]);
          const vector_t y(parameters[1]);
@@ -39916,7 +45764,7 @@ namespace exprtk
    };
 
    template <typename T>
-   class dotk : public exprtk::igeneric_function<T>
+   class dotk exprtk_final : public exprtk::igeneric_function<T>
    {
    public:
 
@@ -39926,7 +45774,7 @@ namespace exprtk
       typedef typename generic_type::scalar_view    scalar_t;
       typedef typename generic_type::vector_view    vector_t;
 
-      using exprtk::igeneric_function<T>::operator();
+      using igfun_t::operator();
 
       dotk()
       : exprtk::igeneric_function<T>("VV|VVTT")
@@ -39937,7 +45785,7 @@ namespace exprtk
         */
       {}
 
-      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
       {
          const vector_t x(parameters[0]);
          const vector_t y(parameters[1]);
@@ -39962,34 +45810,159 @@ namespace exprtk
       }
    };
 
+   template <typename T>
+   class threshold_below exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
+
+      threshold_below()
+      : exprtk::igeneric_function<T>("VTT|VTTTT")
+      /*
+         Overloads:
+         0. VTT   - vector, TV, SV
+         1. VTTTT - vector, r0, r1, TV, SV
+
+         Where:
+         TV - Threshold value
+         SV - Snap-to value
+      */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         vector_t vec(parameters[0]);
+
+         const T threshold_value = (0 == ps_index) ?
+                                   scalar_t(parameters[1]) :
+                                   scalar_t(parameters[3]) ;
+
+         const T snap_value = scalar_t(parameters.back());
+
+         std::size_t r0 = 0;
+         std::size_t r1 = vec.size() - 1;
+
+         if (
+              (1 == ps_index) &&
+              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+            )
+         {
+            return T(0);
+         }
+
+         for (std::size_t i = r0; i <= r1; ++i)
+         {
+            if (vec[i] < threshold_value)
+            {
+               vec[i] = snap_value;
+            }
+         }
+
+         return T(1);
+      }
+   };
+
+   template <typename T>
+   class threshold_above exprtk_final : public exprtk::igeneric_function<T>
+   {
+   public:
+
+      typedef typename exprtk::igeneric_function<T> igfun_t;
+      typedef typename igfun_t::parameter_list_t    parameter_list_t;
+      typedef typename igfun_t::generic_type        generic_type;
+      typedef typename generic_type::scalar_view    scalar_t;
+      typedef typename generic_type::vector_view    vector_t;
+
+      using igfun_t::operator();
+
+      threshold_above()
+      : exprtk::igeneric_function<T>("VTT|VTTTT")
+      /*
+         Overloads:
+         0. VTT   - vector, TV, SV
+         1. VTTTT - vector, r0, r1, TV, SV
+
+         Where:
+         TV - Threshold value
+         SV - Snap-to value
+      */
+      {}
+
+      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
+      {
+         vector_t vec(parameters[0]);
+
+         const T threshold_value = (0 == ps_index) ?
+                                   scalar_t(parameters[1]) :
+                                   scalar_t(parameters[3]) ;
+
+         const T snap_value = scalar_t(parameters.back());
+
+         std::size_t r0 = 0;
+         std::size_t r1 = vec.size() - 1;
+
+         if (
+              (1 == ps_index) &&
+              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
+            )
+         {
+            return T(0);
+         }
+
+         for (std::size_t i = r0; i <= r1; ++i)
+         {
+            if (vec[i] > threshold_value)
+            {
+               vec[i] = snap_value;
+            }
+         }
+
+         return T(1);
+      }
+   };
+
    template <typename T>
    struct package
    {
-      all_true   <T> at;
-      all_false  <T> af;
-      any_true   <T> nt;
-      any_false  <T> nf;
-      count      <T>  c;
-      copy       <T> cp;
-      rol        <T> rl;
-      ror        <T> rr;
-      shift_left <T> sl;
-      shift_right<T> sr;
-      sort       <T> st;
-      nthelement <T> ne;
-      iota       <T> ia;
-      sumk       <T> sk;
-      axpy       <T> b1_axpy;
-      axpby      <T> b1_axpby;
-      axpyz      <T> b1_axpyz;
-      axpbyz     <T> b1_axpbyz;
-      axpbz      <T> b1_axpbz;
-      dot        <T> dt;
-      dotk       <T> dtk;
+      all_true       <T> at;
+      all_false      <T> af;
+      any_true       <T> nt;
+      any_false      <T> nf;
+      count          <T>  c;
+      copy           <T> cp;
+      rol            <T> rl;
+      ror            <T> rr;
+      reverse        <T> rev;
+      shift_left     <T> sl;
+      shift_right    <T> sr;
+      sort           <T> st;
+      nthelement     <T> ne;
+      assign         <T> an;
+      iota           <T> ia;
+      sumk           <T> sk;
+      axpy           <T> b1_axpy;
+      axpby          <T> b1_axpby;
+      axpyz          <T> b1_axpyz;
+      axpbyz         <T> b1_axpbyz;
+      axpbsy         <T> b1_axpbsy;
+      axpbsyz        <T> b1_axpbsyz;
+      axpbz          <T> b1_axpbz;
+      diff           <T> df;
+      dot            <T> dt;
+      dotk           <T> dtk;
+      threshold_above<T> ta;
+      threshold_below<T> tb;
 
       bool register_package(exprtk::symbol_table<T>& symtab)
       {
-         #define exprtk_register_function(FunctionName,FunctionType)                  \
+         #define exprtk_register_function(FunctionName, FunctionType)                 \
          if (!symtab.add_function(FunctionName,FunctionType))                         \
          {                                                                            \
             exprtk_debug((                                                            \
@@ -39998,29 +45971,36 @@ namespace exprtk
             return false;                                                             \
          }                                                                            \
 
-         exprtk_register_function("all_true"     ,at)
-         exprtk_register_function("all_false"    ,af)
-         exprtk_register_function("any_true"     ,nt)
-         exprtk_register_function("any_false"    ,nf)
-         exprtk_register_function("count"        , c)
-         exprtk_register_function("copy"         ,cp)
-         exprtk_register_function("rotate_left"  ,rl)
-         exprtk_register_function("rol"          ,rl)
-         exprtk_register_function("rotate_right" ,rr)
-         exprtk_register_function("ror"          ,rr)
-         exprtk_register_function("shftl"        ,sl)
-         exprtk_register_function("shftr"        ,sr)
-         exprtk_register_function("sort"         ,st)
-         exprtk_register_function("nth_element"  ,ne)
-         exprtk_register_function("iota"         ,ia)
-         exprtk_register_function("sumk"         ,sk)
-         exprtk_register_function("axpy"    ,b1_axpy)
-         exprtk_register_function("axpby"  ,b1_axpby)
-         exprtk_register_function("axpyz"  ,b1_axpyz)
-         exprtk_register_function("axpbyz",b1_axpbyz)
-         exprtk_register_function("axpbz"  ,b1_axpbz)
-         exprtk_register_function("dot"          ,dt)
-         exprtk_register_function("dotk"        ,dtk)
+         exprtk_register_function("all_true"        , at        )
+         exprtk_register_function("all_false"       , af        )
+         exprtk_register_function("any_true"        , nt        )
+         exprtk_register_function("any_false"       , nf        )
+         exprtk_register_function("count"           , c         )
+         exprtk_register_function("copy"            , cp        )
+         exprtk_register_function("rotate_left"     , rl        )
+         exprtk_register_function("rol"             , rl        )
+         exprtk_register_function("rotate_right"    , rr        )
+         exprtk_register_function("ror"             , rr        )
+         exprtk_register_function("reverse"         , rev       )
+         exprtk_register_function("shftl"           , sl        )
+         exprtk_register_function("shftr"           , sr        )
+         exprtk_register_function("sort"            , st        )
+         exprtk_register_function("nth_element"     , ne        )
+         exprtk_register_function("assign"          , an        )
+         exprtk_register_function("iota"            , ia        )
+         exprtk_register_function("sumk"            , sk        )
+         exprtk_register_function("axpy"            , b1_axpy   )
+         exprtk_register_function("axpby"           , b1_axpby  )
+         exprtk_register_function("axpyz"           , b1_axpyz  )
+         exprtk_register_function("axpbyz"          , b1_axpbyz )
+         exprtk_register_function("axpbsy"          , b1_axpbsy )
+         exprtk_register_function("axpbsyz"         , b1_axpbsyz)
+         exprtk_register_function("axpbz"           , b1_axpbz  )
+         exprtk_register_function("diff"            , df        )
+         exprtk_register_function("dot"             , dt        )
+         exprtk_register_function("dotk"            , dtk       )
+         exprtk_register_function("threshold_above" , ta        )
+         exprtk_register_function("threshold_below" , tb        )
          #undef exprtk_register_function
 
          return true;
@@ -40036,18 +46016,22 @@ namespace exprtk
 {
    namespace information
    {
-      static const char* library = "Mathematical Expression Toolkit";
-      static const char* version = "2.718281828459045235360287471352"
-                                   "66249775724709369995957496696762"
-                                   "77240766303535475945713821785251"
-                                   "66427427466391932003059921817413";
-      static const char* date    = "20210101";
+      using ::exprtk::details::char_cptr;
+
+      static char_cptr library = "Mathematical Expression Toolkit";
+      static char_cptr version = "2.718281828459045235360287471352662497757"
+                                 "24709369995957496696762772407663035354759"
+                                 "45713821785251664274274663919320030599218"
+                                 "17413596629043572900334295260595630738132";
+      static char_cptr date    = "20240101";
+      static char_cptr min_cpp = "199711L";
 
       static inline std::string data()
       {
          static const std::string info_str = std::string(library) +
                                              std::string(" v") + std::string(version) +
-                                             std::string(" (") + date + std::string(")");
+                                             std::string(" (") + date + std::string(")") +
+                                             std::string(" (") + min_cpp + std::string(")");
          return info_str;
       }
 
@@ -40061,12 +46045,20 @@ namespace exprtk
    #undef exprtk_error_location
    #endif
 
-   #ifdef exprtk_disable_fallthrough_begin
-   #undef exprtk_disable_fallthrough_begin
+   #ifdef exprtk_fallthrough
+   #undef exprtk_fallthrough
+   #endif
+
+   #ifdef exprtk_override
+   #undef exprtk_override
+   #endif
+
+   #ifdef exprtk_final
+   #undef exprtk_final
    #endif
 
-   #ifdef exprtk_disable_fallthrough_end
-   #undef exprtk_disable_fallthrough_end
+   #ifdef exprtk_delete
+   #undef exprtk_delete
    #endif
 
 } // namespace exprtk