From 4ba2236c4a352c81705e2b56a32d5c77bd310116 Mon Sep 17 00:00:00 2001
From: Arash Partow <partow@gmail.com>
Date: Sun, 22 Oct 2017 20:42:11 +1100
Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) 
 http://www.partow.net/programming/exprtk/index.html

---
 exprtk.hpp                   |  33 +++++---
 exprtk_simple_example_02.cpp |  10 +--
 exprtk_simple_example_03.cpp |   6 +-
 exprtk_test.cpp              |   6 +-
 readme.txt                   | 146 ++++++++++++++++++++++++-----------
 5 files changed, 138 insertions(+), 63 deletions(-)

diff --git a/exprtk.hpp b/exprtk.hpp
index b819573..916e74b 100644
--- a/exprtk.hpp
+++ b/exprtk.hpp
@@ -3577,7 +3577,6 @@ namespace exprtk
                add_invalid(lexer::token::e_string ,lexer::token::e_string );
                add_invalid(lexer::token::e_number ,lexer::token::e_string );
                add_invalid(lexer::token::e_string ,lexer::token::e_number );
-               add_invalid(lexer::token::e_string ,lexer::token::e_ternary);
                add_invalid_set1(lexer::token::e_assign );
                add_invalid_set1(lexer::token::e_shr    );
                add_invalid_set1(lexer::token::e_shl    );
@@ -4204,6 +4203,11 @@ namespace exprtk
            data_(reinterpret_cast<value_t*>(ts_.data))
          {}
 
+         type_view(const type_store_t& ts)
+         : ts_(const_cast<type_store_t&>(ts)),
+           data_(reinterpret_cast<value_t*>(ts_.data))
+         {}
+
          inline std::size_t size() const
          {
             return ts_.size;
@@ -15975,6 +15979,7 @@ 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);
@@ -15993,6 +15998,16 @@ namespace exprtk
 
    protected:
 
+       struct freefunc00 : public exprtk::ifunction<T>
+       {
+          using exprtk::ifunction<T>::operator();
+
+          freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
+          inline T operator() ()
+          { return f(); }
+          ff00_functor f;
+       };
+
       struct freefunc01 : public exprtk::ifunction<T>
       {
          using exprtk::ifunction<T>::operator();
@@ -17034,14 +17049,14 @@ namespace exprtk
          return add_function(function_name,(*local_data().free_function_list_.back()));     \
       }                                                                                     \
 
-      exprtk_define_freefunction(01) exprtk_define_freefunction(02)
-      exprtk_define_freefunction(03) exprtk_define_freefunction(04)
-      exprtk_define_freefunction(05) exprtk_define_freefunction(06)
-      exprtk_define_freefunction(07) exprtk_define_freefunction(08)
-      exprtk_define_freefunction(09) exprtk_define_freefunction(10)
-      exprtk_define_freefunction(11) exprtk_define_freefunction(12)
-      exprtk_define_freefunction(13) exprtk_define_freefunction(14)
-      exprtk_define_freefunction(15)
+      exprtk_define_freefunction(00) exprtk_define_freefunction(01)
+      exprtk_define_freefunction(02) exprtk_define_freefunction(03)
+      exprtk_define_freefunction(04) exprtk_define_freefunction(05)
+      exprtk_define_freefunction(06) exprtk_define_freefunction(07)
+      exprtk_define_freefunction(08) exprtk_define_freefunction(09)
+      exprtk_define_freefunction(10) exprtk_define_freefunction(11)
+      exprtk_define_freefunction(12) exprtk_define_freefunction(13)
+      exprtk_define_freefunction(14) exprtk_define_freefunction(15)
 
       #undef exprtk_define_freefunction
 
diff --git a/exprtk_simple_example_02.cpp b/exprtk_simple_example_02.cpp
index cb18b35..71b2069 100644
--- a/exprtk_simple_example_02.cpp
+++ b/exprtk_simple_example_02.cpp
@@ -39,14 +39,14 @@ void square_wave()
 
    static const T pi = T(3.141592653589793238462643383279502);
 
-   T f = pi / T(10);
-   T t = T(0);
-   T a = T(10);
+   const T f = pi / T(10);
+   const T a = T(10);
+         T t = T(0);
 
    symbol_table_t symbol_table;
-   symbol_table.add_variable("f",f);
    symbol_table.add_variable("t",t);
-   symbol_table.add_variable("a",a);
+   symbol_table.add_constant("f",f);
+   symbol_table.add_constant("a",a);
    symbol_table.add_constants();
 
    expression_t expression;
diff --git a/exprtk_simple_example_03.cpp b/exprtk_simple_example_03.cpp
index 16b627f..924e404 100644
--- a/exprtk_simple_example_03.cpp
+++ b/exprtk_simple_example_03.cpp
@@ -30,9 +30,9 @@ void polynomial()
 
    std::string expression_string = "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1";
 
-   T r0 = T(0);
-   T r1 = T(1);
-   T  x = T(0);
+   const T r0 = T(0);
+   const T r1 = T(1);
+         T  x = T(0);
 
    symbol_table_t symbol_table;
    symbol_table.add_variable("x",x);
diff --git a/exprtk_test.cpp b/exprtk_test.cpp
index 4fcdbe4..9867f33 100644
--- a/exprtk_test.cpp
+++ b/exprtk_test.cpp
@@ -4848,7 +4848,7 @@ inline std::size_t load_expressions(const std::string& file_name,
 
    std::size_t line_count = 0;
 
-   while (std::getline(stream,buffer))
+   while (std::getline(stream,(buffer)))
    {
       if (buffer.empty())
          continue;
@@ -7685,7 +7685,7 @@ struct my_usr_ext : public exprtk::parser<T>::unknown_symbol_resolver
       {
          static T var_default_value = 1.0;
 
-         if (!(result = symbol_table.create_variable(unknown_symbol, var_default_value++)))
+         if ((result = symbol_table.create_variable(unknown_symbol, var_default_value++)) == false)
          {
             error_message = "Failed to create variable(" + unknown_symbol + ") in primary symbol table";
          }
@@ -7694,7 +7694,7 @@ struct my_usr_ext : public exprtk::parser<T>::unknown_symbol_resolver
       {
          static T cvar_default_value = 1.0;
 
-         if (!(result = symbol_table.add_constant(unknown_symbol, cvar_default_value++)))
+         if ((result = symbol_table.add_constant(unknown_symbol, cvar_default_value++)) == false)
          {
             error_message = "Failed to create const variable(" + unknown_symbol + ") in primary symbol table";
          }
diff --git a/readme.txt b/readme.txt
index 485791b..99dd3b7 100644
--- a/readme.txt
+++ b/readme.txt
@@ -224,7 +224,7 @@ of C++ compilers:
 +----------+---------------------------------------------------------+
 | true     | True state or any value other than zero (typically 1).  |
 +----------+---------------------------------------------------------+
-| false    | False state, value of zero.                             |
+| false    | False state, value of exactly zero.                     |
 +----------+---------------------------------------------------------+
 | and      | Logical AND, True only if x and y are both true.        |
 |          | (eg: x and y)                                           |
@@ -275,7 +275,7 @@ of C++ compilers:
 | clamp    | Clamp x in range between r0 and r1, where r0 < r1.      |
 |          | (eg: clamp(r0,x,r1))                                    |
 +----------+---------------------------------------------------------+
-| equal    | Equality test between x and y using normalized epsilon  |
+| equal    | Equality test between x and y using normalised epsilon  |
 +----------+---------------------------------------------------------+
 | erf      | Error function of x.  (eg: erf(x))                      |
 +----------+---------------------------------------------------------+
@@ -321,7 +321,7 @@ of C++ compilers:
 +----------+---------------------------------------------------------+
 | ncdf     | Normal cumulative distribution function.  (eg: ncdf(x)) |
 +----------+---------------------------------------------------------+
-| nequal   | Not-equal test between x and y using normalized epsilon |
+| nequal   | Not-equal test between x and y using normalised epsilon |
 +----------+---------------------------------------------------------+
 | pow      | x to the power of y.  (eg: pow(x,y) == x ^ y)           |
 +----------+---------------------------------------------------------+
@@ -499,7 +499,7 @@ of C++ compilers:
 |          | eg:                                                     |
 |          | 1. if (x > y) z; else w;                                |
 |          | 2. if (x > y) z; else if (w != u) v;                    |
-|          | 3. if (x < y) {z; w + 1;} else u;                       |
+|          | 3. if (x < y) { z; w + 1; } else u;                     |
 |          | 4. if ((x != y) and (z > w))                            |
 |          |    {                                                    |
 |          |      y := sin(x) / u;                                   |
@@ -651,7 +651,7 @@ expressions. The types are as follows:
 
 (1) Scalar Type
 The scalar type  is a singular  numeric value. The  underlying type is
-that used  to specialize  the ExprTk  components (float,  double, long
+that used  to specialise  the ExprTk  components (float,  double, long
 double, MPFR et al).
 
 
@@ -673,7 +673,7 @@ however can not interact with scalar or vector types.
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 [SECTION 10 - COMPONENTS]
-There are three primary components, that are specialized upon a  given
+There are three primary components, that are specialised upon a  given
 numeric type, which make up the core of ExprTk. The components are  as
 follows:
 
@@ -791,8 +791,9 @@ methods:
    4. bool add_vector   (const std::string& name,    vector_type&)
 
 
-The 'vector' type must consist of a contiguous array of scalars  which
-can be one of the following:
+Note: The 'vector' type must  be comprised from a contiguous  array of
+scalars with a size that is  larger than zero. The vector type  itself
+can be any one of the following:
 
    1. std::vector<scalar_t>
    2. scalar_t(&v)[N]
@@ -800,6 +801,18 @@ can be one of the following:
    4. exprtk::vector_view<scalar_t>
 
 
+When  registering  a variable,  vector,  string or  function  with  an
+instance of a symbol_table, the call to 'add_...' may fail and  return
+a false result due to one or more of the following reasons:
+
+  1. Variable name contains invalid characters or is ill-formed
+  2. Variable name conflicts with a reserved word (eg: 'while')
+  3. Variable name conflicts with a previously registered variable
+  4. A vector of size (length) zero is being registered
+  5. A free function exceeding fifteen parameters is being registered
+  6. The symbol_table instance is in an invalid state
+
+
 (2) Expression
 A structure that holds an abstract syntax tree or AST for a  specified
 expression and is used to evaluate said expression. Evaluation of  the
@@ -920,8 +933,8 @@ 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
+   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' |
@@ -934,7 +947,7 @@ associated reference counts.
     +--------------------+           +--------------------+
 
 
-  e0 = e1; // e0 and e1 are now 2z+y
+   e0 = e1; // e0 and e1 are now 2z+y
 
                +-----[ e1 cntrl block]-----+
                | 1. Expression Node '2z+y' |
@@ -1226,7 +1239,7 @@ In the following example, the  return value of the expression  will be
 within the loop body on its last iteration:
 
    var x := 1;
-   x + for (var i := i; i < 10; i += 1)
+   x + for (var i := x; i < 10; i += 1)
        {
          i / 2;
          i + 1;
@@ -1303,7 +1316,7 @@ lets review the following expression:
 
    var x := 2;      // Statement 1
    var y := x + 2;  // Statement 2
-   x + y            // Statement 3
+   x + y;           // Statement 3
    y := x + 3y;     // Statement 4
    x - y;           // Statement 5
 
@@ -1332,7 +1345,7 @@ ExprTk support two forms  of conditional branching or  otherwise known
 as  if-statements.  The  first  form,  is  a  simple  function   based
 conditional  statement, that  takes exactly  three input  expressions:
 condition, consequent  and alternative.  The following  is an  example
-expression that utilizes the function based if-statement.
+expression that utilises the function based if-statement.
 
    x := if (y < z, y + 1, 2* z)
 
@@ -1451,7 +1464,7 @@ Special functions dramatically decrease  the total evaluation time  of
 expressions which would otherwise  have been written using  the common
 form by reducing the total number  of nodes in the evaluation tree  of
 an  expression  and  by  also  leveraging  the  compiler's  ability to
-correctly optimize such expressions for a given architecture.
+correctly optimise such expressions for a given architecture.
 
           3-Parameter                       4-Parameter
  +-------------+-------------+    +--------------+------------------+
@@ -1581,25 +1594,28 @@ examples of string variable definitions:
    (a) Initialise to a string
        var x := 'abc';
 
-   (b) Initialise to a string expression
+   (b) Initialise to an empty string
+       var x := '';
+
+   (c) Initialise to a string expression
        var x := 'abc' + '123';
 
-   (c) Initialise to a string range
+   (d) Initialise to a string range
        var x := 'abc123'[2:4];
 
-   (d) Initialise to another string variable
+   (e) Initialise to another string variable
        var x := 'abc';
        var y := x;
 
-   (e) Initialise to another string variable range
+   (f) Initialise to another string variable range
        var x := 'abc123';
        var y := x[2:4];
 
-   (f) Initialise to a string expression
+   (g) Initialise to a string expression
        var x := 'abc';
        var y := x + '123';
 
-   (g) Initialise to a string expression range
+   (h) Initialise to a string expression range
        var x := 'abc';
        var y := (x + '123')[1:3];
 
@@ -1775,7 +1791,7 @@ needs  to  be  'updated' to  either another  vector or  sub-range, the
 vector_view instance  can be  efficiently rebased,  and the expression
 evaluated as normal.
 
-   exprtk::vector_view<T> view = exprtk::make_vector_view(v, v.size());
+   exprtk::vector_view<T> view = exprtk::make_vector_view(v,v.size());
 
    symbol_table_t symbol_table;
    symbol_table.add_vector("v",view);
@@ -1794,7 +1810,7 @@ evaluated as normal.
 
 [SECTION 15 - USER DEFINED FUNCTIONS]
 ExprTk provides a means  whereby custom functions can  be defined  and
-utilized within  expressions.  The   concept  requires  the  user   to
+utilised within  expressions.  The   concept  requires  the  user   to
 provide a reference  to the function  coupled with an  associated name
 that  will be invoked within  expressions. Functions may take numerous
 inputs but will always return a single value of the underlying numeric
@@ -1840,7 +1856,7 @@ function called 'foo':
 (2) ivararg_function
 This interface supports a variable number of scalar arguments as input
 into the function. The function operator interface uses a  std::vector
-specialized upon type T to facilitate parameter passing. The following
+specialised upon type T to facilitate parameter passing. The following
 example defines a vararg function called 'boo':
 
    template <typename T>
@@ -1863,7 +1879,7 @@ example defines a vararg function called 'boo':
 (3) igeneric_function
 This interface supports  a variable number  of arguments and  types as
 input  into  the  function. The  function  operator  interface uses  a
-std::vector  specialized  upon  the  type_store  type  to   facilitate
+std::vector  specialised  upon  the  type_store  type  to   facilitate
 parameter passing.
 
     Scalar <-- function(i_0, i_1, i_2....., i_N)
@@ -2335,6 +2351,42 @@ Note: For  the igeneric_function  type, there  also needs  to be a 'Z'
 parameter sequence  defined in order for the  zero parameter  trait to
 properly take effect otherwise a compilation error will occur.
 
+
+(9) Free Functions
+The ExprTk symbol  table supports the  registration of free  functions
+and lambdas  (anonymous functors)  for use  in expressions.  The basic
+requirements  are similar  to those  found in  ifunction derived  user
+defined  functions. This  includes  support  for free  functions using
+anywhere from zero up to fifteen input parameters of scalar type, with
+a return type that is also scalar. Furthermore such functions will  by
+default be assumed to have side-effects and hence will not participate
+in constant folding optimisations.
+
+In the following  example, a two  input parameter free  function named
+'compute', and a three input parameter lambda will be registered  with
+the given symbol_table instance:
+
+
+   double compute(double v0, double v1)
+   {
+      return 2.0 * v0 + v1 / 3.0;
+   }
+
+   .
+   .
+   .
+
+   typedef exprtk::symbol_table<double> symbol_table_t;
+
+   symbol_table_t symbol_table;
+
+   symbol_table.add_function("compute", compute);
+
+   symbol_table.add_function("lambda",
+                             [](double v0, double v1, double v2) -> double
+                             { return v0 / v1 + v2; });
+
+
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 [SECTION 16 - EXPRESSION DEPENDENTS]
@@ -2443,7 +2495,7 @@ associated assignments:
    (5) None          x + y + z
 
 
-Note: In expression 4, both variables 'z' and 'w' are denoted as being
+Note: In expression 4, both variables 'w' and 'z' are denoted as being
 assignments even though only one of  them can ever be modified at  the
 time of evaluation. Furthermore the determination of which of the  two
 variables the  modification will  occur upon  can only  be known  with
@@ -2489,7 +2541,7 @@ associated with a given expression instance.
 
 However as an expression can have more than one symbol table  instance
 associated  with  itself,  when  building  more  complex  systems that
-utilize many expressions  where each can  in turn utilize  one or more
+utilise many expressions  where each can  in turn utilise  one or more
 variables  from  a  large set  of  potential  variables, functions  or
 constants, it becomes evident  that grouping variables into  layers of
 symbol_tables will simplify and streamline the overall process.
@@ -2722,7 +2774,7 @@ expressions:
 In  this  scenario   one  can  use   the  'dependent_entity_collector'
 component as described in [Section  16] to further determine which  of
 the registered variables were  actually used in the  given expression.
-As  an example  once the  set of  utilized  variables  are known,  any
+As  an example  once the  set of  utilised  variables  are known,  any
 further 'attention'  can be  restricted to  only those  variables when
 evaluating the expression. This can be quite useful when dealing  with
 expressions that can draw from a set of hundreds or even thousands  of
@@ -3427,8 +3479,8 @@ values.
 
    expression.value();
 
-   printf("Result0: %15.5f\n",result0        );
-   printf("Result1: %s\n"    ,result1.c_str());
+   printf("Result0: %15.5f\n", result0        );
+   printf("Result1: %s\n"    , result1.c_str());
 
 
 In the example above, the expression will compute two results. As such
@@ -3436,7 +3488,7 @@ two result variables are defined to hold the values named result0  and
 result1 respectively. The first is of scalar type (double), the second
 is of  string type.  Once the  expression has  been evaluated, the two
 variables will have been updated  with the new result values,  and can
-then be further utilized from within the calling program.
+then be further utilised from within the calling program.
 
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -3753,12 +3805,12 @@ overloads, the definitions of which are:
 
    (1) No variables
    (2) One variable called x
-   (3) Two variable called x and y
-   (3) Three variable called x, y and z
+   (3) Two variables called x and y
+   (3) Three variables called x, y and z
 
 
-An example use of each of the three overloads for the compute  routine
-is as follows:
+Example uses of  each of the  three overloads for  the compute routine
+are as follows:
 
    T result = T(0);
 
@@ -3803,11 +3855,11 @@ is as follows:
 
 (d) integrate
 This free function will attempt to perform a numerical integration  of
-a single variable compiled expression  over a defined range and  given
-step size. The numerical integration is based on the three point  form
-of the Simpson's rule. The integrate function has two overloads, where
-the variable of integration can either be passed as a reference or  as
-a name in string form. Example usage of the function is as follows:
+a single variable compiled expression over a specified range and  step
+size. The numerical  integration is based  on the three  point form of
+Simpson's rule. The  integrate function has  two overloads, where  the
+variable of integration can  either be passed as  a reference or as  a
+name in string form. Example usage of the function is as follows:
 
    typedef exprtk::parser<T>             parser_t;
    typedef exprtk::expression<T>     expression_t;
@@ -4047,7 +4099,7 @@ expressions. As an example, lets take the following expression:
    1 / sqrt(2x) * e^(3y)
 
 
-Let's say we would like to determine which sub-part of the  expression
+Lets say we would like to determine which sub-part  of the  expression
 takes the  most time  to evaluate  and perhaps  attempt to  rework the
 expression based on the results. In order to do this we will create  a
 text file  called 'test.txt'  and then  proceed to  make some educated
@@ -4133,7 +4185,7 @@ into account when using ExprTk:
 
  (09) The  life-time of  objects registered  with or  created from  a
       specific symbol-table must span  at least the life-time  of the
-      compiled expressions which utilize objects, such as  variables,
+      compiled expressions which utilise objects, such as  variables,
       of that  symbol-table, otherwise  the result  will be undefined
       behavior.
 
@@ -4289,7 +4341,15 @@ into account when using ExprTk:
       performance  critical  code  paths, and  should  instead  occur
       entirely either before or after such code paths.
 
- (32) Before jumping in and using ExprTk, do take the time to  peruse
+ (32) Deep  copying  an  expression  instance  for  the  purposes  of
+      persisting to disk or otherwise transmitting elsewhere with the
+      intent to 'resurrect' the  expression instance later on  is not
+      possible due  to the  reasons described  in the  final note  of
+      Section 10. The recommendation is to instead simply persist the
+      string form  of the  expression and  compile the  expression at
+      run-time on the target.
+
+ (33) Before jumping in and using ExprTk, do take the time to  peruse
       the documentation and all of the examples, both in the main and
       the extras  distributions. Having  an informed  general view of
       what can and  can't be done,  and how something  should be done