C++ Mathematical Expression Library (ExprTk)  http://www.partow.net/programming/exprtk/index.html
diff --git a/exprtk.hpp b/exprtk.hpp
index a1d7366..9cd92ff 100644
--- a/exprtk.hpp
+++ b/exprtk.hpp
@@ -2256,7 +2256,9 @@
          inline void scan_token()
          {
             skip_whitespace();
+
             skip_comments();
+
             if (is_end(s_itr_))
             {
                return;
@@ -2391,14 +2393,20 @@
          {
             /*
                Attempt to match a valid numeric value in one of the following formats:
-               1. 123456
-               2. 123.456
-               3. 123.456e3
-               4. 123.456E3
-               5. 123.456e+3
-               6. 123.456E+3
-               7. 123.456e-3
-               8. 123.456E-3
+               01. 123456
+               02. 123.456
+               03. 123.456e3
+               04. 123.456E3
+               05. 123.456e+3
+               06. 123.456E+3
+               07. 123.456e-3
+               08. 123.456E-3
+               09. .1234
+               10. .1234e3
+               11. .1234E+3
+               12. .1234e+3
+               13. .1234E-3
+               14. .1234e-3
             */
             const char* initial_itr = s_itr_;
             bool dot_found          = false;
@@ -2825,30 +2833,27 @@
             return changes;
          }
 
-         inline virtual int insert(const token&, token& )
-         {
-            return -1;
-         }
+         #define token_inserter_empty_body \
+         {                                 \
+            return -1;                     \
+         }                                 \
+
+         inline virtual int insert(const token&, token&)
+         token_inserter_empty_body
 
          inline virtual int insert(const token&, const token&, token&)
-         {
-            return -1;
-         }
+         token_inserter_empty_body
 
          inline virtual int insert(const token&, const token&, const token&, token&)
-         {
-            return -1;
-         }
+         token_inserter_empty_body
 
          inline virtual int insert(const token&, const token&, const token&, const token&, token&)
-         {
-            return -1;
-         }
+         token_inserter_empty_body
 
          inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
-         {
-            return -1;
-         }
+         token_inserter_empty_body
+
+         #undef token_inserter_empty_body
 
       private:
 
@@ -2888,7 +2893,7 @@
 
             std::size_t changes = 0;
 
-            for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i)
+            for (std::size_t i = 0; i < (g.token_list_.size() - 1); ++i)
             {
                token t;
 
@@ -2912,7 +2917,7 @@
 
             std::size_t changes = 0;
 
-            for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i)
+            for (std::size_t i = 0; i < (g.token_list_.size() - 2); ++i)
             {
                token t;
 
@@ -3023,6 +3028,7 @@
                   t.type     = lexer::token::e_assign;
                   t.value    = ":=";
                   t.position = t0.position;
+
                   return true;
                }
                // '+ =' --> '+='
@@ -3031,6 +3037,7 @@
                   t.type     = lexer::token::e_addass;
                   t.value    = "+=";
                   t.position = t0.position;
+
                   return true;
                }
                // '- =' --> '-='
@@ -3039,6 +3046,7 @@
                   t.type     = lexer::token::e_subass;
                   t.value    = "-=";
                   t.position = t0.position;
+
                   return true;
                }
                // '* =' --> '*='
@@ -3047,6 +3055,7 @@
                   t.type     = lexer::token::e_mulass;
                   t.value    = "*=";
                   t.position = t0.position;
+
                   return true;
                }
                // '/ =' --> '/='
@@ -3055,6 +3064,7 @@
                   t.type     = lexer::token::e_divass;
                   t.value    = "/=";
                   t.position = t0.position;
+
                   return true;
                }
                // '% =' --> '%='
@@ -3063,6 +3073,7 @@
                   t.type     = lexer::token::e_modass;
                   t.value    = "%=";
                   t.position = t0.position;
+
                   return true;
                }
                // '> =' --> '>='
@@ -3071,6 +3082,7 @@
                   t.type     = lexer::token::e_gte;
                   t.value    = ">=";
                   t.position = t0.position;
+
                   return true;
                }
                // '< =' --> '<='
@@ -3079,6 +3091,7 @@
                   t.type     = lexer::token::e_lte;
                   t.value    = "<=";
                   t.position = t0.position;
+
                   return true;
                }
                // '= =' --> '=='
@@ -3087,6 +3100,7 @@
                   t.type     = lexer::token::e_eq;
                   t.value    = "==";
                   t.position = t0.position;
+
                   return true;
                }
                // '! =' --> '!='
@@ -3095,6 +3109,7 @@
                   t.type     = lexer::token::e_ne;
                   t.value    = "!=";
                   t.position = t0.position;
+
                   return true;
                }
                // '< >' --> '<>'
@@ -3103,6 +3118,7 @@
                   t.type     = lexer::token::e_ne;
                   t.value    = "<>";
                   t.position = t0.position;
+
                   return true;
                }
                // '<= >' --> '<=>'
@@ -3111,6 +3127,7 @@
                   t.type     = lexer::token::e_swap;
                   t.value    = "<=>";
                   t.position = t0.position;
+
                   return true;
                }
                // '+ -' --> '-'
@@ -3119,6 +3136,7 @@
                   t.type     = lexer::token::e_sub;
                   t.value    = "-";
                   t.position = t0.position;
+
                   return true;
                }
                // '- +' --> '-'
@@ -3127,6 +3145,7 @@
                   t.type     = lexer::token::e_sub;
                   t.value    = "-";
                   t.position = t0.position;
+
                   return true;
                }
                // '- -' --> '-'
@@ -3139,6 +3158,7 @@
                   t.type     = lexer::token::e_add;
                   t.value    = "+";
                   t.position = t0.position;
+
                   return true;
                }
                else
@@ -3221,14 +3241,14 @@
                   {
                      if (stack_.empty())
                      {
-                        state_ = false;
+                        state_       = false;
                         error_token_ = t;
 
                         return false;
                      }
                      else if (c != stack_.top().first)
                      {
-                        state_ = false;
+                        state_       = false;
                         error_token_ = t;
 
                         return false;
@@ -3558,6 +3578,7 @@
                }
 
                token_scanner_list.push_back(scanner);
+
                return true;
             }
 
@@ -3571,6 +3592,7 @@
                }
 
                token_modifier_list.push_back(modifier);
+
                return true;
             }
 
@@ -3584,6 +3606,7 @@
                }
 
                token_joiner_list.push_back(joiner);
+
                return true;
             }
 
@@ -3597,13 +3620,13 @@
                }
 
                token_inserter_list.push_back(inserter);
+
                return true;
             }
 
             inline bool run_modifiers(lexer::generator& g)
             {
                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
-               bool result = true;
 
                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
                {
@@ -3615,17 +3638,17 @@
                   if (!modifier.result())
                   {
                      error_token_modifier = token_modifier_list[i];
+
                      return false;
                   }
                }
 
-               return result;
+               return true;
             }
 
             inline bool run_joiners(lexer::generator& g)
             {
                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
-               bool result = true;
 
                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
                {
@@ -3637,17 +3660,17 @@
                   if (!joiner.result())
                   {
                      error_token_joiner = token_joiner_list[i];
+
                      return false;
                   }
                }
 
-               return result;
+               return true;
             }
 
             inline bool run_inserters(lexer::generator& g)
             {
                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
-               bool result = true;
 
                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
                {
@@ -3659,17 +3682,17 @@
                   if (!inserter.result())
                   {
                      error_token_inserter = token_inserter_list[i];
+
                      return false;
                   }
                }
 
-               return result;
+               return true;
             }
 
             inline bool run_scanners(lexer::generator& g)
             {
                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
-               bool result = true;
 
                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
                {
@@ -3681,11 +3704,12 @@
                   if (!scanner.result())
                   {
                      error_token_scanner = token_scanner_list[i];
+
                      return false;
                   }
                }
 
-               return result;
+               return true;
             }
 
             std::vector<lexer::token_scanner*>  token_scanner_list;
@@ -14235,120 +14259,85 @@
       virtual ~ifunction()
       {}
 
+      #define empty_method_body                      \
+      {                                              \
+         return std::numeric_limits<T>::quiet_NaN(); \
+      }                                              \
+
       inline virtual T operator()()
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&,const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
 
       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
-      {
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      empty_method_body
+
+      #undef empty_method_body
 
       std::size_t param_count;
    };
@@ -14391,33 +14380,27 @@
       virtual ~igeneric_function()
       {}
 
+      #define igeneric_function_empty_body(N)        \
+      {                                              \
+         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
+         return std::numeric_limits<T>::quiet_NaN(); \
+      }                                              \
+
       // f(i_0,i_1,....,i_N) --> Scalar
       inline virtual T operator()(parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [1]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      igeneric_function_empty_body(1)
 
       // f(i_0,i_1,....,i_N) --> String
       inline virtual T operator()(std::string&, parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [2]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      igeneric_function_empty_body(2)
 
       // f(psi,i_0,i_1,....,i_N) --> Scalar
       inline virtual T operator()(const std::size_t&, parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [3]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      igeneric_function_empty_body(3)
 
       // f(psi,i_0,i_1,....,i_N) --> String
       inline virtual T operator()(const std::size_t&, std::string&, parameter_list_t)
-      {
-         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [4]\n"));
-         return std::numeric_limits<T>::quiet_NaN();
-      }
+      igeneric_function_empty_body(4)
 
       std::string parameter_sequence;
       return_type rtrn_type;
@@ -14436,6 +14419,7 @@
       typedef T (*ff3_functor)(T,T,T);
       typedef T (*ff4_functor)(T,T,T,T);
       typedef T (*ff5_functor)(T,T,T,T,T);
+      typedef T (*ff6_functor)(T,T,T,T,T,T);
 
    protected:
 
@@ -14479,6 +14463,14 @@
          ff5_functor f;
       };
 
+      struct freefunc6 : public exprtk::ifunction<T>
+      {
+         freefunc6(ff6_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)
+         { return f(v0,v1,v2,v3,v4,v5); }
+         ff5_functor f;
+      };
+
       template <typename Type, typename RawType>
       struct type_store
       {
@@ -14762,6 +14754,7 @@
             static RawType null_type = init_type::set(RawType());
 
             tm_const_itr_t itr = map.find(symbol_name);
+
             if (map.end() == itr)
                return null_type;
             else
@@ -15372,6 +15365,22 @@
          return add_function(function_name,(*local_data().free_function_list_.back()));
       }
 
+      inline bool add_function(const std::string& function_name, ff6_functor function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+
+         exprtk::ifunction<T>* ifunc = new freefunc6(function);
+
+         local_data().free_function_list_.push_back(ifunc);
+
+         return add_function(function_name,(*local_data().free_function_list_.back()));
+      }
+
       inline bool add_reserved_function(const std::string& function_name, function_t& function)
       {
          if (!valid())
@@ -25968,6 +25977,7 @@
                   if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
                   {
                      free_node(*expr_gen.node_allocator_,branch[0]);
+
                      return result;
                   }
                }
@@ -26247,6 +26257,7 @@
                      if (details::e_pow == boc_opr)
                      {
                         bocnode->set_c(bocnode->c() * c);
+
                         return bocnode;
                      }
                   }
@@ -26362,6 +26373,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26415,6 +26427,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26430,6 +26443,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26445,6 +26459,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26460,6 +26475,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26517,6 +26533,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                      else if (details::e_sub == operation)
@@ -26561,6 +26578,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26571,6 +26589,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                      else if (details::e_sub == operation)
@@ -26578,6 +26597,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26593,6 +26613,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -26608,6 +26629,7 @@
                         result = expr_gen.node_allocator_->
                                     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]);
                      }
                   }
@@ -32504,66 +32526,71 @@
       virtual ~polynomial()
       {}
 
+      #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)
       {
-         return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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)
       {
-         return ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+         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()()
       {
          return std::numeric_limits<T>::quiet_NaN();
@@ -32645,6 +32672,19 @@
             v_.push_back(v2); v_.push_back(v3);
          }
 
+         function(const std::string& name,
+                  const std::string& expression,
+                  const std::string& v0, const std::string& v1,
+                  const std::string& v2, const std::string& v3,
+                  const std::string& v4)
+         : name_(name),
+           expression_(expression)
+         {
+            v_.push_back(v0); v_.push_back(v1);
+            v_.push_back(v2); v_.push_back(v3);
+            v_.push_back(v4);
+         }
+
          inline function& name(const std::string& n)
          {
             name_ = n;
@@ -32672,12 +32712,12 @@
 
       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::pair<T*,std::size_t> lvarref_t;
-         typedef std::vector<lvarref_t> lvr_vec_t;
+         typedef std::vector<lvarref_t>    lvr_vec_t;
 
          base_func(const std::size_t& pc = 0)
          : exprtk::ifunction<T>(pc),
@@ -32893,16 +32933,30 @@
 
       typedef const T& type;
 
+      template <typename BaseFuncType>
+      struct scoped_bft
+      {
+         scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
+        ~scoped_bft()                              { bft_.post(); }
+
+         BaseFuncType& bft_;
+
+      private:
+
+         scoped_bft(scoped_bft&);
+         scoped_bft& operator=(scoped_bft&);
+      };
+
       struct func_1param : public base_func
       {
          func_1param() : base_func(1) {}
 
          inline T operator()(type v0)
          {
-            base_func::pre();
+            scoped_bft<func_1param> sb(*this);
             base_func::update(v0);
             T result = this->value(base_func::expression);
-            base_func::post();
+
             return result;
          }
       };
@@ -32913,10 +32967,10 @@
 
          inline T operator()(type v0, type v1)
          {
-            base_func::pre();
+            scoped_bft<func_2param> sb(*this);
             base_func::update(v0,v1);
             T result = this->value(base_func::expression);
-            base_func::post();
+
             return result;
          }
       };
@@ -32927,10 +32981,10 @@
 
          inline T operator()(type v0, type v1, type v2)
          {
-            base_func::pre();
+            scoped_bft<func_3param> sb(*this);
             base_func::update(v0,v1,v2);
             T result = this->value(base_func::expression);
-            base_func::post();
+
             return result;
          }
       };
@@ -32941,10 +32995,10 @@
 
          inline T operator()(type v0, type v1, type v2, type v3)
          {
-            base_func::pre();
+            scoped_bft<func_4param> sb(*this);
             base_func::update(v0,v1,v2,v3);
             T result = this->value(base_func::expression);
-            base_func::post();
+
             return result;
          }
       };
@@ -32955,10 +33009,10 @@
 
          inline T operator()(type v0, type v1, type v2, type v3, type v4)
          {
-            base_func::pre();
+            scoped_bft<func_5param> sb(*this);
             base_func::update(v0,v1,v2,v3,v4);
             T result = this->value(base_func::expression);
-            base_func::post();
+
             return result;
          }
       };
@@ -32969,10 +33023,10 @@
 
          inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
          {
-            base_func::pre();
+            scoped_bft<func_6param> sb(*this);
             base_func::update(v0,v1,v2,v3,v4,v5);
             T result = this->value(base_func::expression);
-            base_func::post();
+
             return result;
          }
       };
@@ -33040,6 +33094,7 @@
          if (compile_expression(name,expression,var_list))
          {
             fp_map_[n][name]->setup(expr_map_[name]);
+
             return true;
          }
          else
diff --git a/readme.txt b/readme.txt
index 224da97..24f542b 100644
--- a/readme.txt
+++ b/readme.txt
@@ -94,6 +94,7 @@
 
   (a) Download:   http://www.partow.net/programming/exprtk/index.html
   (b) Repository: https://github.com/ArashPartow/exprtk
+                  https://github.com/ArashPartow/exprtk-extras
 
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -240,7 +241,7 @@
 | ceil     | Smallest integer that is greater than or equal to x.    |
 +----------+---------------------------------------------------------+
 | clamp    | Clamp x in range between r0 and r1, where r0 < r1.      |
-|          | (eg: clamp(r0,x,r1)                                     |
+|          | (eg: clamp(r0,x,r1))                                    |
 +----------+---------------------------------------------------------+
 | equal    | Equality test between x and y using normalized epsilon  |
 +----------+---------------------------------------------------------+
@@ -762,12 +763,12 @@
  Variable(z)            [Multiplication]
                 ____________/      \___________
                /                               \
-              /                          [Unary-Func(sin)]
+              /                      [Unary-Function(sin)]
          [Addition]                            |
       ____/      \____                    [Division]
      /                \                 ___/      \___
  Variable(x)   [Exponentiation]        /              \
-              ______/   \______  Constant(pi)  [Binary-Func(min)]
+              ______/   \______  Constant(pi) [Binary-Function(min)]
              /                 \                ____/    \____
         Variable(y)        [Negation]          /              \
                                |              /           Variable(v)
@@ -801,6 +802,118 @@
 and  its  location  within  the  input  provided  by  the  'get_error'
 interface.
 
+
+Note: The exprtk::expression  and exprtk::symbol_table components  are
+reference counted entities. Copy constructing or assigning to or  from
+either component will result in  a shallow copy and a  reference count
+increment,  rather  than  a  complete  replication.  Furthermore   the
+expression  and symbol_table  components being  Default-Constructible,
+Copy-Constructible  and  Copy-Assignable  make  them  compatible  with
+various  C++  standard  library   containers  and  adaptors  such   as
+std::vector, std::map, std::stack etc.
+
+The following is  an example of  two unique expressions,  after having
+being instantiated and  compiled, one expression  is  assigned to  the
+other. The diagrams depict  their initial and post  assignment states,
+including  which  control  block each  expression references and their
+associated reference counts.
+
+
+  exprtk::expression e0; // constructed expression, eg: x + 1
+  exprtk::expression e1; // constructed expression, eg: 2z + y
+
+  +-----[ e0 cntrl block]----+     +-----[ e1 cntrl block]-----+
+  | 1. Expression Node 'x+1' |     | 1. Expression Node '2z+y' |
+  | 2. Ref Count: 1          |<-+  | 2. Ref Count: 1           |<-+
+  +--------------------------+  |  +---------------------------+  |
+                                |                                 |
+    +--[ e0 expression]--+      |    +--[ e1 expression]--+       |
+    | 1. Reference to    ]------+    | 1. Reference to    ]-------+
+    | e0 Control Block   |           | e1 Control Block   |
+    +--------------------+           +--------------------+
+
+
+  e0 = e1; // e0 and e1 are now 2z+y
+
+               +-----[ e1 cntrl block]-----+
+               | 1. Expression Node '2z+y' |
+  +----------->| 2. Ref Count: 2           |<----------+
+  |            +---------------------------+           |
+  |                                                    |
+  |   +--[ e0 expression]--+  +--[ e1 expression]--+   |
+  +---[ 1. Reference to    |  | 1. Reference to    ]---+
+      | e1 Control Block   |  | e1 Control Block   |
+      +--------------------+  +--------------------+
+
+The reason for  the above complexity  and restrictions of  deep copies
+for the expression and symbol_table components is because  expressions
+may include user defined variables or functions. These are embedded as
+references into the expression's AST. When copying an expression, said
+references  need to  also  be  copied. if  the references  are blindly
+copied,  then it  will  result  in two  or more  identical expressions
+utilizing the exact same  references for variables. This  obviously is
+not the  default assumed  scenario and  will give  rise to non-obvious
+behaviours  when  using the  expressions in  various contexts such  as
+muli-threading et al.
+
+The prescribed method for cloning an expression is to compile it  from
+its string form. Doing so will allow the one to properly consider  the
+exact source of user defined variables and functions.
+
+Note:  The  exprtk::parser  is  a  non-copyable  and  non-thread  safe
+component, and should only be shared via either a reference, a  shared
+pointer  or  a  std::ref  mechanism,  and  considerations  relating to
+synchronisation  taken  into  account  where  appropriate.  The parser
+represents an object factory,  specifically a factory of  expressions,
+and generally should  not be instantiated  solely on a  per expression
+compilation basis.
+
+The  following  diagram  and  example depicts  the  flow  of  data and
+operations  for  compiling  multiple expressions  via  the  parser and
+inserting  the  newly  minted  exprtk::expression  instances  into   a
+std::vector.
+
+
+                        +--[exprtk::parser]--+
+                        | expression factory |
+                     +---->- compile(....) ->---+
+                     |  +--------------------+  |
+  Expressions        |                          |   Expressions as
+  in string form     A                          V   exprtk::expression
+                     |                          |   instances
+  [s0:'x+1'     ]-+  |                          |   +-[e0: x+1]
+                  |  |                          |   |
+  [s1:'2z+y']-----+--+                          +-->+-[e1: 2z+y]
+                  |                                 |
+  [s2:'sin(k+w)']-+                                 +-[e2: sin(k+w)]
+
+
+   const std::string expression_str[3]
+                       = { "x + 1", "2x + y", "sin(k + w)" };
+
+   std::vector<expression_t> expression_list;
+
+   parser_t             parser;
+   expression_t     expression;
+   symbol_table_t symbol_table;
+
+   expression.register_symbol_table(symbol_table);
+
+   for (std::size_t i = 0; i < 3; ++i)
+   {
+      if (parser.compile(expression_str[i],expression))
+      {
+         expression_list.push_back(expression);
+      }
+      else
+        std::cout << "Error in " << expression_str[i] << "\n";
+   }
+
+   for (auto e : expression_list)
+   {
+      e.value();
+   }
+
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 [11 - COMPILATION OPTIONS]
@@ -1060,9 +1173,9 @@
 
 
 (3) String Definition
-Strings are a sequence of  8-bit characters. They can only  be defined
-with an explicit initialisation  value. The following are  examples of
-string variable definitions:
+Strings are sequences comprised of 8-bit characters. They can only be
+defined  with an explicit  initialisation  value. The  following  are
+examples of string variable definitions:
 
    (a) Initialise to a string
        var x := 'abc';
@@ -1096,6 +1209,9 @@
 will be returned. Where as for vectors, the value of the first element
 (eg: v[0]) will be returned.
 
+   8 == ((var x := 7;) + 1)
+   4 == (var y[3] := {4, 5, 6};)
+
 
 (5) Variable/Vector Assignment
 The value of a variable can be assigned to a vector and a vector or  a
@@ -1700,7 +1816,7 @@
    {
       foo() : exprtk::ifunction<T>(3)
       {
-          exprtk::disable_has_side_effects(*this);
+         exprtk::disable_has_side_effects(*this);
       }
 
       T operator()(const T& v1, const T& v2, const T& v3)