0000 | C++ Mathematical Expression Toolkit Library Documentation 
 0001 |  
 0002 |   Section 00 - Introduction 
 0003 |   Section 01 - Capabilities 
 0004 |   Section 02 - Example Expressions 
 0005 |   Section 03 - Copyright Notice 
 0006 |   Section 04 - Downloads & Updates 
 0007 |   Section 05 - Installation 
 0008 |   Section 06 - Compilation 
 0009 |   Section 07 - Compiler Compatibility 
 0010 |   Section 08 - Built-In Operations & Functions 
 0011 |   Section 09 - Fundamental Types 
 0012 |   Section 10 - Components 
 0013 |   Section 11 - Compilation Options 
 0014 |   Section 12 - Expression Structures 
 0015 |   Section 13 - Variable, Vector & String Definition 
 0016 |   Section 14 - Vector Processing 
 0017 |   Section 15 - User Defined Functions 
 0018 |   Section 16 - Expression Dependents 
 0019 |   Section 17 - Hierarchies Of Symbol Tables 
 0020 |   Section 18 - Unknown Unknowns 
 0021 |   Section 19 - Enabling & Disabling Features 
 0022 |   Section 20 - Expression Return Values 
 0023 |   Section 21 - Compilation Errors 
 0024 |   Section 22 - Runtime Library Packages 
 0025 |   Section 23 - Helpers & Utils 
 0026 |   Section 24 - Runtime Checks 
 0027 |   Section 25 - Benchmarking 
 0028 |   Section 26 - Exprtk Notes 
 0029 |   Section 27 - Simple Exprtk Example 
 0030 |   Section 28 - Build Options 
 0031 |   Section 29 - Files 
 0032 |   Section 30 - Language Structure 
 0033 |  
 0034 |  
 0035 | [SECTION 00 - INTRODUCTION] 
 0036 | The C++ Mathematical Expression  Toolkit Library (ExprTk) is  a simple 
 0037 | to  use,   easy  to   integrate  and   extremely  efficient   run-time 
 0038 | mathematical  expression parsing  and evaluation  engine. The  parsing 
 0039 | engine  supports numerous  forms  of  functional and  logic processing 
 0040 | semantics and is easily extensible. 
 0041 |  
 0042 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0043 |  
 0044 | [SECTION 01 - CAPABILITIES] 
 0045 | The  ExprTk expression  evaluator supports  the following  fundamental 
 0046 | arithmetic operations, functions and processes: 
 0047 |  
 0048 |  (00) Types:           Scalar, Vector, String 
 0049 |  
 0050 |  (01) Basic operators: +, -, *, /, %, ^ 
 0051 |  
 0052 |  (02) Assignment:      :=, +=, -=, *=, /=, %= 
 0053 |  
 0054 |  (03) Equalities & 
 0055 |       Inequalities:    =, ==, <>, !=, <, <=, >, >= 
 0056 |  
 0057 |  (04) Logic operators: and, mand, mor, nand, nor, not, or, shl, shr, 
 0058 |                        xnor, xor, true, false 
 0059 |  
 0060 |  (05) Functions:       abs, avg, ceil, clamp, equal, erf, erfc,  exp, 
 0061 |                        expm1, floor, frac,  log, log10, log1p,  log2, 
 0062 |                        logn, max,  min, mul,  ncdf,  not_equal, root, 
 0063 |                        round, roundn, sgn, sqrt, sum, swap, trunc 
 0064 |  
 0065 |  (06) Trigonometry:    acos, acosh, asin, asinh, atan, atanh,  atan2, 
 0066 |                        cos,  cosh, cot,  csc, sec,  sin, sinc,  sinh, 
 0067 |                        tan, tanh, hypot, rad2deg, deg2grad,  deg2rad, 
 0068 |                        grad2deg 
 0069 |  
 0070 |  (07) Control 
 0071 |       structures:      if-then-else, ternary conditional, switch-case, 
 0072 |                        return-statement 
 0073 |  
 0074 |  (08) Loop statements: while, for, repeat-until, break, continue 
 0075 |  
 0076 |  (09) String 
 0077 |       processing:      in, like, ilike, concatenation 
 0078 |  
 0079 |  (10) Optimisations:   constant-folding, simple strength reduction and 
 0080 |                        dead code elimination 
 0081 |  
 0082 |  (11) Runtime checks:  vector bounds, string bounds, loop iteration, 
 0083 |                        execution-time bounds and compilation process 
 0084 |                        checkpointing, assert statements 
 0085 |  
 0086 |  (12) Calculus:        numerical integration and differentiation 
 0087 |  
 0088 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0089 |  
 0090 | [SECTION 02 - EXAMPLE EXPRESSIONS] 
 0091 | The following is  a short listing  of infix format  based mathematical 
 0092 | expressions that can be parsed and evaluated using the ExprTk library. 
 0093 |  
 0094 |   (01) sqrt(1 - (3 / x^2)) 
 0095 |   (02) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1) 
 0096 |   (03) sin(2.34e-3 * x) 
 0097 |   (04) if(((x[2] + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) 
 0098 |   (05) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) 
 0099 |   (06) ({1/1}*[1/2]+(1/3))-{1/4}^[1/5]+(1/6)-({1/7}+[1/8]*(1/9)) 
 0100 |   (07) a * exp(2.2 / 3.3 * t) + c 
 0101 |   (08) z := x + sin(2.567 * pi / y) 
 0102 |   (09) u := 2.123 * {pi * z} / (w := x + cos(y / pi)) 
 0103 |   (10) 2x + 3y + 4z + 5w == 2 * x + 3 * y + 4 * z + 5 * w 
 0104 |   (11) 3(x + y) / 2.9 + 1.234e+12 == 3 * (x + y) / 2.9 + 1.234e+12 
 0105 |   (12) (x + y)3.3 + 1 / 4.5 == [x + y] * 3.3 + 1 / 4.5 
 0106 |   (13) (x + y[i])z + 1.1 / 2.7 == (x + y[i]) * z + 1.1 / 2.7 
 0107 |   (14) (sin(x / pi) cos(2y) + 1) == (sin(x / pi) * cos(2 * y) + 1) 
 0108 |   (15) 75x^17 + 25.1x^5 - 35x^4 - 15.2x^3 + 40x^2 - 15.3x + 1 
 0109 |   (16) (avg(x,y) <= x + y ? x - y : x * y) + 2.345 * pi / x 
 0110 |   (17) while (x <= 100) { x -= 1; } 
 0111 |   (18) x <= 'abc123' and (y in 'AString') or ('1x2y3z' != z) 
 0112 |   (19) ((x + 'abc') like '*123*') or ('a123b' ilike y) 
 0113 |   (20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x } 
 0114 |  
 0115 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0116 |  
 0117 | [SECTION 03 - COPYRIGHT NOTICE] 
 0118 | Free  use  of  the  C++  Mathematical  Expression  Toolkit  Library is 
 0119 | permitted under the guidelines and in accordance with the most current 
 0120 | version of the MIT License. 
 0121 |  
 0122 |    (1) https://www.opensource.org/licenses/MIT 
 0123 |    (2) SPDX-License-Identifier: MIT 
 0124 |    (3) SPDX-FileCopyrightText : Copyright (C) 1999-2024 Arash Partow 
 0125 |  
 0126 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0127 |  
 0128 | [SECTION 04 - DOWNLOADS & UPDATES] 
 0129 | The most  recent version  of the C++ Mathematical  Expression  Toolkit 
 0130 | Library including all updates and tests can be found at the  following 
 0131 | locations: 
 0132 |  
 0133 |   (1) Download: https://www.partow.net/programming/exprtk/index.html 
 0134 |   (2) Mirror Repository: https://github.com/ArashPartow/exprtk 
 0135 |                          https://github.com/ArashPartow/exprtk-extras 
 0136 |  
 0137 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0138 |  
 0139 | [SECTION 05 - INSTALLATION] 
 0140 | The header  file exprtk.hpp  should be  placed in a project or  system 
 0141 | include path (e.g: /usr/include/). 
 0142 |  
 0143 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0144 |  
 0145 | [SECTION 06 - COMPILATION] 
 0146 | The  ExprTk  package  contains  the ExprTk  header,  a  set  of simple 
 0147 | examples and a benchmark and unit test  suite. The following is a list 
 0148 | of commands to build the various components: 
 0149 |  
 0150 |   (a) For a complete build: make clean all 
 0151 |   (b) For a PGO build: make clean pgo 
 0152 |   (c) To strip executables: make strip_bin 
 0153 |   (d) Execute valgrind check: make valgrind_check 
 0154 |  
 0155 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0156 |  
 0157 | [SECTION 07 - COMPILER COMPATIBILITY] 
 0158 | ExprTk has been built error and warning free using the following set 
 0159 | of C++ compilers: 
 0160 |  
 0161 |   (*) GNU Compiler Collection (3.5+) 
 0162 |   (*) Clang/LLVM (1.1+) 
 0163 |   (*) Microsoft Visual Studio C++ Compiler (7.1+) 
 0164 |   (*) Intel C++ Compiler (8.x+) 
 0165 |   (*) AMD Optimizing C++ Compiler (1.2+) 
 0166 |   (*) Nvidia C++ Compiler (19.x+) 
 0167 |   (*) PGI C++ (10.x+) 
 0168 |   (*) Circle C++ (circa: b81c37d2bb227c) 
 0169 |   (*) IBM XL C/C++ (9.x+) 
 0170 |   (*) C++ Builder (XE4+) 
 0171 |  
 0172 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0173 |  
 0174 | [SECTION 08 - BUILT-IN OPERATIONS & FUNCTIONS] 
 0175 |  
 0176 | (0) Arithmetic & Assignment Operators 
 0177 | +----------+---------------------------------------------------------+ 
 0178 | | OPERATOR | DEFINITION                                              | 
 0179 | +----------+---------------------------------------------------------+ 
 0180 | |  +       | Addition between x and y.  (eg: x + y)                  | 
 0181 | +----------+---------------------------------------------------------+ 
 0182 | |  -       | Subtraction between x and y.  (eg: x - y)               | 
 0183 | +----------+---------------------------------------------------------+ 
 0184 | |  *       | Multiplication between x and y.  (eg: x * y)            | 
 0185 | +----------+---------------------------------------------------------+ 
 0186 | |  /       | Division between x and y.  (eg: x / y)                  | 
 0187 | +----------+---------------------------------------------------------+ 
 0188 | |  %       | Modulus of x with respect to y.  (eg: x % y)            | 
 0189 | +----------+---------------------------------------------------------+ 
 0190 | |  ^       | x to the power of y.  (eg: x ^ y)                       | 
 0191 | +----------+---------------------------------------------------------+ 
 0192 | |  :=      | Assign the value of x to y. Where y is either a variable| 
 0193 | |          | or vector type.  (eg: y := x)                           | 
 0194 | +----------+---------------------------------------------------------+ 
 0195 | |  +=      | Increment x by the value of the expression on the right | 
 0196 | |          | hand side. Where x is either a variable or vector type. | 
 0197 | |          | (eg: x += abs(y - z))                                   | 
 0198 | +----------+---------------------------------------------------------+ 
 0199 | |  -=      | Decrement x by the value of the expression on the right | 
 0200 | |          | hand side. Where x is either a variable or vector type. | 
 0201 | |          | (eg: x[i] -= abs(y + z))                                | 
 0202 | +----------+---------------------------------------------------------+ 
 0203 | |  *=      | Assign the multiplication of x by the value of the      | 
 0204 | |          | expression on the righthand side to x. Where x is either| 
 0205 | |          | a variable or vector type.                              | 
 0206 | |          | (eg: x *= abs(y / z))                                   | 
 0207 | +----------+---------------------------------------------------------+ 
 0208 | |  /=      | Assign the division of x by the value of the expression | 
 0209 | |          | on the right-hand side to x. Where x is either a        | 
 0210 | |          | variable or vector type.  (eg: x[i + j] /= abs(y * z))  | 
 0211 | +----------+---------------------------------------------------------+ 
 0212 | |  %=      | Assign x modulo the value of the expression on the right| 
 0213 | |          | hand side to x. Where x is either a variable or vector  | 
 0214 | |          | type.  (eg: x[2] %= y ^ 2)                              | 
 0215 | +----------+---------------------------------------------------------+ 
 0216 |  
 0217 | (1) Equalities & Inequalities 
 0218 | +----------+---------------------------------------------------------+ 
 0219 | | OPERATOR | DEFINITION                                              | 
 0220 | +----------+---------------------------------------------------------+ 
 0221 | | == or =  | True only if x is strictly equal to y. (eg: x == y)     | 
 0222 | +----------+---------------------------------------------------------+ 
 0223 | | <> or != | True only if x does not equal y. (eg: x <> y or x != y) | 
 0224 | +----------+---------------------------------------------------------+ 
 0225 | |  <       | True only if x is less than y. (eg: x < y)              | 
 0226 | +----------+---------------------------------------------------------+ 
 0227 | |  <=      | True only if x is less than or equal to y. (eg: x <= y) | 
 0228 | +----------+---------------------------------------------------------+ 
 0229 | |  >       | True only if x is greater than y. (eg: x > y)           | 
 0230 | +----------+---------------------------------------------------------+ 
 0231 | |  >=      | True only if x greater than or equal to y. (eg: x >= y) | 
 0232 | +----------+---------------------------------------------------------+ 
 0233 |  
 0234 | (2) Boolean Operations 
 0235 | +----------+---------------------------------------------------------+ 
 0236 | | OPERATOR | DEFINITION                                              | 
 0237 | +----------+---------------------------------------------------------+ 
 0238 | | true     | True state or any value other than zero (typically 1).  | 
 0239 | +----------+---------------------------------------------------------+ 
 0240 | | false    | False state, value of exactly zero.                     | 
 0241 | +----------+---------------------------------------------------------+ 
 0242 | | and      | Logical AND, True only if x and y are both true.        | 
 0243 | |          | (eg: x and y)                                           | 
 0244 | +----------+---------------------------------------------------------+ 
 0245 | | mand     | Multi-input logical AND, True only if all inputs are    | 
 0246 | |          | true. Left to right short-circuiting of expressions.    | 
 0247 | |          | (eg: mand(x > y, z < w, u or v, w and x))               | 
 0248 | +----------+---------------------------------------------------------+ 
 0249 | | mor      | Multi-input logical OR, True if at least one of the     | 
 0250 | |          | inputs are true. Left to right short-circuiting of      | 
 0251 | |          | expressions.  (eg: mor(x > y, z < w, u or v, w and x))  | 
 0252 | +----------+---------------------------------------------------------+ 
 0253 | | nand     | Logical NAND, True only if either x or y is false.      | 
 0254 | |          | (eg: x nand y)                                          | 
 0255 | +----------+---------------------------------------------------------+ 
 0256 | | nor      | Logical NOR, True only if the result of x or y is false | 
 0257 | |          | (eg: x nor y)                                           | 
 0258 | +----------+---------------------------------------------------------+ 
 0259 | | not      | Logical NOT, Negate the logical sense of the input.     | 
 0260 | |          | (eg: not(x and y) == x nand y)                          | 
 0261 | +----------+---------------------------------------------------------+ 
 0262 | | or       | Logical OR, True if either x or y is true. (eg: x or y) | 
 0263 | +----------+---------------------------------------------------------+ 
 0264 | | xor      | Logical XOR, True only if the logical states of x and y | 
 0265 | |          | differ.  (eg: x xor y)                                  | 
 0266 | +----------+---------------------------------------------------------+ 
 0267 | | xnor     | Logical XNOR, True iff the biconditional of x and y is  | 
 0268 | |          | satisfied.  (eg: x xnor y)                              | 
 0269 | +----------+---------------------------------------------------------+ 
 0270 | | &        | Similar to AND but with left to right expression short  | 
 0271 | |          | circuiting optimisation.  (eg: (x & y) == (y and x))    | 
 0272 | +----------+---------------------------------------------------------+ 
 0273 | | |        | Similar to OR but with left to right expression short   | 
 0274 | |          | circuiting optimisation.  (eg: (x | y) == (y or x))     | 
 0275 | +----------+---------------------------------------------------------+ 
 0276 |  
 0277 | (3) General Purpose Functions 
 0278 | +----------+---------------------------------------------------------+ 
 0279 | | FUNCTION | DEFINITION                                              | 
 0280 | +----------+---------------------------------------------------------+ 
 0281 | | abs      | Absolute value of x.  (eg: abs(x))                      | 
 0282 | +----------+---------------------------------------------------------+ 
 0283 | | avg      | Average of all the inputs.                              | 
 0284 | |          | (eg: avg(x,y,z,w,u,v) == (x + y + z + w + u + v) / 6)   | 
 0285 | +----------+---------------------------------------------------------+ 
 0286 | | ceil     | Smallest integer that is greater than or equal to x.    | 
 0287 | +----------+---------------------------------------------------------+ 
 0288 | | clamp    | Clamp x in range between r0 and r1, where r0 < r1.      | 
 0289 | |          | (eg: clamp(r0,x,r1))                                    | 
 0290 | +----------+---------------------------------------------------------+ 
 0291 | | equal    | Equality test between x and y using normalised epsilon  | 
 0292 | +----------+---------------------------------------------------------+ 
 0293 | | erf      | Error function of x.  (eg: erf(x))                      | 
 0294 | +----------+---------------------------------------------------------+ 
 0295 | | erfc     | Complimentary error function of x.  (eg: erfc(x))       | 
 0296 | +----------+---------------------------------------------------------+ 
 0297 | | exp      | e to the power of x.  (eg: exp(x))                      | 
 0298 | +----------+---------------------------------------------------------+ 
 0299 | | expm1    | e to the power of x minus 1, where x is very small.     | 
 0300 | |          | (eg: expm1(x))                                          | 
 0301 | +----------+---------------------------------------------------------+ 
 0302 | | floor    | Largest integer that is less than or equal to x.        | 
 0303 | |          | (eg: floor(x))                                          | 
 0304 | +----------+---------------------------------------------------------+ 
 0305 | | frac     | Fractional portion of x.  (eg: frac(x))                 | 
 0306 | +----------+---------------------------------------------------------+ 
 0307 | | hypot    | Hypotenuse of x and y (eg: hypot(x,y) = sqrt(x*x + y*y))| 
 0308 | +----------+---------------------------------------------------------+ 
 0309 | | iclamp   | Inverse-clamp x outside of the range r0 and r1. Where   | 
 0310 | |          | r0 < r1. If x is within the range it will snap to the   | 
 0311 | |          | closest bound. (eg: iclamp(r0,x,r1)                     | 
 0312 | +----------+---------------------------------------------------------+ 
 0313 | | inrange  | In-range returns 'true' when x is within the range r0   | 
 0314 | |          | and r1. Where r0 < r1.  (eg: inrange(r0,x,r1)           | 
 0315 | +----------+---------------------------------------------------------+ 
 0316 | | log      | Natural logarithm of x.  (eg: log(x))                   | 
 0317 | +----------+---------------------------------------------------------+ 
 0318 | | log10    | Base 10 logarithm of x.  (eg: log10(x))                 | 
 0319 | +----------+---------------------------------------------------------+ 
 0320 | | log1p    | Natural logarithm of 1 + x, where x is very small.      | 
 0321 | |          | (eg: log1p(x))                                          | 
 0322 | +----------+---------------------------------------------------------+ 
 0323 | | log2     | Base 2 logarithm of x.  (eg: log2(x))                   | 
 0324 | +----------+---------------------------------------------------------+ 
 0325 | | logn     | Base N logarithm of x. where n is a positive integer.   | 
 0326 | |          | (eg: logn(x,8))                                         | 
 0327 | +----------+---------------------------------------------------------+ 
 0328 | | max      | Largest value of all the inputs. (eg: max(x,y,z,w,u,v)) | 
 0329 | +----------+---------------------------------------------------------+ 
 0330 | | min      | Smallest value of all the inputs. (eg: min(x,y,z,w,u))  | 
 0331 | +----------+---------------------------------------------------------+ 
 0332 | | mul      | Product of all the inputs.                              | 
 0333 | |          | (eg: mul(x,y,z,w,u,v,t) == (x * y * z * w * u * v * t)) | 
 0334 | +----------+---------------------------------------------------------+ 
 0335 | | ncdf     | Normal cumulative distribution function.  (eg: ncdf(x)) | 
 0336 | +----------+---------------------------------------------------------+ 
 0337 | | not_equal| Not-equal test between x and y using normalised epsilon | 
 0338 | +----------+---------------------------------------------------------+ 
 0339 | | pow      | x to the power of y.  (eg: pow(x,y) == x ^ y)           | 
 0340 | +----------+---------------------------------------------------------+ 
 0341 | | root     | Nth-Root of x. where n is a positive integer.           | 
 0342 | |          | (eg: root(x,3) == x^(1/3))                              | 
 0343 | +----------+---------------------------------------------------------+ 
 0344 | | round    | Round x to the nearest integer.  (eg: round(x))         | 
 0345 | +----------+---------------------------------------------------------+ 
 0346 | | roundn   | Round x to n decimal places  (eg: roundn(x,3))          | 
 0347 | |          | where n > 0 and is an integer.                          | 
 0348 | |          | (eg: roundn(1.2345678,4) == 1.2346)                     | 
 0349 | +----------+---------------------------------------------------------+ 
 0350 | | sgn      | Sign of x, -1 where x < 0, +1 where x > 0, else zero.   | 
 0351 | |          | (eg: sgn(x))                                            | 
 0352 | +----------+---------------------------------------------------------+ 
 0353 | | sqrt     | Square root of x, where x >= 0.  (eg: sqrt(x))          | 
 0354 | +----------+---------------------------------------------------------+ 
 0355 | | sum      | Sum of all the inputs.                                  | 
 0356 | |          | (eg: sum(x,y,z,w,u,v,t) == (x + y + z + w + u + v + t)) | 
 0357 | +----------+---------------------------------------------------------+ 
 0358 | | swap     | Swap the values of the variables x and y and return the | 
 0359 | | <=>      | current value of y.  (eg: swap(x,y) or x <=> y)         | 
 0360 | +----------+---------------------------------------------------------+ 
 0361 | | trunc    | Integer portion of x.  (eg: trunc(x))                   | 
 0362 | +----------+---------------------------------------------------------+ 
 0363 |  
 0364 | (4) Trigonometry Functions 
 0365 | +----------+---------------------------------------------------------+ 
 0366 | | FUNCTION | DEFINITION                                              | 
 0367 | +----------+---------------------------------------------------------+ 
 0368 | | acos     | Arc cosine of x expressed in radians. Interval [-1,+1]  | 
 0369 | |          | (eg: acos(x))                                           | 
 0370 | +----------+---------------------------------------------------------+ 
 0371 | | acosh    | Inverse hyperbolic cosine of x expressed in radians.    | 
 0372 | |          | (eg: acosh(x))                                          | 
 0373 | +----------+---------------------------------------------------------+ 
 0374 | | asin     | Arc sine of x expressed in radians. Interval [-1,+1]    | 
 0375 | |          | (eg: asin(x))                                           | 
 0376 | +----------+---------------------------------------------------------+ 
 0377 | | asinh    | Inverse hyperbolic sine of x expressed in radians.      | 
 0378 | |          | (eg: asinh(x))                                          | 
 0379 | +----------+---------------------------------------------------------+ 
 0380 | | atan     | Arc tangent of x expressed in radians. Interval [-1,+1] | 
 0381 | |          | (eg: atan(x))                                           | 
 0382 | +----------+---------------------------------------------------------+ 
 0383 | | atan2    | Arc tangent of (x / y) expressed in radians. [-pi,+pi]  | 
 0384 | |          | eg: atan2(x,y)                                          | 
 0385 | +----------+---------------------------------------------------------+ 
 0386 | | atanh    | Inverse hyperbolic tangent of x expressed in radians.   | 
 0387 | |          | (eg: atanh(x))                                          | 
 0388 | +----------+---------------------------------------------------------+ 
 0389 | | cos      | Cosine of x.  (eg: cos(x))                              | 
 0390 | +----------+---------------------------------------------------------+ 
 0391 | | cosh     | Hyperbolic cosine of x.  (eg: cosh(x))                  | 
 0392 | +----------+---------------------------------------------------------+ 
 0393 | | cot      | Cotangent of x.  (eg: cot(x))                           | 
 0394 | +----------+---------------------------------------------------------+ 
 0395 | | csc      | Cosecant of x.  (eg: csc(x))                            | 
 0396 | +----------+---------------------------------------------------------+ 
 0397 | | sec      | Secant of x.  (eg: sec(x))                              | 
 0398 | +----------+---------------------------------------------------------+ 
 0399 | | sin      | Sine of x.  (eg: sin(x))                                | 
 0400 | +----------+---------------------------------------------------------+ 
 0401 | | sinc     | Sine cardinal of x.  (eg: sinc(x))                      | 
 0402 | +----------+---------------------------------------------------------+ 
 0403 | | sinh     | Hyperbolic sine of x.  (eg: sinh(x))                    | 
 0404 | +----------+---------------------------------------------------------+ 
 0405 | | tan      | Tangent of x.  (eg: tan(x))                             | 
 0406 | +----------+---------------------------------------------------------+ 
 0407 | | tanh     | Hyperbolic tangent of x.  (eg: tanh(x))                 | 
 0408 | +----------+---------------------------------------------------------+ 
 0409 | | deg2rad  | Convert x from degrees to radians.  (eg: deg2rad(x))    | 
 0410 | +----------+---------------------------------------------------------+ 
 0411 | | deg2grad | Convert x from degrees to gradians.  (eg: deg2grad(x))  | 
 0412 | +----------+---------------------------------------------------------+ 
 0413 | | rad2deg  | Convert x from radians to degrees.  (eg: rad2deg(x))    | 
 0414 | +----------+---------------------------------------------------------+ 
 0415 | | grad2deg | Convert x from gradians to degrees.  (eg: grad2deg(x))  | 
 0416 | +----------+---------------------------------------------------------+ 
 0417 |  
 0418 | (5) String Processing 
 0419 | +----------+---------------------------------------------------------+ 
 0420 | | FUNCTION | DEFINITION                                              | 
 0421 | +----------+---------------------------------------------------------+ 
 0422 | |  = , ==  | All common equality/inequality operators are applicable | 
 0423 | |  !=, <>  | to strings and are applied in a case sensitive manner.  | 
 0424 | |  <=, >=  | In the following example x, y and z are of type string. | 
 0425 | |  < , >   | (eg: not((x <= 'AbC') and ('1x2y3z' <> y)) or (z == x)  | 
 0426 | +----------+---------------------------------------------------------+ 
 0427 | | in       | True only if x is a substring of y.                     | 
 0428 | |          | (eg: x in y or 'abc' in 'abcdefgh')                     | 
 0429 | +----------+---------------------------------------------------------+ 
 0430 | | like     | True only if the string x matches the pattern y.        | 
 0431 | |          | Available wildcard characters are '*' and '?' denoting  | 
 0432 | |          | zero or more and zero or one matches respectively.      | 
 0433 | |          | (eg: x like y or 'abcdefgh' like 'a?d*h')               | 
 0434 | +----------+---------------------------------------------------------+ 
 0435 | | ilike    | True only if the string x matches the pattern y in a    | 
 0436 | |          | case insensitive manner. Available wildcard characters  | 
 0437 | |          | are '*' and '?' denoting zero or more and zero or one   | 
 0438 | |          | matches respectively.                                   | 
 0439 | |          | (eg: x ilike y or 'a1B2c3D4e5F6g7H' ilike 'a?d*h')      | 
 0440 | +----------+---------------------------------------------------------+ 
 0441 | | [r0:r1]  | The closed interval[r0,r1] of the specified string.     | 
 0442 | |          | eg: Given a string x with a value of 'abcdefgh' then:   | 
 0443 | |          | 1. x[1:4] == 'bcde'                                     | 
 0444 | |          | 2. x[ :4] == x[:8 / 2] == 'abcde'                       | 
 0445 | |          | 3. x[2 + 1: ] == x[3:] =='defgh'                        | 
 0446 | |          | 4. x[ : ] == x[:] == 'abcdefgh'                         | 
 0447 | |          | 5. x[4/2:3+1] == x[2:4] == 'cde'                        | 
 0448 | |          |                                                         | 
 0449 | |          | Note: Both r0 and r1 are assumed to be integers, where  | 
 0450 | |          | r0 <= r1. They may also be the result of an expression, | 
 0451 | |          | in the event they have fractional components truncation | 
 0452 | |          | shall be performed. (eg: 1.67 --> 1)                    | 
 0453 | +----------+---------------------------------------------------------+ 
 0454 | |  :=      | Assign the value of x to y. Where y is a mutable string | 
 0455 | |          | or string range and x is either a string or a string    | 
 0456 | |          | range. eg:                                              | 
 0457 | |          | 1. y := x                                               | 
 0458 | |          | 2. y := 'abc'                                           | 
 0459 | |          | 3. y := x[:i + j]                                       | 
 0460 | |          | 4. y := '0123456789'[2:7]                               | 
 0461 | |          | 5. y := '0123456789'[2i + 1:7]                          | 
 0462 | |          | 6. y := (x := '0123456789'[2:7])                        | 
 0463 | |          | 7. y[i:j] := x                                          | 
 0464 | |          | 8. y[i:j] := (x + 'abcdefg'[8 / 4:5])[m:n]              | 
 0465 | |          |                                                         | 
 0466 | |          | Note: For options 7 and 8 the shorter of the two ranges | 
 0467 | |          | will denote the number characters that are to be copied.| 
 0468 | +----------+---------------------------------------------------------+ 
 0469 | |  +       | Concatenation of x and y. Where x and y are strings or  | 
 0470 | |          | string ranges. eg                                       | 
 0471 | |          | 1. x + y                                                | 
 0472 | |          | 2. x + 'abc'                                            | 
 0473 | |          | 3. x + y[:i + j]                                        | 
 0474 | |          | 4. x[i:j] + y[2:3] + '0123456789'[2:7]                  | 
 0475 | |          | 5. 'abc' + x + y                                        | 
 0476 | |          | 6. 'abc' + '1234567'                                    | 
 0477 | |          | 7. (x + 'a1B2c3D4' + y)[i:2j]                           | 
 0478 | +----------+---------------------------------------------------------+ 
 0479 | |  +=      | Append to x the value of y. Where x is a mutable string | 
 0480 | |          | and y is either a string or a string range. eg:         | 
 0481 | |          | 1. x += y                                               | 
 0482 | |          | 2. x += 'abc'                                           | 
 0483 | |          | 3. x += y[:i + j] + 'abc'                               | 
 0484 | |          | 4. x += '0123456789'[2:7]                               | 
 0485 | +----------+---------------------------------------------------------+ 
 0486 | | <=>      | Swap the values of x and y. Where x and y are mutable   | 
 0487 | |          | strings.  (eg: x <=> y)                                 | 
 0488 | +----------+---------------------------------------------------------+ 
 0489 | | []       | The string size operator returns the size of the string | 
 0490 | |          | being actioned.                                         | 
 0491 | |          | eg:                                                     | 
 0492 | |          | 1. 'abc'[] == 3                                         | 
 0493 | |          | 2. var max_str_length := max(s0[], s1[], s2[], s3[])    | 
 0494 | |          | 3. ('abc' + 'd')[] == 6                                 | 
 0495 | |          | 4. (('abc' + 'xyz')[1:4])[] == 4                        | 
 0496 | +----------+---------------------------------------------------------+ 
 0497 |  
 0498 | (6) Control Structures 
 0499 | +----------+---------------------------------------------------------+ 
 0500 | |STRUCTURE | DEFINITION                                              | 
 0501 | +----------+---------------------------------------------------------+ 
 0502 | | if       | If x is true then return y else return z.               | 
 0503 | |          | eg:                                                     | 
 0504 | |          | 1. if (x, y, z)                                         | 
 0505 | |          | 2. if ((x + 1) > 2y, z + 1, w / v)                      | 
 0506 | |          | 3. if (x > y) z;                                        | 
 0507 | |          | 4. if (x <= 2*y) { z + w };                             | 
 0508 | +----------+---------------------------------------------------------+ 
 0509 | | if-else  | The if-else/else-if statement. Subject to the condition | 
 0510 | |          | branch the statement will return either the value of the| 
 0511 | |          | consequent or the alternative branch.                   | 
 0512 | |          | eg:                                                     | 
 0513 | |          | 1. if (x > y) z; else w;                                | 
 0514 | |          | 2. if (x > y) z; else if (w != u) v;                    | 
 0515 | |          | 3. if (x < y) { z; w + 1; } else u;                     | 
 0516 | |          | 4. if ((x != y) and (z > w))                            | 
 0517 | |          |    {                                                    | 
 0518 | |          |      y := sin(x) / u;                                   | 
 0519 | |          |      z := w + 1;                                        | 
 0520 | |          |    }                                                    | 
 0521 | |          |    else if (x > (z + 1))                                | 
 0522 | |          |    {                                                    | 
 0523 | |          |      w := abs (x - y) + z;                              | 
 0524 | |          |      u := (x + 1) > 2y ? 2u : 3u;                       | 
 0525 | |          |    }                                                    | 
 0526 | +----------+---------------------------------------------------------+ 
 0527 | | switch   | The first true case condition that is encountered will  | 
 0528 | |          | determine the result of the switch. If none of the case | 
 0529 | |          | conditions hold true, the default action is assumed as  | 
 0530 | |          | the final return value. This is sometimes also known as | 
 0531 | |          | a multi-way branch mechanism.                           | 
 0532 | |          | eg:                                                     | 
 0533 | |          | switch                                                  | 
 0534 | |          | {                                                       | 
 0535 | |          |    case x > (y + z) : 2 * x / abs(y - z);               | 
 0536 | |          |    case x < 3       : sin(x + y);                       | 
 0537 | |          |    default          : 1 + x;                            | 
 0538 | |          | }                                                       | 
 0539 | +----------+---------------------------------------------------------+ 
 0540 | | while    | The structure will repeatedly evaluate the internal     | 
 0541 | |          | statement(s) 'while' the condition is true. The final   | 
 0542 | |          | statement in the final iteration shall be used as the   | 
 0543 | |          | return value of the loop.                               | 
 0544 | |          | eg:                                                     | 
 0545 | |          | while ((x -= 1) > 0)                                    | 
 0546 | |          | {                                                       | 
 0547 | |          |    y := x + z;                                          | 
 0548 | |          |    w := u + y;                                          | 
 0549 | |          | }                                                       | 
 0550 | +----------+---------------------------------------------------------+ 
 0551 | | repeat/  | The structure will repeatedly evaluate the internal     | 
 0552 | | until    | statement(s) 'until' the condition is true. The final   | 
 0553 | |          | statement in the final iteration shall be used as the   | 
 0554 | |          | return value of the loop.                               | 
 0555 | |          | eg:                                                     | 
 0556 | |          | repeat                                                  | 
 0557 | |          |    y := x + z;                                          | 
 0558 | |          |    w := u + y;                                          | 
 0559 | |          | until ((x += 1) > 100)                                  | 
 0560 | +----------+---------------------------------------------------------+ 
 0561 | | for      | The structure will repeatedly evaluate the internal     | 
 0562 | |          | statement(s) while the condition is true. On each loop  | 
 0563 | |          | iteration, an 'incrementing' expression is evaluated.   | 
 0564 | |          | The conditional is mandatory whereas the initialiser    | 
 0565 | |          | and incrementing expressions are optional.              | 
 0566 | |          | eg:                                                     | 
 0567 | |          | for (var x := 0; (x < n) and (x != y); x += 1)          | 
 0568 | |          | {                                                       | 
 0569 | |          |    y := y + x / 2 - z;                                  | 
 0570 | |          |    w := u + y;                                          | 
 0571 | |          | }                                                       | 
 0572 | +----------+---------------------------------------------------------+ 
 0573 | | break    | Break terminates the execution of the nearest enclosed  | 
 0574 | | break[]  | loop, allowing for the execution to continue on external| 
 0575 | |          | to the loop. The default break statement will set the   | 
 0576 | |          | return value of the loop to NaN, where as the return    | 
 0577 | |          | based form will set the value to that of the break      | 
 0578 | |          | expression.                                             | 
 0579 | |          | eg:                                                     | 
 0580 | |          | while ((i += 1) < 10)                                   | 
 0581 | |          | {                                                       | 
 0582 | |          |    if (i < 5)                                           | 
 0583 | |          |       j -= i + 2;                                       | 
 0584 | |          |    else if (i % 2 == 0)                                 | 
 0585 | |          |       break;                                            | 
 0586 | |          |    else                                                 | 
 0587 | |          |       break[2i + 3];                                    | 
 0588 | |          | }                                                       | 
 0589 | +----------+---------------------------------------------------------+ 
 0590 | | continue | Continue results in the remaining portion of the nearest| 
 0591 | |          | enclosing loop body to be skipped.                      | 
 0592 | |          | eg:                                                     | 
 0593 | |          | for (var i := 0; i < 10; i += 1)                        | 
 0594 | |          | {                                                       | 
 0595 | |          |    if (i < 5)                                           | 
 0596 | |          |       continue;                                         | 
 0597 | |          |    j -= i + 2;                                          | 
 0598 | |          | }                                                       | 
 0599 | +----------+---------------------------------------------------------+ 
 0600 | | return   | Return immediately from within the current expression.  | 
 0601 | |          | With the option of passing back a variable number of    | 
 0602 | |          | values (scalar, vector or string). eg:                  | 
 0603 | |          | 1. return [1];                                          | 
 0604 | |          | 2. return [x, 'abx'];                                   | 
 0605 | |          | 3. return [x, x + y,'abx'];                             | 
 0606 | |          | 4. return [];                                           | 
 0607 | |          | 5. if (x < y)                                           | 
 0608 | |          |     return [x, x - y, 'result-set1', 123.456];          | 
 0609 | |          |    else                                                 | 
 0610 | |          |     return [y, x + y, 'result-set2'];                   | 
 0611 | +----------+---------------------------------------------------------+ 
 0612 | | ?:       | Ternary conditional statement, similar to that of the   | 
 0613 | |          | above denoted if-statement.                             | 
 0614 | |          | eg:                                                     | 
 0615 | |          | 1. x ? y : z                                            | 
 0616 | |          | 2. x + 1 > 2y ? z + 1 : (w / v)                         | 
 0617 | |          | 3. min(x,y) > z ? (x < y + 1) ? x : y : (w * v)         | 
 0618 | +----------+---------------------------------------------------------+ 
 0619 | | ~        | Evaluate each sub-expression, then return as the result | 
 0620 | |          | the value of the last sub-expression. This is sometimes | 
 0621 | |          | known as multiple sequence point evaluation.            | 
 0622 | |          | eg:                                                     | 
 0623 | |          | ~(i := x + 1, j := y / z, k := sin(w/u)) == (sin(w/u))) | 
 0624 | |          | ~{i := x + 1; j := y / z; k := sin(w/u)} == (sin(w/u))) | 
 0625 | +----------+---------------------------------------------------------+ 
 0626 | | [*]      | Evaluate any consequent for which its case statement is | 
 0627 | |          | true. The return value will be either zero or the result| 
 0628 | |          | of the last consequent to have been evaluated.          | 
 0629 | |          | eg:                                                     | 
 0630 | |          | [*]                                                     | 
 0631 | |          | {                                                       | 
 0632 | |          |   case (x + 1) > (y - 2)    : x := z / 2 + sin(y / pi); | 
 0633 | |          |   case (x + 2) < abs(y + 3) : w / 4 + min(5y,9);        | 
 0634 | |          |   case (x + 3) == (y * 4)   : y := abs(z / 6) + 7y;     | 
 0635 | |          | }                                                       | 
 0636 | +----------+---------------------------------------------------------+ 
 0637 | | []       | The vector size operator returns the size of the vector | 
 0638 | |          | being actioned.                                         | 
 0639 | |          | eg:                                                     | 
 0640 | |          | 1. v[]                                                  | 
 0641 | |          | 2. max_size := max(v0[],v1[],v2[],v3[])                 | 
 0642 | +----------+---------------------------------------------------------+ 
 0643 |  
 0644 | Note01: In  the  tables above, the symbols x, y, z, w, u  and v  where 
 0645 | appropriate may represent any of one the following: 
 0646 |  
 0647 |    1. Literal numeric/string value 
 0648 |    2. A variable 
 0649 |    3. A vector element 
 0650 |    4. A vector 
 0651 |    5. A string 
 0652 |    6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3]) 
 0653 |  
 0654 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0655 |  
 0656 | [SECTION 09 - FUNDAMENTAL TYPES] 
 0657 | ExprTk supports three fundamental types which can be used freely in 
 0658 | expressions. The types are as follows: 
 0659 |  
 0660 |    (1) Scalar 
 0661 |    (2) Vector 
 0662 |    (3) String 
 0663 |  
 0664 |  
 0665 | (1) Scalar Type 
 0666 | The scalar type  is a singular  numeric value. The  underlying type is 
 0667 | that used  to specialise  the ExprTk  components (float,  double, long 
 0668 | double, MPFR et al). 
 0669 |  
 0670 |  
 0671 | (2) Vector Type 
 0672 | The vector type is a fixed size sequence of contiguous scalar  values. 
 0673 | A  vector  can be  indexed  resulting in  a  scalar value.  Operations 
 0674 | between a vector and scalar will result in a vector with a size  equal 
 0675 | to that  of the  original vector,  whereas operations  between vectors 
 0676 | will result in a  vector of size equal  to that of the  smaller of the 
 0677 | two. In both mentioned cases, the operations will occur element-wise. 
 0678 |  
 0679 |  
 0680 | (3) String Type 
 0681 | The string type is a variable length sequence of 8-bit chars.  Strings 
 0682 | can be  assigned and  concatenated to  one another,  they can  also be 
 0683 | manipulated via sub-ranges using the range definition syntax.  Strings 
 0684 | however can not interact with scalar or vector types. 
 0685 |  
 0686 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 0687 |  
 0688 | [SECTION 10 - COMPONENTS] 
 0689 | There are three primary components, that are specialised upon a  given 
 0690 | numeric type, which make up the core of ExprTk. The components are  as 
 0691 | follows: 
 0692 |  
 0693 |    (1) Symbol Table  exprtk::symbol_table<NumericType> 
 0694 |    (2) Expression    exprtk::expression<NumericType> 
 0695 |    (3) Parser        exprtk::parser<NumericType> 
 0696 |  
 0697 |  
 0698 | (1) Symbol Table 
 0699 | A structure that is used  to store references to variables,  constants 
 0700 | and functions that are to  be used within expressions. Furthermore  in 
 0701 | the context  of composited  recursive functions  the symbol  table can 
 0702 | also be thought of as a simple representation of a stack specific  for 
 0703 | the expression(s) that reference it. The following is a list of the 
 0704 | types a symbol table can handle: 
 0705 |  
 0706 |    (a) Numeric variables 
 0707 |    (b) Numeric constants 
 0708 |    (c) Numeric vector elements 
 0709 |    (d) String variables 
 0710 |    (e) String constants 
 0711 |    (f) Functions 
 0712 |    (g) Vararg functions 
 0713 |  
 0714 |  
 0715 | During the compilation  process if an  expression is found  to require 
 0716 | any  of  the  elements   noted  above,  the  expression's   associated 
 0717 | symbol_table  will  be  queried  for  the  element  and  if  present a 
 0718 | reference to the element will be embedded within the expression's AST. 
 0719 | This allows for the original  element to be modified independently  of 
 0720 | the  expression  instance  and  to also  allow  the  expression  to be 
 0721 | evaluated using the current value of the element. 
 0722 |  
 0723 | The  example  below demonstrates  the  relationship between variables, 
 0724 | symbol_table and expression. Note  the variables are modified  as they 
 0725 | normally would in a program, and when the expression is  evaluated the 
 0726 | current values assigned to the variables shall be used. 
 0727 |  
 0728 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 0729 |    typedef exprtk::expression<double>   expression_t; 
 0730 |    typedef exprtk::parser<double>       parser_t; 
 0731 |  
 0732 |    double x = 0; 
 0733 |    double y = 0; 
 0734 |  
 0735 |    symbol_table_t symbol_table; 
 0736 |    expression_t   expression; 
 0737 |    parser_t       parser; 
 0738 |  
 0739 |    std::string expression_string = "x * y + 3" 
 0740 |  
 0741 |    symbol_table.add_variable("x",x); 
 0742 |    symbol_table.add_variable("y",y); 
 0743 |  
 0744 |    expression.register_symbol_table(symbol_table); 
 0745 |  
 0746 |    parser.compile(expression_string,expression); 
 0747 |  
 0748 |    x = 1.0; 
 0749 |    y = 2.0; 
 0750 |    expression.value(); // 1 * 2 + 3 
 0751 |  
 0752 |    x = 3.7; 
 0753 |    expression.value(); // 3.7 * 2 + 3 
 0754 |  
 0755 |    y = -9.0; 
 0756 |    expression.value(); // 3.7 * -9 + 3 
 0757 |  
 0758 |    // 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001 
 0759 |    for (x = 0.0; x < 100.0; x += 0.0001) 
 0760 |    { 
 0761 |       expression.value(); // x * -9 + 3 
 0762 |    } 
 0763 |  
 0764 |  
 0765 | Note02: Any  variable  reference  provided  to  a  given  symbol_table 
 0766 | instance, must have a lifetime at least as long as the lifetime of the 
 0767 | symbol_table  instance.  In  the  event  the  variable  reference   is 
 0768 | invalidated  before  the  symbol_table  or  any  dependent  expression 
 0769 | instances  have  been  destructed,  then  any  associated   expression 
 0770 | evaluations or variable referencing via the symbol_table instance will 
 0771 | result in undefined behaviour. 
 0772 |  
 0773 | The following bit of  code instantiates a symbol_table  and expression 
 0774 | instance,  then  proceeds  to   demonstrate  various  ways  in   which 
 0775 | references to  variables can  be added  to the  symbol_table, and  how 
 0776 | those  references are  subsequently invalidated  resulting in  various 
 0777 | forms of undefined behaviour. 
 0778 |  
 0779 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 0780 |    typedef exprtk::expression<double>   expression_t; 
 0781 |  
 0782 |    symbol_table_t symbol_table; 
 0783 |    expression_t   expression; 
 0784 |  
 0785 |    std::deque<double > y {1.1, 2.2, 3.3}; 
 0786 |    std::vector<double> z {4.4, 5.5, 6.6}; 
 0787 |    double* w = new double(123.456); 
 0788 |  
 0789 |    { 
 0790 |       double x = 123.4567; 
 0791 |       symbol_table.add_variable("x", x); 
 0792 |    }             // Reference to variable x has been invalidated 
 0793 |  
 0794 |  
 0795 |    symbol_table.add_variable("y", y.back()); 
 0796 |  
 0797 |    y.pop_back(); // Reference to variable y has been invalidated 
 0798 |  
 0799 |  
 0800 |    symbol_table.add_variable("z", z.front()); 
 0801 |  
 0802 |    z.erase(z.begin()); 
 0803 |                  // Reference to variable z has been invalidated 
 0804 |  
 0805 |    symbol_table.add_variable("w", *w); 
 0806 |  
 0807 |    delete w;     // Reference to variable w has been invalidated 
 0808 |  
 0809 |    const std::string expression_string = "x + y / z * w" 
 0810 |  
 0811 |                  // Compilation of expression will succeed 
 0812 |    parser.compile(expression_string,expression); 
 0813 |  
 0814 |    expression.value(); 
 0815 |                  // Evaluation will result in undefined behaviour 
 0816 |                  // due to 'x' and 'w' having been destroyed. 
 0817 |  
 0818 |    symbol_table.get_variable("x")->ref() = 135.791; 
 0819 |                  // Assignment will result in undefined behaviour 
 0820 |  
 0821 |  
 0822 | A compiled expression that references variables from a symbol_table is 
 0823 | dependent on  that symbol_table  instance and  the variables  it holds 
 0824 | being valid. 
 0825 |  
 0826 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 0827 |    typedef exprtk::expression<double>   expression_t; 
 0828 |  
 0829 |    symbol_table_t symbol_table; 
 0830 |    expression_t   expression; 
 0831 |  
 0832 |    double x = 123.456; 
 0833 |  
 0834 |    symbol_table.add_variable("x", x); 
 0835 |  
 0836 |    const std::string expression_string = "(x + 1) / 2" 
 0837 |  
 0838 |                  // Compilation of the expression will succeed 
 0839 |    parser.compile(expression_string,expression); 
 0840 |  
 0841 |                  // Clear all variables from symbol_table 
 0842 |    symbol_table.clear(); 
 0843 |  
 0844 |    expression.value(); 
 0845 |                  // Evaluation will result in undefined behaviour 
 0846 |                  // because the reference to 'x' having been destroyed 
 0847 |                  // during the clearing of the symbol_table 
 0848 |  
 0849 |  
 0850 | In  the  above  example, an  expression  is  compiled that  references 
 0851 | variable "x". As part of the compilation process the node holding  the 
 0852 | variable "x" is obtained from the symbol_table and embedded in the AST 
 0853 | of the  expression -  in short  the expression  is now referencing the 
 0854 | node that holds  the variable "x".  The following diagram  depicts the 
 0855 | dependencies between  the  variable   x,  the  symbol  table  and  the 
 0856 | expression: 
 0857 |  
 0858 |       +--[Symbol Table]--+ 
 0859 |       |                  | 
 0860 |       | +- ------+       | 
 0861 |       | | x-node |       | 
 0862 |       | +-----A--+       |    +--[Expression]--+ 
 0863 |       +---|---|----------+    |  +---------+   | 
 0864 |           v   |               |  |  A.S.T  |   | 
 0865 |           |   +--------<--------[.]        |   | 
 0866 |     +-----+                   |  +---------+   | 
 0867 |     |                         +----------------+ 
 0868 |   +-v-[variable]---+ 
 0869 |   | x: 123.456     | 
 0870 |   +----------------+ 
 0871 |  
 0872 |  
 0873 | When the  clear method  is called  on the  symbol table  the X-Node is 
 0874 | destroyed, so now the expression  is referencing a node that  has been 
 0875 | destroyed.  From  this point  onwards  any attempts  to  reference the 
 0876 | expression instance will result in undefined behaviour. Simply put the 
 0877 | above  example  violates  the requirement  that  the  lifetime of  any 
 0878 | objects referenced by  expressions should exceed  the lifetime of  the 
 0879 | expression instance. 
 0880 |  
 0881 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 0882 |    typedef exprtk::expression<double>   expression_t; 
 0883 |  
 0884 |    symbol_table_t symbol_table; 
 0885 |    expression_t   expression; 
 0886 |  
 0887 |    double x = 123.456; 
 0888 |  
 0889 |    symbol_table.add_variable("x", x); 
 0890 |  
 0891 |    const std::string expression_string = "(x + 1) / 2" 
 0892 |  
 0893 |                  // Compilation of the expression will succeed 
 0894 |    parser.compile(expression_string,expression); 
 0895 |  
 0896 |    expression.value(); 
 0897 |  
 0898 |                  // Release the expression and its dependents 
 0899 |    expression.release(); 
 0900 |  
 0901 |                  // Clear all variables from symbol_table 
 0902 |    symbol_table.clear(); 
 0903 |  
 0904 |    expression.value(); 
 0905 |                  // Will return null_node value of NaN 
 0906 |  
 0907 |  
 0908 | In the above example the expression is released before the  associated 
 0909 | symbol_table is cleared of its variables, which resolves the undefined 
 0910 | behaviour issue noted in the previous example. 
 0911 |  
 0912 | Note03: It  is possible  to  register  multiple  symbol_tables  with a 
 0913 | single  expression object.  In the  event an  expression has  multiple 
 0914 | symbol tables, and where  there exists conflicts between  symbols, the 
 0915 | compilation stage  will resolve  the conflicts  based on  the order of 
 0916 | registration  of  the  symbol_tables to  the  expression.  For a  more 
 0917 | expansive discussion please review section [17 - Hierarchies Of Symbol 
 0918 | Tables] 
 0919 |  
 0920 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 0921 |    typedef exprtk::expression<double>   expression_t; 
 0922 |    typedef exprtk::parser<double>       parser_t; 
 0923 |  
 0924 |    symbol_table_t symbol_table0; 
 0925 |    symbol_table_t symbol_table1; 
 0926 |  
 0927 |    expression_t   expression; 
 0928 |    parser_t       parser; 
 0929 |  
 0930 |    double x0 = 123.0; 
 0931 |    double x1 = 678.0; 
 0932 |  
 0933 |    std::string expression_string = "x + 1" 
 0934 |  
 0935 |    symbol_table0.add_variable("x",x0); 
 0936 |    symbol_table1.add_variable("x",x1); 
 0937 |  
 0938 |    expression.register_symbol_table(symbol_table0); 
 0939 |    expression.register_symbol_table(symbol_table1); 
 0940 |  
 0941 |    parser.compile(expression_string,expression); 
 0942 |  
 0943 |    expression.value(); // 123 + 1 
 0944 |  
 0945 |  
 0946 | The symbol table supports  adding references to external  instances of 
 0947 | types  that  can  be accessed  within  expressions  via the  following 
 0948 | methods: 
 0949 |  
 0950 |   1. bool add_variable    (const std::string& name, scalar_t&        ) 
 0951 |   2. bool add_constant    (const std::string& name, const scalar_t&  ) 
 0952 |   3. bool add_stringvar   (const std::string& name, std::string&     ) 
 0953 |   4. bool add_vector      (const std::string& name, vector_type&     ) 
 0954 |   5. bool add_function    (const std::string& name, function_t&      ) 
 0955 |   6. bool create_stringvar(const std::string& name,const std::string&) 
 0956 |   7. bool create_variable (const std::string& name, const T&         ) 
 0957 |  
 0958 |  
 0959 | Note04: The 'vector' type must be comprised from a contiguous array of 
 0960 | scalars with a size that is  larger than zero. The vector type  itself 
 0961 | can be any one of the following: 
 0962 |  
 0963 |    1. std::vector<scalar_t> 
 0964 |    2. scalar_t(&v)[N] 
 0965 |    3. scalar_t* and array size 
 0966 |    4. exprtk::vector_view<scalar_t> 
 0967 |  
 0968 |  
 0969 | When  registering  a variable,  vector,  string or  function  with  an 
 0970 | instance of a symbol_table, the call to 'add_...' may fail and  return 
 0971 | a false result due to one or more of the following reasons: 
 0972 |  
 0973 |   1. Variable name contains invalid characters or is ill-formed 
 0974 |   2. Variable name conflicts with a reserved word (eg: 'while') 
 0975 |   3. Variable name conflicts with a previously registered variable 
 0976 |   4. A vector of size (length) zero is being registered 
 0977 |   5. A free function exceeding fifteen parameters is being registered 
 0978 |   6. The symbol_table instance is in an invalid state 
 0979 |  
 0980 |  
 0981 | Note05: The symbol_table has a method called clear, which when invoked 
 0982 | will clear  all variables,  vectors, strings  and functions registered 
 0983 | with the symbol_table instance. If  this method is to be  called, then 
 0984 | one  must  make  sure  that  all  compiled  expression  instances that 
 0985 | reference  variables  belonging  to  that  symbol_table  instance  are 
 0986 | released (aka call  release method on  expression) before calling  the 
 0987 | clear  method  on  the  symbol_table  instance,  otherwise   undefined 
 0988 | behaviours will occur. 
 0989 |  
 0990 | A further property of symbol tables is that they can be classified  at 
 0991 | instantiation as either being mutable (by default) or immutable.  This 
 0992 | property determines if variables,  vectors or strings registered  with 
 0993 | the symbol  table can  undergo modifications  within expressions  that 
 0994 | reference  them.  The   following  demonstrates  construction   of  an 
 0995 | immutable symbol table instance: 
 0996 |  
 0997 |   symbol_table_t immutable_symbol_table 
 0998 |      (symbol_table_t::symtab_mutability_type::e_immutable); 
 0999 |  
 1000 |  
 1001 | When a symbol table, that has been constructed as  being immutable, is 
 1002 | registered with an expression, any statements in the expression string 
 1003 | that modify  the variables  that are  managed by  the immutable symbol 
 1004 | table will result in a compilation error. The operations that  trigger 
 1005 | the mutability constraint are the following assignment operators: 
 1006 |  
 1007 |   1. Assignment:       := 
 1008 |   2. Assign operation: +=, -=, *=, /= , %= 
 1009 |  
 1010 |    const std::string expression_str = "x += x + 123.456" 
 1011 |  
 1012 |    symbol_table_t immutable_symbol_table 
 1013 |       (symbol_table_t::symtab_mutability_type::e_immutable); 
 1014 |  
 1015 |    T x = 0.0; 
 1016 |  
 1017 |    immutable_symbol_table.add_variable("x" , x); 
 1018 |  
 1019 |    expression_t expression; 
 1020 |    expression.register_symbol_table(immutable_symbol_table); 
 1021 |  
 1022 |    parser_t parser; 
 1023 |  
 1024 |    parser.compile(expression_str, expression); 
 1025 |       // Compile error because of assignment to variable x 
 1026 |  
 1027 |  
 1028 | In the above example, variable x is registered to an immutable  symbol 
 1029 | table,  making it  an immutable  variable within  the context  of any 
 1030 | expressions that  reference it.  The expression  string being compiled 
 1031 | uses the addition assignment operator  which will modify the value  of 
 1032 | variable x.  The compilation  process detects  this semantic violation 
 1033 | and proceeds to halt compilation and return the appropriate error. 
 1034 |  
 1035 | One of the main reasons for  this functionality is that, one may  want 
 1036 | the immutability  properties that  come with  constness of  a variable 
 1037 | such  as  scalars,  vectors  and  strings,  but  not  necessarily  the 
 1038 | accompanying  compile  time  const-folding  optimisations,  that would 
 1039 | result in  the value  of the  variables being  retrieved only  once at 
 1040 | compile time, causing external updates to the variables to not be part 
 1041 | of the expression evaluation. 
 1042 |  
 1043 |    symbol_table_t immutable_symbol_table 
 1044 |       (symbol_table_t::symtab_mutability_type::e_immutable); 
 1045 |  
 1046 |    T x = 0.0; 
 1047 |  
 1048 |    const std::string expression_str = "x + (y + y)" 
 1049 |  
 1050 |    immutable_symbol_table.add_variable("x" , x    ); 
 1051 |    immutable_symbol_table.add_constant("y" , 123.0); 
 1052 |  
 1053 |    expression_t expression; 
 1054 |    expression.register_symbol_table(immutable_symbol_table); 
 1055 |  
 1056 |    parser_t parser; 
 1057 |    parser.compile(expression_str, expression); 
 1058 |  
 1059 |    for (; x < 10.0; ++x) 
 1060 |    { 
 1061 |       const auto expected_value = x + (123.0 + 123.0); 
 1062 |       const auto result_value   = expression.value(); 
 1063 |       assert(expression.value() !=  expected_value); 
 1064 |    } 
 1065 |  
 1066 |  
 1067 | In the above example,  there are two variables  X and Y. Where  Y is a 
 1068 | constant and X is a normal variable. Both are registered with a symbol 
 1069 | table that is immutable. The  expression when compiled will result  in 
 1070 | the "(y + y)" part being  const-folded at compile time to the  literal 
 1071 | value of 246. Whereas  the current value of  X, being updated via  the 
 1072 | for-loop, externally to  the expression and  the symbol table shall be 
 1073 | observable to the expression upon each evaluation. 
 1074 |  
 1075 |  
 1076 | (2) Expression 
 1077 | A structure that holds an Abstract Syntax Tree or AST for a  specified 
 1078 | expression and is used to evaluate said expression. Evaluation of  the 
 1079 | expression is accomplished by performing a post-order traversal of the 
 1080 | AST.  If  a  compiled  Expression  uses  variables  or  user   defined 
 1081 | functions, it will have an associated Symbol Table, which will contain 
 1082 | references  to said  variables, functions  or strings. An example  AST 
 1083 | structure for the denoted expression is as follows: 
 1084 |  
 1085 | Expression:  z := (x + y^-2.345) * sin(pi / min(w - 7.3,v)) 
 1086 |  
 1087 |                   [Root] 
 1088 |                     | 
 1089 |                [Assignment] 
 1090 |         ________/        \_____ 
 1091 |        /                       \ 
 1092 |  Variable(z)            [Multiplication] 
 1093 |                 ____________/      \___________ 
 1094 |                /                               \ 
 1095 |               /                      [Unary-Function(sin)] 
 1096 |          [Addition]                            | 
 1097 |       ____/      \____                    [Division] 
 1098 |      /                \                 ___/      \___ 
 1099 |  Variable(x)   [Exponentiation]        /              \ 
 1100 |               ______/   \______  Constant(pi) [Binary-Function(min)] 
 1101 |              /                 \                ____/    \___ 
 1102 |         Variable(y)        [Negation]          /             \ 
 1103 |                                |              /          Variable(v) 
 1104 |                         Constant(2.345)      / 
 1105 |                                             / 
 1106 |                                      [Subtraction] 
 1107 |                                    ____/      \____ 
 1108 |                                   /                \ 
 1109 |                              Variable(w)      Constant(7.3) 
 1110 |  
 1111 |  
 1112 | The above denoted AST shall be evaluated in the following order: 
 1113 |  
 1114 |    (01) Load Variable  (z)        (10) Load Constant  (7.3) 
 1115 |    (02) Load Variable  (x)        (11) Subtraction    (09 & 10) 
 1116 |    (03) Load Variable  (y)        (12) Load Variable  (v) 
 1117 |    (04) Load Constant  (2.345)    (13) Min            (11 & 12) 
 1118 |    (05) Negation       (04)       (14) Division       (08 & 13) 
 1119 |    (06) Exponentiation (03 & 05)  (15) Sin            (14) 
 1120 |    (07) Addition       (02 & 06)  (16) Multiplication (07 & 15) 
 1121 |    (08) Load Constant  (pi)       (17) Assignment     (01 & 16) 
 1122 |    (09) Load Variable  (w) 
 1123 |  
 1124 |  
 1125 | Generally an expression in ExprTk can be thought of as a free function 
 1126 | similar to those  found in imperative  languages. This form  of pseudo 
 1127 | function will have a name, it may have a set of one or more inputs and 
 1128 | will return at least one value as its result. Furthermore the function 
 1129 | when invoked, may  cause a side-effect  that changes the  state of the 
 1130 | host program. 
 1131 |  
 1132 | As an  example the  following is  a pseudo-code  definition of  a free 
 1133 | function that performs a computation taking four inputs, modifying one 
 1134 | of them and returning a value based on some arbitrary calculation: 
 1135 |  
 1136 |    ResultType foo(InputType x, InputType y, InputType z, InputType w) 
 1137 |    { 
 1138 |       w = 2 * x^y + z;        // Side-Effect 
 1139 |       return abs(x - y) / z;  // Return Result 
 1140 |    } 
 1141 |  
 1142 |  
 1143 | Given the above definition the following is a functionally  equivalent 
 1144 | version using ExprTk: 
 1145 |  
 1146 |    const std::string foo_str = 
 1147 |       " w := 2 * x^y + z; " 
 1148 |       " abs(x - y) / z;   " 
 1149 |  
 1150 |    T x, y, z, w; 
 1151 |  
 1152 |    symbol_table_t symbol_table; 
 1153 |    symbol_table.add_variable("x",x); 
 1154 |    symbol_table.add_variable("y",y); 
 1155 |    symbol_table.add_variable("z",z); 
 1156 |    symbol_table.add_variable("w",w); 
 1157 |  
 1158 |    expression_t foo; 
 1159 |    foo.register_symbol_table(symbol_table); 
 1160 |  
 1161 |    parser_t parser; 
 1162 |    if (!parser.compile(foo_str,foo)) 
 1163 |    { 
 1164 |       // Error in expression... 
 1165 |       return; 
 1166 |    } 
 1167 |  
 1168 |    T result = foo.value(); 
 1169 |  
 1170 |  
 1171 | (3) Parser 
 1172 | A  component  which  takes  as input  a  string  representation  of an 
 1173 | expression and attempts to compile said input with the result being an 
 1174 | instance  of  Expression.  If  an  error  is  encountered  during  the 
 1175 | compilation  process, the  parser will  stop compiling  and return  an 
 1176 | error status code,  with a more  detailed description of  the error(s) 
 1177 | and  its  location  within  the  input  provided  by  the  'get_error' 
 1178 | interface. 
 1179 |  
 1180 | Note06: The exprtk::expression and exprtk::symbol_table components are 
 1181 | reference counted entities. Copy constructing or assigning to or  from 
 1182 | either component will result in  a shallow copy and a  reference count 
 1183 | increment,  rather  than  a  complete  replication.  Furthermore   the 
 1184 | expression  and symbol_table  components being  Default-Constructible, 
 1185 | Copy-Constructible  and  Copy-Assignable  make  them  compatible  with 
 1186 | various  C++  standard  library   containers  and  adaptors  such   as 
 1187 | std::vector, std::map, std::stack etc. 
 1188 |  
 1189 | The following is  an example of  two unique expressions,  after having 
 1190 | been instantiated and  compiled,  one expression  is  assigned to  the 
 1191 | other. The diagrams depict  their initial and post  assignment states, 
 1192 | including  which  control  block each  expression references and their 
 1193 | associated reference counts. 
 1194 |  
 1195 |  
 1196 |     exprtk::expression e0; // constructed expression, eg: x + 1 
 1197 |     exprtk::expression e1; // constructed expression, eg: 2z + y 
 1198 |  
 1199 |   +-----[ e0 cntrl block]----+     +-----[ e1 cntrl block]-----+ 
 1200 |   | 1. Expression Node 'x+1' |     | 1. Expression Node '2z+y' | 
 1201 |   | 2. Ref Count: 1          |<-+  | 2. Ref Count: 1           |<-+ 
 1202 |   +--------------------------+  |  +---------------------------+  | 
 1203 |                                 |                                 | 
 1204 |     +--[ e0 expression]--+      |    +--[ e1 expression]--+       | 
 1205 |     | 1. Reference to    ]------+    | 1. Reference to    ]-------+ 
 1206 |     | e0 Control Block   |           | e1 Control Block   | 
 1207 |     +--------------------+           +--------------------+ 
 1208 |  
 1209 |  
 1210 |    e0 = e1; // e0 and e1 are now 2z+y 
 1211 |  
 1212 |                +-----[ e1 cntrl block]-----+ 
 1213 |                | 1. Expression Node '2z+y' | 
 1214 |   +----------->| 2. Ref Count: 2           |<----------+ 
 1215 |   |            +---------------------------+           | 
 1216 |   |                                                    | 
 1217 |   |   +--[ e0 expression]--+  +--[ e1 expression]--+   | 
 1218 |   +---[ 1. Reference to    |  | 1. Reference to    ]---+ 
 1219 |       | e1 Control Block   |  | e1 Control Block   | 
 1220 |       +--------------------+  +--------------------+ 
 1221 |  
 1222 | The reason for  the above complexity  and restrictions of  deep copies 
 1223 | for the expression and symbol_table components is because  expressions 
 1224 | may include user defined variables or functions. These are embedded as 
 1225 | references into the expression's AST. When copying an expression, said 
 1226 | references  need to  also  be  copied. If  the references  are blindly 
 1227 | copied,  it  will then  result  in two  or more  identical expressions 
 1228 | utilising the exact same  references for variables. This  obviously is 
 1229 | not the  default assumed  scenario and  will give  rise to non-obvious 
 1230 | behaviours  when  using the  expressions in  various contexts such  as 
 1231 | multi-threading et al. 
 1232 |  
 1233 | The prescribed method for cloning an expression is to compile it  from 
 1234 | its string  form. Doing so will allow the 'user' to  properly consider 
 1235 | the exact source of user defined variables and functions. 
 1236 |  
 1237 | Note07: The exprtk::parser  is  a  non-copyable  and  non-thread  safe 
 1238 | component, and should only be shared via either a reference, a  shared 
 1239 | pointer  or  a  std::ref  mechanism,  and  considerations  relating to 
 1240 | synchronisation  taken  into  account  where  appropriate.  The parser 
 1241 | represents an object factory,  specifically a factory of  expressions, 
 1242 | and generally should  not be instantiated  solely on a  per expression 
 1243 | compilation basis. 
 1244 |  
 1245 | The  following  diagram  and  example depicts  the  flow  of  data and 
 1246 | operations  for  compiling  multiple expressions  via  the  parser and 
 1247 | inserting  the  newly  minted  exprtk::expression  instances  into   a 
 1248 | std::vector. 
 1249 |  
 1250 |                       +----[exprtk::parser]---+ 
 1251 |                       |   Expression Factory  | 
 1252 |                       | parser_t::compile(...)| 
 1253 |                     +--> ~.~.~.~.~.~.~.~.~.~ ->--+ 
 1254 |                     | +-----------------------+  | 
 1255 |  Expressions in     |                            |  Expressions as 
 1256 |  string form        ^                            V  exprtk::expression 
 1257 |                     |                            |  instances 
 1258 |  [s0:'x+1']--->--+  |                            |  +-[e0: x+1] 
 1259 |                  |  |                            |  | 
 1260 |  [s1:'2z+y']-->--+--+                            +->+-[e1: 2z+y] 
 1261 |                  |                                  | 
 1262 |  [s2:'sin(k+w)']-+                                  +-[e2: sin(k+w)] 
 1263 |  
 1264 |  
 1265 |    const std::string expression_str[3] = 
 1266 |       { 
 1267 |          "x + 1", 
 1268 |          "2x + y", 
 1269 |          "sin(k + w)" 
 1270 |       }; 
 1271 |  
 1272 |    std::vector<expression_t> expression_list; 
 1273 |  
 1274 |    parser_t       parser; 
 1275 |    expression_t   expression; 
 1276 |    symbol_table_t symbol_table; 
 1277 |  
 1278 |    expression.register_symbol_table(symbol_table); 
 1279 |  
 1280 |    for (std::size_t i = 0; i < 3; ++i) 
 1281 |    { 
 1282 |       if (parser.compile(expression_str[i],expression)) 
 1283 |       { 
 1284 |          expression_list.push_back(expression); 
 1285 |       } 
 1286 |       else 
 1287 |         std::cout << "Error in " << expression_str[i] << "\n" 
 1288 |    } 
 1289 |  
 1290 |    for (auto& e : expression_list) 
 1291 |    { 
 1292 |       e.value(); 
 1293 |    } 
 1294 |  
 1295 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 1296 |  
 1297 | [SECTION 11 - COMPILATION OPTIONS] 
 1298 | The exprtk::parser  when being  instantiated takes  as input  a set of 
 1299 | options  to be  used during  the compilation  process of  expressions. 
 1300 | An  example instantiation  of exprtk::parser  where only  the  joiner, 
 1301 | commutative and strength reduction options are enabled is as  follows: 
 1302 |  
 1303 |    typedef exprtk::parser<NumericType>::settings_t settings_t; 
 1304 |  
 1305 |    const std::size_t compile_options = 
 1306 |                         settings_t::e_joiner            + 
 1307 |                         settings_t::e_commutative_check + 
 1308 |                         settings_t::e_strength_reduction; 
 1309 |  
 1310 |    parser_t parser(compile_options); 
 1311 |  
 1312 |  
 1313 | Currently  eight  types of  compile  time options  are  supported, and 
 1314 | enabled by default. The options and their explanations are as follows: 
 1315 |  
 1316 |    (1) Replacer 
 1317 |    (2) Joiner 
 1318 |    (3) Numeric Check 
 1319 |    (4) Bracket Check 
 1320 |    (5) Sequence Check 
 1321 |    (6) Commutative Check 
 1322 |    (7) Strength Reduction Check 
 1323 |    (8) Stack And Node Depth Check 
 1324 |    (9) Vector Size Check 
 1325 |  
 1326 |  
 1327 | (1) Replacer (e_replacer) 
 1328 | Enable replacement of specific  tokens with other tokens.  For example 
 1329 | the token  "true" of  type symbol  shall be  replaced with the numeric 
 1330 | token of value one. 
 1331 |  
 1332 |    (a) (x < y) == true   --->  (x < y) == 1 
 1333 |    (b) false == (x > y)  --->  0 == (x > y) 
 1334 |  
 1335 |  
 1336 | (2) Joiner (e_joiner) 
 1337 | Enable  joining  of  multi-character  operators  that  may  have  been 
 1338 | incorrectly  disjoint in the  string  representation  of the specified 
 1339 | expression. For example the consecutive tokens of ">" "=" will  become 
 1340 | ">=" representing  the "greater  than or  equal to"  operator. If  not 
 1341 | properly resolved the  original form will  cause a compilation  error. 
 1342 | The  following  is  a listing  of the  scenarios that  the joiner  can 
 1343 | handle: 
 1344 |  
 1345 |    (a) '>' '='  --->  '>='  (gte) 
 1346 |    (b) '<' '='  --->  '<='  (lte) 
 1347 |    (c) '=' '='  --->  '=='  (equal) 
 1348 |    (d) '!' '='  --->  '!='  (not-equal) 
 1349 |    (e) '<' '>'  --->  '<>'  (not-equal) 
 1350 |    (f) ':' '='  --->  ':='  (assignment) 
 1351 |    (g) '+' '='  --->  '+='  (addition assignment) 
 1352 |    (h) '-' '='  --->  '-='  (subtraction assignment) 
 1353 |    (i) '*' '='  --->  '*='  (multiplication assignment) 
 1354 |    (j) '/' '='  --->  '/='  (division assignment) 
 1355 |    (k) '%' '='  --->  '%='  (modulo assignment) 
 1356 |    (l) '+' '-'  --->  '-'   (subtraction) 
 1357 |    (m) '-' '+'  --->  '-'   (subtraction) 
 1358 |    (n) '-' '-'  --->  '+'   (addition) 
 1359 |    (o) '<=' '>' --->  '<=>' (swap) 
 1360 |  
 1361 |  
 1362 | An example of the transformation that takes place is as follows: 
 1363 |  
 1364 |    (a) (x > = y) and (z ! = w)  --->  (x >= y) and (z != w) 
 1365 |  
 1366 |  
 1367 | (3) Numeric Check (e_numeric_check) 
 1368 | Enable validation of tokens representing numeric types so as to  catch 
 1369 | any errors prior  to the costly  process of the  main compilation step 
 1370 | commencing. 
 1371 |  
 1372 |  
 1373 | (4) Bracket Check (e_bracket_check) 
 1374 | Enable  the  check for  validating  the ordering  of  brackets in  the 
 1375 | specified expression. 
 1376 |  
 1377 |  
 1378 | (5) Sequence Check (e_sequence_check) 
 1379 | Enable the  check for  validating that  sequences of  either pairs  or 
 1380 | triplets of tokens make sense.  For example the following sequence  of 
 1381 | tokens when encountered will raise an error: 
 1382 |  
 1383 |    (a) (x + * 3)  --->  sequence error 
 1384 |  
 1385 |  
 1386 | (6) Commutative Check (e_commutative_check) 
 1387 | Enable the check that will transform sequences of pairs of tokens that 
 1388 | imply a multiplication operation.  The following are some  examples of 
 1389 | such transformations: 
 1390 |  
 1391 |    (a) 2x             --->  2 * x 
 1392 |    (b) 25x^3          --->  25 * x^3 
 1393 |    (c) 3(x + 1)       --->  3 * (x + 1) 
 1394 |    (d) (x + 1)4       --->  (x + 1) * 4 
 1395 |    (e) 5foo(x,y)      --->  5 * foo(x,y) 
 1396 |    (f) foo(x,y)6 + 1  --->  foo(x,y) * 6 + 1 
 1397 |    (g) (4((2x)3))     --->  4 * ((2 * x) * 3) 
 1398 |    (h) w / (x - y)z   --->  w / (x - y) * z 
 1399 |  
 1400 |  
 1401 | (7) Strength Reduction Check (e_strength_reduction) 
 1402 | Enable  the  use  of  strength  reduction  optimisations  during   the 
 1403 | compilation  process.  In  ExprTk  strength  reduction   optimisations 
 1404 | predominantly involve  transforming sub-expressions  into other  forms 
 1405 | that  are algebraically  equivalent yet  less costly  to compute.  The 
 1406 | following are examples of the various transformations that can occur: 
 1407 |  
 1408 |    (a) (x / y) / z               --->  x / (y * z) 
 1409 |    (b) (x / y) / (z / w)         --->  (x * w) / (y * z) 
 1410 |    (c) (2 * x) - (2 * y)         --->  2 * (x - y) 
 1411 |    (d) (2 / x) / (3 / y)         --->  (2 / 3) / (x * y) 
 1412 |    (e) (2 * x) * (3 * y)         --->  6 * (x * y) 
 1413 |    (f) (2 * x) * (2 - 4 / 2)     --->  0 
 1414 |    (g) (3 - 6 / 2) / (2 * x)     --->  0 
 1415 |    (h) avg(x,y,z) * (2 - 4 / 2)  --->  0 
 1416 |  
 1417 |  
 1418 | Note08: When using strength reduction in conjunction with  expressions 
 1419 | whose inputs or sub-expressions may result in values nearing either of 
 1420 | the bounds of the underlying  numeric type (eg: double), there  may be 
 1421 | the  possibility of a decrease in the precision of results. 
 1422 |  
 1423 | In  the following  example the  given expression  which represents  an 
 1424 | attempt at computing the average  between x and y will  be transformed 
 1425 | as follows: 
 1426 |  
 1427 |    (0.5 * x) + (y * 0.5) ---> 0.5 * (x + y) 
 1428 |  
 1429 | There  may be  situations where  the above  transformation will  cause 
 1430 | numerical overflows and  that the original  form of the  expression is 
 1431 | desired over the strength reduced form. In these situations it is best 
 1432 | to turn off strength reduction optimisations  or to use a type with  a 
 1433 | larger numerical bound. 
 1434 |  
 1435 |  
 1436 | (8) Stack And Node Depth Check 
 1437 | ExprTk  incorporates   a  recursive   descent  parser.   When  parsing 
 1438 | expressions comprising inner sub-expressions, the recursive nature  of 
 1439 | the parsing process causes the stack to grow. If the expression causes 
 1440 | the stack to grow  beyond the stack size  limit, this would lead  to a 
 1441 | stackoverflow  and  its  associated  stack  corruption  and   security 
 1442 | vulnerability issues. 
 1443 |  
 1444 | Similarly to parsing, evaluating an expression may cause the stack  to 
 1445 | grow. Such things like user defined functions, composite functions and 
 1446 | the general nature of the AST  being evaluated can cause the stack  to 
 1447 | grow,  and may  result in  potential stackoverflow  issues as  denoted 
 1448 | above. 
 1449 |  
 1450 | ExprTk provides a set of checks that prevent both of the above denoted 
 1451 | problems at  compile time.  These checks rely on  two specific  limits 
 1452 | being set on the parser settings instance, these limits are: 
 1453 |  
 1454 |    1. max_stack_depth (default: 400  ) 
 1455 |    2. max_node_depth  (default: 10000) 
 1456 |  
 1457 |  
 1458 | The following demonstrates how these two parser parameters can be set: 
 1459 |  
 1460 |    parser_t parser; 
 1461 |  
 1462 |    parser.settings().set_max_stack_depth(100); 
 1463 |    parser.settings().set_max_node_depth(200); 
 1464 |  
 1465 |  
 1466 | In  the  above  code, during  parsing if  the stack  depth reaches  or 
 1467 | exceeds  100 levels,  the parsing  process will  immediately halt  and 
 1468 | return with a failure.  Similarly, during synthesizing the  AST nodes, 
 1469 | if the  compilation process  detects an  AST tree  depth exceeding 200 
 1470 | levels the parsing process will halt and return a parsing failure. 
 1471 |  
 1472 |  
 1473 | (9) Vector Size Check 
 1474 | When defining an  expression local vector,  ExprTk uses a  default max 
 1475 | vector size of  two billion elements.  One may want  to limit the  max 
 1476 | vector size to be either smaller or larger than the specified  default 
 1477 | value. The max size value can be changed via the parser settings. 
 1478 |  
 1479 |    parser_t parser; 
 1480 |  
 1481 |    parser.settings().set_max_local_vector_size(1000000); 
 1482 |  
 1483 |    std::string expression1 = "var v[1e6] := [123]" 
 1484 |    std::string expression2 = "var v[1e9] := [123]" 
 1485 |  
 1486 |    expression_t expression; 
 1487 |  
 1488 |    parser.compile(expression1, expression); // compilation success 
 1489 |    parser.compile(expression2, expression); // compilation error 
 1490 |  
 1491 |  
 1492 | In the above  code, the max  local vector size  is set to  one million 
 1493 | elements. During  compilation  of an expression  if there is  a vector 
 1494 | definition  where  the  vector  size exceeds  the  max  vector  size a 
 1495 | compilation error shall be emitted. 
 1496 |  
 1497 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 1498 |  
 1499 | [SECTION 12 - EXPRESSION STRUCTURES] 
 1500 | Exprtk supports mathematical expressions in numerous forms based on  a 
 1501 | simple  imperative  programming  model. This  section  will  cover the 
 1502 | following  topics  related  to general  structure  and  programming of 
 1503 | expressions using ExprTk: 
 1504 |  
 1505 |    (1) Multi-Statement Expressions 
 1506 |    (2) Statements And Side-Effects 
 1507 |    (3) Conditional Statements 
 1508 |    (4) Special Functions 
 1509 |  
 1510 |  
 1511 | (1) Multi-Statement Expressions 
 1512 | Expressions in ExprTk can be comprised of one or more statements, which 
 1513 | may  sometimes  be  called  sub-expressions.  The  following  are  two 
 1514 | examples of expressions stored  in std::string variables, the  first a 
 1515 | single statement and the second a multi-statement expression: 
 1516 |  
 1517 |    std::string single_statement = " z := x + y " 
 1518 |  
 1519 |    std::string multi_statement  = " var temp := x; " 
 1520 |                                   " x := y + z;    " 
 1521 |                                   " y := temp;     " 
 1522 |  
 1523 |  
 1524 | In a  multi-statement expression,  the final  statement will determine 
 1525 | the overall result of the expression. In the following multi-statement 
 1526 | expression, the result of the expression when evaluated will be '2.3', 
 1527 | which will also be the value stored in the 'y' variable. 
 1528 |  
 1529 |    z := x + y; 
 1530 |    y := 2.3; 
 1531 |  
 1532 |  
 1533 | As  demonstrated  in  the  expression  above,  statements  within   an 
 1534 | expression are  separated using  the semi-colon  ';' operator.  In the 
 1535 | event  two  statements are  not  separated by  a  semi-colon, and  the 
 1536 | implied multiplication  feature is  active (enabled  by default),  the 
 1537 | compiler  will  assume  a  multiplication  operation  between  the two 
 1538 | statements. 
 1539 |  
 1540 | In the following example we have a multi-statement expression composed 
 1541 | of two variable definitions and initialisations for variables x and  y 
 1542 | and two seemingly separate mathematical operations. 
 1543 |  
 1544 |    var x:= 2; 
 1545 |    var y:= 3; 
 1546 |    x + 1 
 1547 |    y * 2 
 1548 |  
 1549 |  
 1550 | However the result of  the expression will not  be 6 as may  have been 
 1551 | assumed based on  the calculation of  'y * 2',  but rather the  result 
 1552 | will be 8. This  is because the compiler  will have conjoined the  two 
 1553 | mathematical statements into one  via a multiplication operation.  The 
 1554 | expression when compiled will actually evaluate as the following: 
 1555 |  
 1556 |    var x:= 2; 
 1557 |    var y:= 3; 
 1558 |    x + 1 * y * 2;   // 2 + 1 * 3 * 2 == 8 
 1559 |  
 1560 |  
 1561 | In ExprTk any valid statement  will itself return a value.  This value 
 1562 | can  further  be  used  in  conjunction  with  other  statements. This 
 1563 | includes language structures such as if-statements, loops (for, while) 
 1564 | and the switch statement. Typically the last statement executed in the 
 1565 | given construct  (conditional, loop  etc), will  be the  value that is 
 1566 | returned. 
 1567 |  
 1568 | In the following example, the  return value of the expression  will be 
 1569 | 11, which is the sum of the variable 'x' and the final value  computed 
 1570 | within the loop body upon its last iteration: 
 1571 |  
 1572 |    var x := 1; 
 1573 |    x + for (var i := x; i < 10; i += 1) 
 1574 |        { 
 1575 |           i / 2; 
 1576 |           i + 1; 
 1577 |        } 
 1578 |  
 1579 |  
 1580 | (2) Statements And Side-Effects 
 1581 | Statements themselves may have side effects, which in-turn affect  the 
 1582 | proceeding statements in multi-statement expressions. 
 1583 |  
 1584 | A statement is said  to have a side-effect  if it causes the  state of 
 1585 | the  expression to  change in  some way  -  this  includes but  is not 
 1586 | limited to the  modification of the  state of external  variables used 
 1587 | within the expression. Currently  the following actions being  present 
 1588 | in a statement will cause it to have a side-effect: 
 1589 |  
 1590 |    (a) Assignment operation (explicit or potentially) 
 1591 |    (b) Invoking a user-defined function that has side-effects 
 1592 |  
 1593 | The following are examples of expressions where the side-effect status 
 1594 | of the  statements (sub-expressions) within the expressions  have been 
 1595 | noted: 
 1596 |  
 1597 |   +-+----------------------+------------------------------+ 
 1598 |   |#|      Expression      |      Side Effect Status      | 
 1599 |   +-+----------------------+------------------------------+ 
 1600 |   |0| x + y                | False                        | 
 1601 |   +-+----------------------+------------------------------+ 
 1602 |   |1| z := x + y           | True - Due to assignment     | 
 1603 |   +-+----------------------+------------------------------+ 
 1604 |   |2| abs(x - y)           | False                        | 
 1605 |   +-+----------------------+------------------------------+ 
 1606 |   |3| abs(x - y);          | False                        | 
 1607 |   | | z := (x += y);       | True - Due to assignments    | 
 1608 |   +-+----------------------+------------------------------+ 
 1609 |   |4| abs(x - y);          | False                        | 
 1610 |   | | z := (x += y);       | True - Due to assignments    | 
 1611 |   +-+----------------------+------------------------------+ 
 1612 |   |5| var t := abs(x - y); | True - Due to initialisation | 
 1613 |   | | t + x;               | False                        | 
 1614 |   | | z := (x += y);       | True - Due to assignments    | 
 1615 |   +-+----------------------+------------------------------+ 
 1616 |   |6| foo(x - y)           | True - user defined function | 
 1617 |   +-+----------------------+------------------------------+ 
 1618 |  
 1619 |  
 1620 | Note09: In example  6 from  the above  set, it  is  assumed  the  user 
 1621 | defined function foo has been  registered as having a side-effect.  By 
 1622 | default all user defined  functions are assumed to  have side-effects, 
 1623 | unless they  are configured  in their  constructors to  not have side- 
 1624 | effects using the  'disable_has_side_effects' free function.  For more 
 1625 | information review Section 15  - User Defined Functions  sub-section 7 
 1626 | Function Side-Effects. 
 1627 |  
 1628 | At this point we  can see that there  will be expressions composed  of 
 1629 | certain kinds  of statements  that when  executed will  not affect the 
 1630 | nature  of the  expression's  result.  These statements  are typically 
 1631 | called 'dead code'.  These statements though  not affecting the  final 
 1632 | result will still be executed and as such they will consume processing 
 1633 | time that could otherwise be saved. As such ExprTk attempts to  detect 
 1634 | and remove such statements from expressions. 
 1635 |  
 1636 | The  'Dead  Code  Elimination' (DCE)  optimisation  process,  which is 
 1637 | enabled by default, will remove any statements that are determined  to 
 1638 | not have a side-effect in a multi-statement expression, excluding  the 
 1639 | final or last statement. 
 1640 |  
 1641 | By default the final statement in an expression will always be present 
 1642 | regardless of  its side-effect  status, as  it is  the statement whose 
 1643 | value shall be used as the result of the expression. 
 1644 |  
 1645 | In order to further explain the actions taken during the DCE  process, 
 1646 | lets review the following expression: 
 1647 |  
 1648 |    var x := 2;      // Statement 1 
 1649 |    var y := x + 2;  // Statement 2 
 1650 |    x + y;           // Statement 3 
 1651 |    y := x + 3y;     // Statement 4 
 1652 |    x - y;           // Statement 5 
 1653 |  
 1654 |  
 1655 | The above expression has five statements.  Three of them (1, 2 and  4) 
 1656 | actively have side-effects. The first two are variable declaration and 
 1657 | initialisations, where as the third is due to an assignment operation. 
 1658 | There  are  two  statements (3  and 5),  that do  not explicitly  have 
 1659 | side-effects, however the latter, statement 5, is the final  statement 
 1660 | in the expression and hence will be assumed to have a side-effect. 
 1661 |  
 1662 | During compilation when the DCE  optimisation is applied to the  above 
 1663 | expression, statement 3 will be removed from the expression, as it has 
 1664 | no  bearing  on  the  final result  of  expression,  the  rest of  the 
 1665 | statements will all remain. The optimised form of the expression is as 
 1666 | follows: 
 1667 |  
 1668 |    var x := 2;      // Statement 1 
 1669 |    var y := x + 2;  // Statement 2 
 1670 |    y := x + 3y;     // Statement 3 
 1671 |    x - y;           // Statement 4 
 1672 |  
 1673 |  
 1674 | (3) Conditional Statements (If-Then-Else) 
 1675 | ExprTk supports two forms  of conditional branching or otherwise known 
 1676 | as  if-statements.  The  first  form,  is  a  simple  function   based 
 1677 | conditional  statement, that  takes exactly  three input  expressions: 
 1678 | condition, consequent  and alternative.  The following  is an  example 
 1679 | expression that utilises the function based if-statement. 
 1680 |  
 1681 |    x := if (y < z, y + 1, 2 * z) 
 1682 |  
 1683 |  
 1684 | In the  example above,  if the  condition 'y  < z'  is true,  then the 
 1685 | consequent 'y + 1' will be evaluated, its value shall be  returned and 
 1686 | subsequently assigned to the  variable 'x'. Otherwise the  alternative 
 1687 | '2 *  z' will  be evaluated  and its  value will  be returned. This is 
 1688 | essentially the  simplest form of  an if-then-else statement. A simple 
 1689 | variation of  the expression  where the  value of  the if-statement is 
 1690 | used within another statement is as follows: 
 1691 |  
 1692 |    x := 3 * if (y < z, y + 1, 2 * z) / 2 
 1693 |  
 1694 |  
 1695 | The second form of if-statement resembles the standard syntax found in 
 1696 | most imperative languages. There are two variations of the statement: 
 1697 |  
 1698 |    (a) If-Statement 
 1699 |    (b) If-Then-Else Statement 
 1700 |  
 1701 |  
 1702 | (a) If-Statement 
 1703 | This version  of the  conditional statement  returns the  value of the 
 1704 | consequent expression when the  condition expression is true,  else it 
 1705 | will return a quiet NaN value as its result. 
 1706 |  
 1707 |    Example 1: 
 1708 |    x := if (y < z) y + 3; 
 1709 |  
 1710 |    Example 2: 
 1711 |    x := if (y < z) 
 1712 |         { 
 1713 |            y + 3 
 1714 |         }; 
 1715 |  
 1716 | The two  example expressions  above are  equivalent. If  the condition 
 1717 | 'y < z' is true, the 'x' variable shall be  assigned the value of  the 
 1718 | consequent 'y + 3', otherwise it  will be assigned the value of  quiet 
 1719 | NaN.  As  previously  discussed,  if-statements  are  value  returning 
 1720 | constructs, and if  not properly terminated  using a semi-colon,  will 
 1721 | end-up  combining  with  the  next  statement  via  a   multiplication 
 1722 | operation. The following example will NOT result in the expected value 
 1723 | of 'w + x' being returned: 
 1724 |  
 1725 |    x := if (y < z) y + 3  // missing semi-colon ';' 
 1726 |    w + x 
 1727 |  
 1728 |  
 1729 | When the  above supposed  multi-statement expression  is compiled, the 
 1730 | expression  will  have  a  multiplication  inserted  between  the  two 
 1731 | 'intended' statements resulting in the unanticipated expression: 
 1732 |  
 1733 |    x := (if (y < z) y + 3) * w + x 
 1734 |  
 1735 |  
 1736 | The  solution  to  the  above situation  is  to  simply  terminate the 
 1737 | conditional statement with a semi-colon as follows: 
 1738 |  
 1739 |    x := if (y < z) y + 3; 
 1740 |    w + x 
 1741 |  
 1742 |  
 1743 | (b) If-Then-Else Statement 
 1744 | The second variation of  the if-statement is to  allow for the use  of 
 1745 | Else and Else-If cascading statements. Examples of such statements are 
 1746 | as follows: 
 1747 |  
 1748 |  Example 1:             Example 2:         Example 3: 
 1749 |  if (x < y)             if (x < y)         if (x > y + 1) 
 1750 |     z := x + 3;         {                     y := abs(x - z); 
 1751 |  else                      y := z + x;     else 
 1752 |     y := x - z;            z := x + 3;     { 
 1753 |                         }                     y := z + x; 
 1754 |                         else                  z := x + 3; 
 1755 |                            y := x - z;     }; 
 1756 |  
 1757 |  
 1758 |  Example 4:             Example 5:         Example 6: 
 1759 |  if (2 * x < max(y,3))  if (x < y)         if (x < y or (x + z) > y) 
 1760 |  {                         z := x + 3;     { 
 1761 |     y := z + x;         else if (2y != z)     z := x + 3; 
 1762 |     z := x + 3;         {                     y := x - z; 
 1763 |  }                         z := x + 3;     } 
 1764 |  else if (2y - z)          y := x - z;     else if (abs(2y - z) >= 3) 
 1765 |     y := x - z;         }                     y := x - z; 
 1766 |                         else               else 
 1767 |                            x * x;          { 
 1768 |                                               z := abs(x * x); 
 1769 |                                               x * y * z; 
 1770 |                                            }; 
 1771 |  
 1772 |  
 1773 | In  the case  where  there  is no  final else  statement and  the flow 
 1774 | through the conditional  arrives at this  final point, the  same rules 
 1775 | apply to this form of if-statement as to the previous. That is a quiet 
 1776 | NaN shall be returned as the  result of the  if-statement. Furthermore 
 1777 | the same requirements of  terminating the statement with  a semi-colon 
 1778 | apply. 
 1779 |  
 1780 | (4) Special Functions 
 1781 | The purpose  of special  functions in  ExprTk is  to provide  compiler 
 1782 | generated equivalents of common mathematical expressions which can  be 
 1783 | invoked by  using the  'special function'  syntax (eg:  $f12(x,y,z) or 
 1784 | $f82(x,y,z,w)). 
 1785 |  
 1786 | Special functions dramatically decrease  the total evaluation time  of 
 1787 | expressions which would otherwise  have been written using  the common 
 1788 | form by reducing the total number  of nodes in the evaluation tree  of 
 1789 | an  expression  and  by  also  leveraging  the  compiler's  ability to 
 1790 | correctly optimise such expressions for a given architecture. 
 1791 |  
 1792 |           3-Parameter                       4-Parameter 
 1793 |  +-------------+-------------+    +--------------+------------------+ 
 1794 |  |  Prototype  |  Operation  |    |  Prototype   |    Operation     | 
 1795 |  +-------------+-------------+    +--------------+------------------+ 
 1796 |    $f00(x,y,z) | (x + y) / z       $f48(x,y,z,w) | x + ((y + z) / w) 
 1797 |    $f01(x,y,z) | (x + y) * z       $f49(x,y,z,w) | x + ((y + z) * w) 
 1798 |    $f02(x,y,z) | (x + y) - z       $f50(x,y,z,w) | x + ((y - z) / w) 
 1799 |    $f03(x,y,z) | (x + y) + z       $f51(x,y,z,w) | x + ((y - z) * w) 
 1800 |    $f04(x,y,z) | (x - y) + z       $f52(x,y,z,w) | x + ((y * z) / w) 
 1801 |    $f05(x,y,z) | (x - y) / z       $f53(x,y,z,w) | x + ((y * z) * w) 
 1802 |    $f06(x,y,z) | (x - y) * z       $f54(x,y,z,w) | x + ((y / z) + w) 
 1803 |    $f07(x,y,z) | (x * y) + z       $f55(x,y,z,w) | x + ((y / z) / w) 
 1804 |    $f08(x,y,z) | (x * y) - z       $f56(x,y,z,w) | x + ((y / z) * w) 
 1805 |    $f09(x,y,z) | (x * y) / z       $f57(x,y,z,w) | x - ((y + z) / w) 
 1806 |    $f10(x,y,z) | (x * y) * z       $f58(x,y,z,w) | x - ((y + z) * w) 
 1807 |    $f11(x,y,z) | (x / y) + z       $f59(x,y,z,w) | x - ((y - z) / w) 
 1808 |    $f12(x,y,z) | (x / y) - z       $f60(x,y,z,w) | x - ((y - z) * w) 
 1809 |    $f13(x,y,z) | (x / y) / z       $f61(x,y,z,w) | x - ((y * z) / w) 
 1810 |    $f14(x,y,z) | (x / y) * z       $f62(x,y,z,w) | x - ((y * z) * w) 
 1811 |    $f15(x,y,z) | x / (y + z)       $f63(x,y,z,w) | x - ((y / z) / w) 
 1812 |    $f16(x,y,z) | x / (y - z)       $f64(x,y,z,w) | x - ((y / z) * w) 
 1813 |    $f17(x,y,z) | x / (y * z)       $f65(x,y,z,w) | ((x + y) * z) - w 
 1814 |    $f18(x,y,z) | x / (y / z)       $f66(x,y,z,w) | ((x - y) * z) - w 
 1815 |    $f19(x,y,z) | x * (y + z)       $f67(x,y,z,w) | ((x * y) * z) - w 
 1816 |    $f20(x,y,z) | x * (y - z)       $f68(x,y,z,w) | ((x / y) * z) - w 
 1817 |    $f21(x,y,z) | x * (y * z)       $f69(x,y,z,w) | ((x + y) / z) - w 
 1818 |    $f22(x,y,z) | x * (y / z)       $f70(x,y,z,w) | ((x - y) / z) - w 
 1819 |    $f23(x,y,z) | x - (y + z)       $f71(x,y,z,w) | ((x * y) / z) - w 
 1820 |    $f24(x,y,z) | x - (y - z)       $f72(x,y,z,w) | ((x / y) / z) - w 
 1821 |    $f25(x,y,z) | x - (y / z)       $f73(x,y,z,w) | (x * y) + (z * w) 
 1822 |    $f26(x,y,z) | x - (y * z)       $f74(x,y,z,w) | (x * y) - (z * w) 
 1823 |    $f27(x,y,z) | x + (y * z)       $f75(x,y,z,w) | (x * y) + (z / w) 
 1824 |    $f28(x,y,z) | x + (y / z)       $f76(x,y,z,w) | (x * y) - (z / w) 
 1825 |    $f29(x,y,z) | x + (y + z)       $f77(x,y,z,w) | (x / y) + (z / w) 
 1826 |    $f30(x,y,z) | x + (y - z)       $f78(x,y,z,w) | (x / y) - (z / w) 
 1827 |    $f31(x,y,z) | x * y^2 + z       $f79(x,y,z,w) | (x / y) - (z * w) 
 1828 |    $f32(x,y,z) | x * y^3 + z       $f80(x,y,z,w) | x / (y + (z * w)) 
 1829 |    $f33(x,y,z) | x * y^4 + z       $f81(x,y,z,w) | x / (y - (z * w)) 
 1830 |    $f34(x,y,z) | x * y^5 + z       $f82(x,y,z,w) | x * (y + (z * w)) 
 1831 |    $f35(x,y,z) | x * y^6 + z       $f83(x,y,z,w) | x * (y - (z * w)) 
 1832 |    $f36(x,y,z) | x * y^7 + z       $f84(x,y,z,w) | x*y^2 + z*w^2 
 1833 |    $f37(x,y,z) | x * y^8 + z       $f85(x,y,z,w) | x*y^3 + z*w^3 
 1834 |    $f38(x,y,z) | x * y^9 + z       $f86(x,y,z,w) | x*y^4 + z*w^4 
 1835 |    $f39(x,y,z) | x * log(y)+z      $f87(x,y,z,w) | x*y^5 + z*w^5 
 1836 |    $f40(x,y,z) | x * log(y)-z      $f88(x,y,z,w) | x*y^6 + z*w^6 
 1837 |    $f41(x,y,z) | x * log10(y)+z    $f89(x,y,z,w) | x*y^7 + z*w^7 
 1838 |    $f42(x,y,z) | x * log10(y)-z    $f90(x,y,z,w) | x*y^8 + z*w^8 
 1839 |    $f43(x,y,z) | x * sin(y)+z      $f91(x,y,z,w) | x*y^9 + z*w^9 
 1840 |    $f44(x,y,z) | x * sin(y)-z      $f92(x,y,z,w) | (x and y) ? z : w 
 1841 |    $f45(x,y,z) | x * cos(y)+z      $f93(x,y,z,w) | (x or  y) ? z : w 
 1842 |    $f46(x,y,z) | x * cos(y)-z      $f94(x,y,z,w) | (x <   y) ? z : w 
 1843 |    $f47(x,y,z) | x ? y : z         $f95(x,y,z,w) | (x <=  y) ? z : w 
 1844 |                                    $f96(x,y,z,w) | (x >   y) ? z : w 
 1845 |                                    $f97(x,y,z,w) | (x >=  y) ? z : w 
 1846 |                                    $f98(x,y,z,w) | (x ==  y) ? z : w 
 1847 |                                    $f99(x,y,z,w) | x*sin(y)+z*cos(w) 
 1848 |  
 1849 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 1850 |  
 1851 | [SECTION 13 - VARIABLE, VECTOR & STRING DEFINITION] 
 1852 | ExprTk supports the definition of expression local variables,  vectors 
 1853 | and  strings.  The definitions  must  be unique  as  shadowing is  not 
 1854 | allowed and object lifetimes are based  on scope. Definitions use  the 
 1855 | following general form: 
 1856 |  
 1857 |    var <name> := <initialiser>; 
 1858 |  
 1859 | (1) Variable Definition 
 1860 | Variables are  of numeric  type denoting  a single  value. They can be 
 1861 | explicitly initialised to a value, otherwise they will be defaulted to 
 1862 | zero. The following are examples of variable definitions: 
 1863 |  
 1864 |    (a) Initialise x to zero 
 1865 |        var x; 
 1866 |  
 1867 |    (b) Initialise y to three 
 1868 |        var y := 3; 
 1869 |  
 1870 |    (c) Initialise z to the expression 
 1871 |        var z := if (max(1, x + y) > 2, w, v); 
 1872 |  
 1873 |    (d) Initialise const literal n 
 1874 |        var n := 12 / 3; 
 1875 |  
 1876 |  
 1877 | (2) Vector Definition 
 1878 | Vectors are arrays of a common numeric type. The elements in a  vector 
 1879 | can be explicitly initialised, otherwise they will all be defaulted to 
 1880 | zero. The following are examples of vector definitions: 
 1881 |  
 1882 |    (a) Initialise all values to zero 
 1883 |        var x[3]; 
 1884 |  
 1885 |    (b) Initialise all values to zero 
 1886 |        var x[3] := {}; 
 1887 |  
 1888 |    (c) Initialise all values to given value or expression 
 1889 |        var x[3]   := [ 42 ]; 
 1890 |        var y[x[]] := [ 123 + 3y + sin(w / z) ]; 
 1891 |  
 1892 |    (d) Initialise all values iota style 
 1893 |        var v[4] := [ 0 : +1];  //  0,  1,  2,  3 
 1894 |        var v[5] := [-3 : -2];  // -3, -5, -7, -9, -11 
 1895 |  
 1896 |    (e) Initialise the first two values, all other elements to zero 
 1897 |        var x[3] := { (1 + x[2]) / x[], (sin(y[0] / x[]) + 3) / x[] }; 
 1898 |  
 1899 |    (f) Initialise the first three (all) values 
 1900 |        const var size := 3; 
 1901 |        var x[size] := { 1, 2, 3 }; 
 1902 |  
 1903 |    (g) Initialise vector from a vector 
 1904 |        var x[4] := { 1, 2, 3, 4 }; 
 1905 |        var y[3] := x; 
 1906 |        var w[5] := { 1, 2 }; // 1, 2, 0, 0, 0 
 1907 |  
 1908 |    (h) Initialise vector from a smaller vector 
 1909 |        var x[3] := { 1, 2, 3 }; 
 1910 |        var y[5] := x;   // 1, 2, 3, ??, ?? 
 1911 |  
 1912 |    (i) Non-initialised vector 
 1913 |        var x[3] := null; // ?? ?? ?? 
 1914 |  
 1915 |    (j) Error as there are too many initialisers 
 1916 |        var x[3] := { 1, 2, 3, 4 }; 
 1917 |  
 1918 |    (k) Error as a vector of size zero is not allowed. 
 1919 |        var x[0]; 
 1920 |  
 1921 |  
 1922 | (3) String Definition 
 1923 | Strings are sequences comprised of 8-bit characters. They can only be 
 1924 | defined  with an explicit  initialisation  value. The  following  are 
 1925 | examples of string variable definitions: 
 1926 |  
 1927 |    (a) Initialise to a string 
 1928 |        var x := 'abc'; 
 1929 |  
 1930 |    (b) Initialise to an empty string 
 1931 |        var x := ''; 
 1932 |  
 1933 |    (c) Initialise to a string expression 
 1934 |        var x := 'abc' + '123'; 
 1935 |  
 1936 |    (d) Initialise to a string range 
 1937 |        var x := 'abc123'[2:4]; 
 1938 |  
 1939 |    (e) Initialise to another string variable 
 1940 |        var x := 'abc'; 
 1941 |        var y := x; 
 1942 |  
 1943 |    (f) Initialise to another string variable range 
 1944 |        var x := 'abc123'; 
 1945 |        var y := x[2:4]; 
 1946 |  
 1947 |    (g) Initialise to a string expression 
 1948 |        var x := 'abc'; 
 1949 |        var y := x + '123'; 
 1950 |  
 1951 |    (h) Initialise to a string expression range 
 1952 |        var x := 'abc'; 
 1953 |        var y := (x + '123')[1:3]; 
 1954 |  
 1955 |  
 1956 | (4) Return Value 
 1957 | Variable and vector  definitions have a  return value. In  the case of 
 1958 | variable definitions, the value  to which the variable  is initialised 
 1959 | will be returned. Where as for vectors, the value of the first element 
 1960 | (eg: v[0]) shall be returned. 
 1961 |  
 1962 |    8 == ((var x := 7;) + 1) 
 1963 |    4 == (var y[3] := {4, 5, 6};) 
 1964 |  
 1965 |  
 1966 | (5) Variable/Vector Assignment 
 1967 | The value of a variable can be assigned to a vector and a vector or  a 
 1968 | vector expression can be assigned to a variable. 
 1969 |  
 1970 |   (a) Variable To Vector: 
 1971 |       Every element of the vector is assigned the value of the variable 
 1972 |       or expression. 
 1973 |       var x    := 3; 
 1974 |       var y[3] := { 1, 2, 3 }; 
 1975 |       y := x + 1; 
 1976 |  
 1977 |   (b) Vector To Variable: 
 1978 |       The variable is assigned the value of the first element of the 
 1979 |       vector (aka vec[0]) 
 1980 |       var x    := 3; 
 1981 |       var y[3] := { 1, 2, 3 }; 
 1982 |       x := y + 1; 
 1983 |  
 1984 |  
 1985 | Note10: During the expression compilation phase, tokens are classified 
 1986 | based on the following priorities: 
 1987 |  
 1988 |    (a) Reserved keywords or operators (+, -, and, or, etc) 
 1989 |    (b) Base functions (abs, sin, cos, min, max etc) 
 1990 |    (c) Symbol table variables 
 1991 |    (d) Expression local defined variables 
 1992 |    (e) Symbol table functions 
 1993 |    (f) Unknown symbol resolver based variables 
 1994 |  
 1995 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 1996 |  
 1997 | [SECTION 14 - VECTOR PROCESSING] 
 1998 | ExprTk  provides  support  for   various  forms  of  vector   oriented 
 1999 | arithmetic, inequalities and  processing. The various  supported pairs 
 2000 | are as follows: 
 2001 |  
 2002 |    (a) vector and vector (eg: v0 + v1) 
 2003 |    (b) vector and scalar (eg: v  + 33) 
 2004 |    (c) scalar and vector (eg: 22 *  v) 
 2005 |  
 2006 | The following is a list of operations that can be used in  conjunction 
 2007 | with vectors: 
 2008 |  
 2009 |    (a) Arithmetic:       +, -, *, /, % 
 2010 |    (b) Exponentiation:   vector ^ scalar 
 2011 |    (c) Assignment:       :=, +=, -=, *=, /=, %=, <=> 
 2012 |    (d) Inequalities:     <, <=, >, >=, ==, =, equal 
 2013 |    (e) Boolean logic:    and, nand, nor, or, xnor, xor 
 2014 |    (f) Unary operations: 
 2015 |        abs, acos, acosh, asin, asinh, atan, atanh, ceil, cos,  cosh, 
 2016 |        cot, csc,  deg2grad, deg2rad,  erf, erfc,  exp, expm1, floor, 
 2017 |        frac, grad2deg, log, log10, log1p, log2, rad2deg, round, sec, 
 2018 |        sgn, sin, sinc, sinh, sqrt, swap, tan, tanh, trunc, 
 2019 |        thresholding 
 2020 |    (g) Aggregate and Reduce operations: 
 2021 |        avg, max, min, mul,  dot, dotk, sum, sumk,  count, all_true, 
 2022 |        all_false, any_true, any_false 
 2023 |    (h) Transformation operations: 
 2024 |        copy, diff, reverse, rotate-left/right, shift-left/right, sort, 
 2025 |        nth_element 
 2026 |    (i) BLAS-L1: 
 2027 |        axpy, axpby, axpyz, axpbyz, axpbz 
 2028 |  
 2029 | Note11: When one of the above  described operations is being performed 
 2030 | between two  vectors, the  operation will  only span  the size  of the 
 2031 | smallest vector.  The elements  of the  larger vector  outside of  the 
 2032 | range will  not be included. The  operation  itself will  be processed 
 2033 | element-wise over values of the smaller of the two ranges. 
 2034 |  
 2035 | The  following  simple  example  demonstrates  the  vector  processing 
 2036 | capabilities by computing the dot-product of the vectors v0 and v1 and 
 2037 | then assigning it to the variable v0dotv1: 
 2038 |  
 2039 |    var v0[3] := { 1, 2, 3 }; 
 2040 |    var v1[3] := { 4, 5, 6 }; 
 2041 |    var v0dotv1 := sum(v0 * v1); 
 2042 |  
 2043 |  
 2044 | The following is a for-loop based implementation that is equivalent to 
 2045 | the previously mentioned dot-product computation expression: 
 2046 |  
 2047 |    var v0[3] := { 1, 2, 3 }; 
 2048 |    var v1[3] := { 4, 5, 6 }; 
 2049 |    var v0dotv1; 
 2050 |  
 2051 |    for (var i := 0; i < min(v0[],v1[]); i += 1) 
 2052 |    { 
 2053 |       v0dotv1 += (v0[i] * v1[i]); 
 2054 |    } 
 2055 |  
 2056 |  
 2057 | Note12: When the aggregate or reduction  operations denoted above  are 
 2058 | used  in conjunction with a  vector or  vector  expression, the return 
 2059 | value is not a vector but rather a single value. 
 2060 |  
 2061 |    var x[3] := { 1, 2, 3 }; 
 2062 |  
 2063 |    sum(x)      ==  6 
 2064 |    sum(1 + 2x) == 15 
 2065 |    avg(3x + 1) ==  7 
 2066 |    min(1 / x)  == (1 / 3) 
 2067 |    max(x / 2)  == (3 / 2) 
 2068 |    sum(x > 0 and x < 5) == x[] 
 2069 |  
 2070 |  
 2071 | When utilising external user defined  vectors via the symbol table  as 
 2072 | opposed to expression local defined vectors, the typical  'add_vector' 
 2073 | method from the symbol table will register the entirety of the  vector 
 2074 | that is passed. The following example attempts to evaluate the sum  of 
 2075 | elements of  the external  user defined  vector within  a typical  yet 
 2076 | trivial expression: 
 2077 |  
 2078 |    const std::string reduce_program = " sum(2 * v + 1) " 
 2079 |  
 2080 |    std::vector<T> v0 { T(1.1), T(2.2), ..... , T(99.99) }; 
 2081 |  
 2082 |    symbol_table_t symbol_table; 
 2083 |    symbol_table.add_vector("v",v); 
 2084 |  
 2085 |    expression_t expression; 
 2086 |    expression.register_symbol_table(symbol_table); 
 2087 |  
 2088 |    parser_t parser; 
 2089 |    parser.compile(reduce_program,expression); 
 2090 |  
 2091 |    T sum = expression.value(); 
 2092 |  
 2093 |  
 2094 | For the most part, this is  a very common use-case. However there  may 
 2095 | be situations where one may want to evaluate the same vector  oriented 
 2096 | expression many times over, but using different vectors or sub  ranges 
 2097 | of the same vector of the same size to that of the original upon every 
 2098 | evaluation. 
 2099 |  
 2100 | The usual solution is to  either recompile the expression for  the new 
 2101 | vector instance, or to  copy the contents from  the new vector to  the 
 2102 | symbol table registered vector  and then perform the  evaluation. When 
 2103 | the  vectors are  large or  the re-evaluation  attempts are  numerous, 
 2104 | these  solutions  can  become  rather  time  consuming  and  generally 
 2105 | inefficient. 
 2106 |  
 2107 |    std::vector<T> v1 { T(2.2), T(2.2), ..... , T(2.2) }; 
 2108 |    std::vector<T> v2 { T(3.3), T(3.3), ..... , T(3.3) }; 
 2109 |    std::vector<T> v3 { T(4.4), T(4.4), ..... , T(4.4) }; 
 2110 |  
 2111 |    std::vector<std::vector<T>> vv { v1, v2, v3 }; 
 2112 |    ... 
 2113 |    T sum = T(0); 
 2114 |  
 2115 |    for (auto& new_vec : vv) 
 2116 |    { 
 2117 |       v = new_vec; // update vector 
 2118 |       sum += expression.value(); 
 2119 |    } 
 2120 |  
 2121 |  
 2122 | A  solution  to  the  above  'efficiency'  problem,  is  to  use   the 
 2123 | exprtk::vector_view  object. The  vector_view is  instantiated with  a 
 2124 | size and backing based upon a vector. Upon evaluations if the  backing 
 2125 | needs  to  be  'updated' to  either another  vector or  sub-range, the 
 2126 | vector_view instance  can be  efficiently rebased,  and the expression 
 2127 | evaluated as normal. 
 2128 |  
 2129 |    exprtk::vector_view<T> view = exprtk::make_vector_view(v,v.size()); 
 2130 |  
 2131 |    symbol_table_t symbol_table; 
 2132 |    symbol_table.add_vector("v",view); 
 2133 |  
 2134 |    ... 
 2135 |  
 2136 |    T sum = T(0); 
 2137 |  
 2138 |    for (auto& new_vec : vv) 
 2139 |    { 
 2140 |       view.rebase(new_vec.data()); // update vector 
 2141 |       sum += expression.value(); 
 2142 |    } 
 2143 |  
 2144 |  
 2145 | Another useful feature of exprtk::vector_view is that all such vectors 
 2146 | can have  their sizes  modified (or  "resized"). The  resizing of  the 
 2147 | associated vectors can happen either between or during evaluations. 
 2148 |  
 2149 |    std::vector<T> v = { 1, 2, 3, 4, 5, 6, 7, 8 }; 
 2150 |    exprtk::vector_view<T> view = exprtk::make_vector_view(v,v.size()); 
 2151 |  
 2152 |    symbol_table_t symbol_table; 
 2153 |    symbol_table.add_vector("v",view); 
 2154 |  
 2155 |    const std::string expression_string = "v[]" 
 2156 |  
 2157 |    expression_t expression; 
 2158 |    expression.register_symbol_table(symbol_table); 
 2159 |  
 2160 |    parser_t parser; 
 2161 |    parser.compile(expression_string, expression); 
 2162 |  
 2163 |    for (std::size_t i = 1; i <= v.size(); ++i) 
 2164 |    { 
 2165 |       vv.set_size(i); 
 2166 |       expression.value(); 
 2167 |    } 
 2168 |  
 2169 |  
 2170 | In the example above, a vector_view is instantiated with a std::vector 
 2171 | instance with eight elements and registered to the given symbol_table. 
 2172 | An expression is then compiled,  which in this case simply returns the 
 2173 | size of the vector at that point in time. The expression is  evaluated 
 2174 | eight times (size of vector times), where upon each iteration the size 
 2175 | of the vector is changed with values ranging from one to eight. 
 2176 |  
 2177 | Note13: When modifying the size of  a vector, the  new size must be at 
 2178 | least one  or larger  and must  not exceed  the original  size of  the 
 2179 | vector_view when it was instantiated. 
 2180 |  
 2181 | Note14: The  lifetime  of  any  parser,  symbol_table   or  expression 
 2182 | instance must  not exceed  that of  any vector_view  instance that has 
 2183 | been registered  with it.  Furthermore the  lifetime of  a vector_view 
 2184 | must not exceed that of the underlying vector instance it is 
 2185 | associated with. 
 2186 |  
 2187 | Note15: In a multi-threaded context the  rebase function should not be 
 2188 | called during associated expression  evaluation, as this will  lead to 
 2189 | undefined behaviour (eg: torn reads and writes). 
 2190 |  
 2191 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 2192 |  
 2193 | [SECTION 15 - USER DEFINED FUNCTIONS] 
 2194 | ExprTk provides a means  whereby custom functions can  be defined  and 
 2195 | utilised within  expressions.  The   concept  requires  the  user   to 
 2196 | provide a reference  to the function  coupled with an  associated name 
 2197 | that  will be invoked within  expressions. Functions may take numerous 
 2198 | inputs but will always return a single value of the underlying numeric 
 2199 | type. 
 2200 |  
 2201 | During  expression  compilation  when required  the  reference  to the 
 2202 | function  shall be obtained from  the associated  symbol_table and  be 
 2203 | embedded into the expression. 
 2204 |  
 2205 | There are five types of function interface: 
 2206 |  
 2207 |   +---+----------------------+--------------+----------------------+ 
 2208 |   | # |         Name         | Return Type  | Input Types          | 
 2209 |   +---+----------------------+--------------+----------------------+ 
 2210 |   | 1 | ifunction            | Scalar       | Scalar               | 
 2211 |   | 2 | ivararg_function     | Scalar       | Scalar               | 
 2212 |   | 3 | igeneric_function    | Scalar       | Scalar,Vector,String | 
 2213 |   | 4 | igeneric_function II | String       | Scalar,Vector,String | 
 2214 |   | 5 | igeneric_function III| String/Scalar| Scalar,Vector,String | 
 2215 |   | 6 | function_compositor  | Scalar       | Scalar               | 
 2216 |   +---+----------------------+--------------+----------------------+ 
 2217 |  
 2218 | (1) ifunction 
 2219 | This interface supports zero to 20 input parameters of only the scalar 
 2220 | type (numbers). The  usage requires a custom function be  derived from 
 2221 | ifunction and to override one of the 21 function operators. As part of 
 2222 | the constructor the custom function will define how many parameters it 
 2223 | expects  to  handle.  The  following  example  defines  a  3 parameter 
 2224 | function called 'foo': 
 2225 |  
 2226 |    template <typename T> 
 2227 |    struct foo final : public exprtk::ifunction<T> 
 2228 |    { 
 2229 |       foo() : exprtk::ifunction<T>(3) 
 2230 |       {} 
 2231 |  
 2232 |       T operator()(const T& v1, const T& v2, const T& v3) override 
 2233 |       { 
 2234 |          return T(1) + (v1 * v2) / T(v3); 
 2235 |       } 
 2236 |    }; 
 2237 |  
 2238 |  
 2239 | (2) ivararg_function 
 2240 | This interface supports a variable number of scalar arguments as input 
 2241 | into the function. The function operator interface uses a  std::vector 
 2242 | specialised upon type T to facilitate parameter passing. The following 
 2243 | example defines a vararg function called 'boo': 
 2244 |  
 2245 |    template <typename T> 
 2246 |    struct boo final : public exprtk::ivararg_function<T> 
 2247 |    { 
 2248 |       inline T operator()(const std::vector<T>& arglist) override 
 2249 |       { 
 2250 |          T result = T(0); 
 2251 |  
 2252 |          for (std::size_t i = 0; i < arglist.size(); ++i) 
 2253 |          { 
 2254 |             result += arglist[i] / arglist[i > 0 ? (i - 1) : 0]; 
 2255 |          } 
 2256 |  
 2257 |          return result; 
 2258 |       } 
 2259 |    }; 
 2260 |  
 2261 |  
 2262 | (3) igeneric_function 
 2263 | This interface supports  a variable number  of arguments and  types as 
 2264 | input  into  the  function. The  function  operator  interface uses  a 
 2265 | std::vector  specialised  upon  the  type_store  type  to   facilitate 
 2266 | parameter passing. 
 2267 |  
 2268 |     Scalar <-- function(i_0, i_1, i_2....., i_N) 
 2269 |  
 2270 |  
 2271 | The  fundamental  types  that  can  be  passed  into  the  function as 
 2272 | parameters and their views are as follows: 
 2273 |  
 2274 |    (1) Scalar - scalar_view 
 2275 |    (2) Vector - vector_view 
 2276 |    (3) String - string_view 
 2277 |  
 2278 |  
 2279 | The above denoted type  views provide non-const reference-like  access 
 2280 | to each parameter, as such modifications made to the input  parameters 
 2281 | will  persist after  the function  call has  completed. The  following 
 2282 | example defines a generic function called 'too': 
 2283 |  
 2284 |    template <typename T> 
 2285 |    struct too final : public exprtk::igeneric_function<T> 
 2286 |    { 
 2287 |       typedef typename exprtk::igeneric_function<T>::parameter_list_t 
 2288 |                                                      parameter_list_t; 
 2289 |  
 2290 |       too() 
 2291 |       {} 
 2292 |  
 2293 |       inline T operator()(parameter_list_t parameters) override 
 2294 |       { 
 2295 |          for (std::size_t i = 0; i < parameters.size(); ++i) 
 2296 |          { 
 2297 |             ... 
 2298 |          } 
 2299 |  
 2300 |          return T(0); 
 2301 |       } 
 2302 |    }; 
 2303 |  
 2304 |  
 2305 | In the example above, the input 'parameters' to the function operator, 
 2306 | parameter_list_t,  is  a  type  of  std::vector  of  type_store.  Each 
 2307 | type_store  instance  has  a  member  called  'type'  which  holds the 
 2308 | enumeration pertaining to the underlying type of the type_store. There 
 2309 | are three type enumerations: 
 2310 |  
 2311 |    (1) e_scalar - literals, variables, vector elements, expressions 
 2312 |        eg: 123.456, x, vec[3x + 1], 2x + 3 
 2313 |  
 2314 |    (2) e_vector - vectors, vector expressions 
 2315 |        eg: vec1, 2 * vec1 + vec2 / 3 
 2316 |  
 2317 |    (3) e_string - strings, string literals and range variants of both 
 2318 |        eg: 'AString', s0, 'AString'[x:y], s1[1 + x:] + 'AString' 
 2319 |  
 2320 |  
 2321 | Each of the  parameters can be  accessed using its  designated view. 
 2322 | A typical loop for processing the parameters is as follows: 
 2323 |  
 2324 |    inline T operator()(parameter_list_t parameters) 
 2325 |    { 
 2326 |       typedef typename exprtk::igeneric_function<T>::generic_type 
 2327 |                                                      generic_type; 
 2328 |  
 2329 |       typedef typename generic_type::scalar_view scalar_t; 
 2330 |       typedef typename generic_type::vector_view vector_t; 
 2331 |       typedef typename generic_type::string_view string_t; 
 2332 |  
 2333 |       for (std::size_t i = 0; i < parameters.size(); ++i) 
 2334 |       { 
 2335 |          generic_type& gt = parameters[i]; 
 2336 |  
 2337 |          if (generic_type::e_scalar == gt.type) 
 2338 |          { 
 2339 |             scalar_t x(gt); 
 2340 |             ... 
 2341 |          } 
 2342 |          else if (generic_type::e_vector == gt.type) 
 2343 |          { 
 2344 |             vector_t vector(gt); 
 2345 |             ... 
 2346 |          } 
 2347 |          else if (generic_type::e_string == gt.type) 
 2348 |          { 
 2349 |             string_t string(gt); 
 2350 |             ... 
 2351 |          } 
 2352 |       } 
 2353 |  
 2354 |       return T(0); 
 2355 |    } 
 2356 |  
 2357 |  
 2358 | Most often than not a custom generic function will require a  specific 
 2359 | sequence of parameters, rather than some arbitrary sequence of  types. 
 2360 | In those situations, ExprTk can perform compile-time type checking  to 
 2361 | validate that function invocations  are carried out using  the correct 
 2362 | sequence of parameters. Furthermore  performing the checks at  compile 
 2363 | -time rather than at run-time (aka every time the function is invoked) 
 2364 | will result in expression evaluation performance gains. 
 2365 |  
 2366 | Compile-time type  checking of  input parameters  can be  requested by 
 2367 | passing  a string  to the  constructor of  the igeneric_function  that 
 2368 | represents the required sequence of parameter types. When no parameter 
 2369 | sequence is provided, it is implied the function can accept a variable 
 2370 | number of parameters comprised of any of the fundamental types. 
 2371 |  
 2372 | Each fundamental type has an  associated character. The following is a 
 2373 | listing of said characters and their meanings: 
 2374 |  
 2375 |    (1) T - Scalar 
 2376 |    (2) V - Vector 
 2377 |    (3) S - String 
 2378 |    (4) Z - Zero or no parameters 
 2379 |    (5) ? - Any type (Scalar, Vector or String) 
 2380 |    (6) * - Wildcard operator 
 2381 |    (7) | - Parameter sequence delimiter 
 2382 |  
 2383 |  
 2384 | No other characters other than the seven denoted above may be included 
 2385 | in the parameter sequence  definition. If any such  invalid characters 
 2386 | do exist, registration of the associated generic function to a  symbol 
 2387 | table ('add_function' method) will fail. If the parameter sequence  is 
 2388 | modified resulting in it becoming  invalid after having been added  to 
 2389 | the symbol table but before the compilation step, a compilation  error 
 2390 | will be incurred. 
 2391 |  
 2392 | The  following   example  demonstrates   a  simple   generic  function 
 2393 | implementation with a user specified parameter sequence: 
 2394 |  
 2395 |    template <typename T> 
 2396 |    struct moo final : public exprtk::igeneric_function<T> 
 2397 |    { 
 2398 |       typedef typename exprtk::igeneric_function<T>::parameter_list_t 
 2399 |                                                      parameter_list_t; 
 2400 |  
 2401 |       moo() 
 2402 |       : exprtk::igeneric_function<T>("SVTT") 
 2403 |       {} 
 2404 |  
 2405 |       inline T operator()(parameter_list_t parameters) override 
 2406 |       { 
 2407 |          ... 
 2408 |       } 
 2409 |    }; 
 2410 |  
 2411 |  
 2412 | In the example above the  generic function 'moo' expects exactly  four 
 2413 | parameters in the following sequence: 
 2414 |  
 2415 |    (1) String 
 2416 |    (2) Vector 
 2417 |    (3) Scalar 
 2418 |    (4) Scalar 
 2419 |  
 2420 | Note16: The 'Z' or no parameter option may not be used in  conjunction 
 2421 | with any other type option in a parameter sequence. When  incorporated 
 2422 | in the parameter  sequence list, the  'No Parameter' option  indicates 
 2423 | that the function may be invoked without any parameters being  passed. 
 2424 | For more information refer to the section: 'Zero Parameter Functions' 
 2425 |  
 2426 |  
 2427 | (4) igeneric_function II 
 2428 | This interface is identical to  the igeneric_function, in that in  can 
 2429 | consume an  arbitrary number  of parameters  of varying  type, but the 
 2430 | difference being  that the  function returns  a string  and as such is 
 2431 | treated as a string when  invoked within expressions. As a  result the 
 2432 | function call can  alias a string  and interact with  other strings in 
 2433 | situations such as concatenation and equality operations. 
 2434 |  
 2435 |     String <-- function(i_0, i_1, i_2....., i_N) 
 2436 |  
 2437 |  
 2438 | The following example defines a generic function  named 'toupper' with 
 2439 | the string return type function operator being explicitly overridden: 
 2440 |  
 2441 |    template <typename T> 
 2442 |    struct toupper final : public exprtk::igeneric_function<T> 
 2443 |    { 
 2444 |       typedef exprtk::igeneric_function<T> igenfunct_t; 
 2445 |       typedef typename igenfunct_t::generic_type generic_t; 
 2446 |       typedef typename igenfunct_t::parameter_list_t parameter_list_t; 
 2447 |       typedef typename generic_t::string_view string_t; 
 2448 |  
 2449 |       toupper() 
 2450 |       : exprtk::igeneric_function<T>("S",igenfunct_t::e_rtrn_string) 
 2451 |       {} 
 2452 |  
 2453 |       inline T operator()(std::string& result, 
 2454 |                           parameter_list_t parameters) override 
 2455 |       { 
 2456 |          result.clear(); 
 2457 |  
 2458 |          string_t string(parameters[0]); 
 2459 |  
 2460 |          for (std::size_t i = 0; i < string.size(); ++i) 
 2461 |          { 
 2462 |             result += std::toupper(string[i]); 
 2463 |          } 
 2464 |  
 2465 |          return T(0); 
 2466 |       } 
 2467 |    }; 
 2468 |  
 2469 |  
 2470 | In the example above the  generic function 'toupper' expects only  one 
 2471 | input parameter  of type  string, as  noted by  the parameter sequence 
 2472 | string passed during the  constructor. Furthermore a second  parameter 
 2473 | is passed to the constructor indicating that it should be treated as a 
 2474 | string returning function -  by default it is  assumed to be a  scalar 
 2475 | returning function. 
 2476 |  
 2477 | When executed,  the function  will return  as a  result a  copy of the 
 2478 | input string converted to uppercase form. An example expression  using 
 2479 | the toupper function registered as the symbol 'toupper' is as follows: 
 2480 |  
 2481 |    "'ABCDEF' == toupper('aBc') + toupper('DeF')" 
 2482 |  
 2483 |  
 2484 | Note17: When  adding a  string type  returning generic  function to  a 
 2485 | symbol  table  the  'add_function'  is  invoked.  The  example   below 
 2486 | demonstrates how this can be done: 
 2487 |  
 2488 |    toupper<T> tu; 
 2489 |  
 2490 |    exprtk::symbol_table<T> symbol_table; 
 2491 |  
 2492 |    symbol_table.add_function("toupper",tu); 
 2493 |  
 2494 |  
 2495 | Note18: Two further refinements to the  type checking facility are the 
 2496 | possibilities  of  a variable  number  of common  types  which can  be 
 2497 | accomplished by using a wildcard '*' and a special 'any type' which is 
 2498 | done using  the '?'  character. It  should be  noted that the wildcard 
 2499 | operator is  associated with  the previous  type in  the sequence  and 
 2500 | implies one or more of that type. 
 2501 |  
 2502 |    template <typename T> 
 2503 |    struct zoo final : public exprtk::igeneric_function<T> 
 2504 |    { 
 2505 |       typedef typename exprtk::igeneric_function<T>::parameter_list_t 
 2506 |                                                      parameter_list_t; 
 2507 |  
 2508 |       zoo() 
 2509 |       : exprtk::igeneric_function<T>("SVT*V?") 
 2510 |       {} 
 2511 |  
 2512 |       inline T operator()(parameter_list_t parameters) override 
 2513 |       { 
 2514 |          ... 
 2515 |       } 
 2516 |    }; 
 2517 |  
 2518 |  
 2519 | In the example above the generic function 'zoo' expects at least  five 
 2520 | parameters in the following sequence: 
 2521 |  
 2522 |    (1) String 
 2523 |    (2) Vector 
 2524 |    (3) One or more Scalars 
 2525 |    (4) Vector 
 2526 |    (5) Any type (one type of either a scalar, vector or string) 
 2527 |  
 2528 |  
 2529 | A final  piece of  type checking  functionality is  available for  the 
 2530 | scenarios where  a single  function name  is intended  to be  used for 
 2531 | multiple distinct parameter sequences,  another name for this  feature 
 2532 | is function  overloading. The  parameter sequences  are passed  to the 
 2533 | constructor as a  single string delimited  by the pipe  '|' character. 
 2534 | Two specific overrides of the  function operator are provided one  for 
 2535 | standard generic functions and one for string returning functions. The 
 2536 | overrides are as follows: 
 2537 |  
 2538 |       // Scalar <-- function(psi,i_0,i_1,....,i_N) 
 2539 |       inline T operator()(const std::size_t& ps_index, 
 2540 |                           parameter_list_t parameters) 
 2541 |       { 
 2542 |          ... 
 2543 |       } 
 2544 |  
 2545 |       // String <-- function(psi,i_0,i_1,....,i_N) 
 2546 |       inline T operator()(const std::size_t& ps_index, 
 2547 |                           std::string& result, 
 2548 |                           parameter_list_t parameters) 
 2549 |       { 
 2550 |          ... 
 2551 |       } 
 2552 |  
 2553 |  
 2554 | When the function  operator is invoked  the 'ps_index' parameter  will 
 2555 | have as its value the index of the parameter sequence that matches the 
 2556 | specific invocation. This way complex and time consuming type checking 
 2557 | conditions need not  be executed in  the function itself  but rather a 
 2558 | simple and efficient  dispatch to a  specific implementation for  that 
 2559 | particular parameter sequence can be performed. 
 2560 |  
 2561 |    template <typename T> 
 2562 |    struct roo final : public exprtk::igeneric_function<T> 
 2563 |    { 
 2564 |       typedef typename exprtk::igeneric_function<T>::parameter_list_t 
 2565 |                                                      parameter_list_t; 
 2566 |  
 2567 |       moo() 
 2568 |       : exprtk::igeneric_function<T>("SVTT|SS|TTV|S?V*S") 
 2569 |       {} 
 2570 |  
 2571 |       inline T operator()(const std::size_t& ps_index, 
 2572 |                           parameter_list_t parameters) override 
 2573 |       { 
 2574 |          ... 
 2575 |       } 
 2576 |    }; 
 2577 |  
 2578 |  
 2579 | In the example above there are four distinct parameter sequences  that 
 2580 | can be processed  by the generic  function 'roo'. Any  other parameter 
 2581 | sequences will cause a compilation error. The four valid sequences are 
 2582 | as follows: 
 2583 |  
 2584 |     Sequence-0    Sequence-1    Sequence-2    Sequence-3 
 2585 |       'SVTT'         'SS'          'TTV'       'S?V*S' 
 2586 |    (1) String    (1) String    (1) Scalar    (1) String 
 2587 |    (2) Vector    (2) String    (2) Scalar    (2) Any Type 
 2588 |    (3) Scalar                  (3) Vector    (3) One or more Vectors 
 2589 |    (4) Scalar                                (4) String 
 2590 |  
 2591 |  
 2592 | (5) igeneric_function III 
 2593 | In this section we will discuss an extension of the  igeneric_function 
 2594 | interface that will allow for the overloading of a user defined custom 
 2595 | function, where by it can return either a scalar or string value  type 
 2596 | depending on the input parameter  sequence with which the function  is 
 2597 | invoked. 
 2598 |  
 2599 |    template <typename T> 
 2600 |    struct foo final : public exprtk::igeneric_function<T> 
 2601 |    { 
 2602 |       typedef typename exprtk::igeneric_function<T>::parameter_list_t 
 2603 |                                                      parameter_list_t; 
 2604 |  
 2605 |       foo() 
 2606 |       : exprtk::igeneric_function<T> 
 2607 |         ( 
 2608 |           "T:T|S:TS", 
 2609 |           igfun_t::e_rtrn_overload 
 2610 |         ) 
 2611 |       {} 
 2612 |  
 2613 |       // Scalar value returning invocations 
 2614 |       inline T operator()(const std::size_t& ps_index, 
 2615 |                           parameter_list_t parameters) override 
 2616 |       { 
 2617 |          ... 
 2618 |       } 
 2619 |  
 2620 |       // String value returning invocations 
 2621 |       inline T operator()(const std::size_t& ps_index, 
 2622 |                           std::string& result, 
 2623 |                           parameter_list_t& parameters) override 
 2624 |       { 
 2625 |          ... 
 2626 |       } 
 2627 |    }; 
 2628 |  
 2629 |  
 2630 | In the  example above  the custom  user defined  function "foo" can be 
 2631 | invoked by using  either one of  two input parameter  sequences, which 
 2632 | are defined as follows: 
 2633 |  
 2634 |    Sequence-0    Sequence-1 
 2635 |    'T' -> T      'TS' -> S 
 2636 |    (1) Scalar    (1) Scalar 
 2637 |                  (2) String 
 2638 |  
 2639 |  
 2640 | The parameter  sequence definitions  are identical  to the  previously 
 2641 | defined igeneric_function, with the exception of the inclusion  of the 
 2642 | return type - which can only be either a scalar T or a string S. 
 2643 |  
 2644 |  
 2645 | (6) function_compositor 
 2646 | The function  compositor is  a factory  that allows  one to define and 
 2647 | construct a function using ExprTk syntax. The functions are limited to 
 2648 | returning a single scalar value and consuming up to six parameters  as 
 2649 | input. 
 2650 |  
 2651 | All composited functions are registered with a symbol table,  allowing 
 2652 | them  to  call  other  functions  and  use  variables  that  have been 
 2653 | registered with the symbol  table instance. Furthermore the  functions 
 2654 | can be  recursive in  nature due  to the  inherent function  prototype 
 2655 | forwarding  that  occurs during  construction.  The following  example 
 2656 | defines,  by using  two different  methods, composited  functions and 
 2657 | implicitly registering the functions with the denoted symbol table. 
 2658 |  
 2659 |    typedef exprtk::symbol_table<T>         symbol_table_t; 
 2660 |    typedef exprtk::function_compositor<T>  compositor_t; 
 2661 |    typedef typename compositor_t::function function_t; 
 2662 |  
 2663 |    T avogadro = T(6.022e23); 
 2664 |  
 2665 |    symbol_table_t symbol_table; 
 2666 |  
 2667 |    symbol_table.add_constant("avogadro", avogadro); 
 2668 |  
 2669 |    compositor_t compositor(symbol_table); 
 2670 |  
 2671 |    // Define function koo0(v1, v2) { ... } 
 2672 |    compositor.add( 
 2673 |       function_t("koo0"), 
 2674 |       .vars("v1", "v2") 
 2675 |       .expression 
 2676 |       ( 
 2677 |          " 1 + cos(v1 * v2) / avogadro; " 
 2678 |       )); 
 2679 |  
 2680 |    // Define function koo1(x, y, z) { ... } 
 2681 |    compositor.add( 
 2682 |       function_t() 
 2683 |       .name("koo1") 
 2684 |       .var("x").var("y").var("z") 
 2685 |       .expression 
 2686 |       ( 
 2687 |          "1 + koo0(x * y, 3) / z;" 
 2688 |       )); 
 2689 |  
 2690 |  
 2691 | A function compositor can also be instantiated without a symbol_table. 
 2692 | When this is the case an internal symbol_table is used for holding the 
 2693 | references to the composited functions. 
 2694 |  
 2695 |    compositor_t compositor; 
 2696 |  
 2697 |    // Define function koo2(v1, v2) { ... } 
 2698 |    compositor.add( 
 2699 |       function_t("koo2"), 
 2700 |       .vars("v1", "v2", "v3") 
 2701 |       .expression 
 2702 |       ( " abs(v1 * v2) / v3; " )); 
 2703 |  
 2704 |  
 2705 | When wanting to  reference functions from  the compositor above  in an 
 2706 | expression, the compositor's symbol_table  will need to be  registered 
 2707 | with the expression  prior to compilation,  as is demonstrated  in the 
 2708 | following code: 
 2709 |  
 2710 |    expression_t expression; 
 2711 |    . 
 2712 |    . 
 2713 |    expression.register_symbol_table(compositor.symbol_table()); 
 2714 |  
 2715 |  
 2716 | In the situation where  more than one symbol table's contents will  be 
 2717 | required by the functions  being composited, then those  symbol tables 
 2718 | can be registered as auxiliary symbol tables with the compositor: 
 2719 |  
 2720 |    symbol_table_t global_symbol_table; 
 2721 |    symbol_table_t local_symbol_table; 
 2722 |    . 
 2723 |    . 
 2724 |    . 
 2725 |    compositor_t compositor; 
 2726 |  
 2727 |    compositor.add_auxiliary_symtab(global_symbol_table); 
 2728 |    compositor.add_auxiliary_symtab(local_symbol_table ); 
 2729 |  
 2730 | Note19: In the event, that two or more symbol tables contain similarly 
 2731 | named  variables,  vectors,  strings   or  functions,  the  order   of 
 2732 | registration with the compositor shall determine the symbol table from 
 2733 | which the target symbol will be referenced. 
 2734 |  
 2735 |  
 2736 | (7) Using Functions In Expressions 
 2737 | For the above denoted custom and composited functions to be used in an 
 2738 | expression, an instance of each function needs to be registered with a 
 2739 | symbol_table that  has been  associated with  the expression instance. 
 2740 | The following demonstrates how all the pieces are put together: 
 2741 |  
 2742 |    typedef exprtk::symbol_table<double>        symbol_table_t; 
 2743 |    typedef exprtk::expression<double>          expression_t; 
 2744 |    typedef exprtk::parser<double>              parser_t; 
 2745 |    typedef exprtk::function_compositor<double> compositor_t; 
 2746 |    typedef typename compositor_t::function     function_t; 
 2747 |  
 2748 |    foo<double> f; 
 2749 |    boo<double> b; 
 2750 |    too<double> t; 
 2751 |    toupper<double> tu; 
 2752 |  
 2753 |    symbol_table_t symbol_table; 
 2754 |    compositor_t   compositor(symbol_table); 
 2755 |  
 2756 |    symbol_table.add_function("foo",f); 
 2757 |    symbol_table.add_function("boo",b); 
 2758 |    symbol_table.add_function("too",t); 
 2759 |  
 2760 |    symbol_table 
 2761 |       .add_function("toupper", tu, symbol_table_t::e_ft_strfunc); 
 2762 |  
 2763 |    compositor.add( 
 2764 |       function_t("koo") 
 2765 |       .var("v1") 
 2766 |       .var("v2") 
 2767 |       .expression 
 2768 |       ( 
 2769 |          "1 + cos(v1 * v2) / 3;" 
 2770 |       )); 
 2771 |  
 2772 |    expression_t expression; 
 2773 |    expression.register_symbol_table(symbol_table); 
 2774 |  
 2775 |    const std::string expression_str = 
 2776 |       " if (foo(1,2,3) + boo(1) > boo(1/2, 2/3, 3/4, 4/5)) " 
 2777 |       "    koo(3,4);                                       " 
 2778 |       " else                                               " 
 2779 |       "    too(2 * v1 + v2 / 3, 'abcdef'[2:4], 3.3);       " 
 2780 |       "                                                    " 
 2781 |  
 2782 |    parser_t parser; 
 2783 |    parser.compile(expression_str,expression); 
 2784 |  
 2785 |    expression.value(); 
 2786 |  
 2787 |  
 2788 | (8) Function Side-Effects 
 2789 | All function calls are assumed  to have side-effects by default.  This 
 2790 | assumption implicitly disables constant folding optimisations when all 
 2791 | parameters being passed to the function are deduced as being constants 
 2792 | at compile time. 
 2793 |  
 2794 | If it is certain that the function being registered does not have  any 
 2795 | side-effects and can  be correctly constant folded  where appropriate, 
 2796 | then during the construction of the function the side-effect trait  of 
 2797 | the function can be disabled. 
 2798 |  
 2799 |    template <typename T> 
 2800 |    struct foo final : public exprtk::ifunction<T> 
 2801 |    { 
 2802 |       foo() : exprtk::ifunction<T>(3) 
 2803 |       { 
 2804 |          exprtk::disable_has_side_effects(*this); 
 2805 |       } 
 2806 |  
 2807 |       T operator()(const T& v1, const T& v2, const T& v3) override 
 2808 |       { ... } 
 2809 |    }; 
 2810 |  
 2811 |  
 2812 | (9) Zero Parameter Functions 
 2813 | When  either  an  ifunction,  ivararg_function  or   igeneric_function 
 2814 | derived type is defined with zero number of parameters, there are  two 
 2815 | calling  conventions  within  expressions  that  are  allowed.  For  a 
 2816 | function named 'foo' with zero input parameters the calling styles are 
 2817 | as follows: 
 2818 |  
 2819 |    (1)  x + sin(foo()- 2) / y 
 2820 |    (2)  x + sin(foo  - 2) / y 
 2821 |  
 2822 |  
 2823 | By default the  zero parameter trait  is disabled. In  order to enable 
 2824 | it, a process similar to that of  enabling of the side-effect trait is 
 2825 | carried out: 
 2826 |  
 2827 |    template <typename T> 
 2828 |    struct foo final : public exprtk::ivararg_function<T> 
 2829 |    { 
 2830 |       foo() 
 2831 |       { 
 2832 |          exprtk::enable_zero_parameters(*this); 
 2833 |       } 
 2834 |  
 2835 |       inline T operator()(const std::vector<T>& arglist) override 
 2836 |       { ... } 
 2837 |    }; 
 2838 |  
 2839 |  
 2840 | Note20: For the igeneric_function  type, there  also needs to be a 'Z' 
 2841 | parameter sequence  defined in order for the  zero parameter  trait to 
 2842 | properly take effect otherwise a compilation error will occur. 
 2843 |  
 2844 |  
 2845 | (10) Free Functions 
 2846 | The ExprTk symbol  table supports the  registration of free  functions 
 2847 | and lambdas  (anonymous functors)  for use  in expressions.  The basic 
 2848 | requirements  are similar  to those  found in  ifunction derived  user 
 2849 | defined  functions. This  includes  support  for free  functions using 
 2850 | anywhere from zero up to fifteen input parameters of scalar type, with 
 2851 | a return type that is also scalar. Furthermore such functions will  by 
 2852 | default be assumed to have side-effects and hence will not participate 
 2853 | in constant folding optimisations. 
 2854 |  
 2855 | In the following  example, a one  input parameter free  function named 
 2856 | 'compute1',  a  two  input  parameter  template  free  function  named 
 2857 | 'compute2' and a three input parameter lambda named 'compute3' will be 
 2858 | registered with the given symbol_table instance: 
 2859 |  
 2860 |    double compute1(double v0) 
 2861 |    { 
 2862 |       return 2.0 * std::abs(v0); 
 2863 |    } 
 2864 |  
 2865 |    template <typename T> 
 2866 |    T compute2(T v0, T v1) 
 2867 |    { 
 2868 |       return 2.0 * v0 + v1 / 3.0; 
 2869 |    } 
 2870 |    . 
 2871 |    . 
 2872 |    . 
 2873 |  
 2874 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 2875 |  
 2876 |    symbol_table_t symbol_table; 
 2877 |  
 2878 |    symbol_table.add_function("compute1", compute1); 
 2879 |    symbol_table.add_function("compute2", compute2<double>); 
 2880 |  
 2881 |    symbol_table.add_function( 
 2882 |       "compute3", 
 2883 |       [](double v0, double v1, double v2) -> double 
 2884 |       { return v0 / v1 + v2; }); 
 2885 |  
 2886 |  
 2887 | Note21: Similar to  variables registered with  symbol_table instances, 
 2888 | for any of the following function providers: 
 2889 |  
 2890 |    1. ifunction 
 2891 |    2. ivararg_function 
 2892 |    3. igeneric_function 
 2893 |    4. function_compositor 
 2894 |    5. Free function 
 2895 |    7. Lambda 
 2896 |  
 2897 |  
 2898 | Their instance lifetimes must exceed the symbol_tables and expressions 
 2899 | they are  registered with.  In the  event that  is not  the case,  the 
 2900 | expected result shall be undefined behaviour. 
 2901 |  
 2902 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 2903 |  
 2904 | [SECTION 16 - EXPRESSION DEPENDENTS] 
 2905 | Any  expression  that  is  not  a  literal  (aka  constant)  will have 
 2906 | dependencies. The types of  'dependencies' an expression can  have are 
 2907 | as follows: 
 2908 |  
 2909 |    (a) Variables 
 2910 |    (b) Vectors 
 2911 |    (c) Strings 
 2912 |    (d) Functions 
 2913 |    (e) Assignments 
 2914 |  
 2915 |  
 2916 | In  the  following  example the  denoted  expression  has its  various 
 2917 | dependencies listed: 
 2918 |  
 2919 |    z := abs(x + sin(2 * pi / y)) 
 2920 |  
 2921 |    (a) Variables:   x, y, z and pi 
 2922 |    (b) Functions:   abs, sin 
 2923 |    (c) Assignments: z 
 2924 |  
 2925 |  
 2926 | ExprTk allows for  the derivation of  expression dependencies via  the 
 2927 | 'dependent_entity_collector'  (DEC).  When  activated  either  through 
 2928 | 'compile_options' at the construction  of the parser or  through calls 
 2929 | to enabler methods just prior to compilation, the DEC will proceed  to 
 2930 | collect any  of the  relevant types  that are  encountered during  the 
 2931 | parsing  phase.   Once  the   compilation  process   has  successfully 
 2932 | completed, the  caller can  then obtain  a list  of symbols  and their 
 2933 | associated types from the DEC. 
 2934 |  
 2935 | The kinds of  questions one can  ask regarding the  dependent entities 
 2936 | within an expression are as follows: 
 2937 |  
 2938 |   * What user defined variables, vectors or strings are used? 
 2939 |   * What functions or custom user functions are used? 
 2940 |   * Which variables, vectors or strings have values assigned to them? 
 2941 |  
 2942 |  
 2943 | The following example demonstrates usage of the DEC in determining the 
 2944 | dependents of the given expression: 
 2945 |  
 2946 |    typedef typename parser_t:: 
 2947 |       dependent_entity_collector::symbol_t symbol_t; 
 2948 |  
 2949 |    const std::string expression_string = 
 2950 |       "z := abs(x + sin(2 * pi / y))" 
 2951 |  
 2952 |    T x,y,z; 
 2953 |  
 2954 |    parser_t parser; 
 2955 |    symbol_table_t symbol_table; 
 2956 |  
 2957 |    symbol_table.add_variable("x",x); 
 2958 |    symbol_table.add_variable("y",y); 
 2959 |    symbol_table.add_variable("z",z); 
 2960 |  
 2961 |    expression_t expression; 
 2962 |    expression.register_symbol_table(symbol_table); 
 2963 |  
 2964 |    // Collect only variable and function symbols 
 2965 |    parser.dec().collect_variables() = true; 
 2966 |    parser.dec().collect_functions() = true; 
 2967 |  
 2968 |    if (!parser.compile(expression_string,expression)) 
 2969 |    { 
 2970 |       // error.... 
 2971 |    } 
 2972 |  
 2973 |    std::deque<symbol_t> symbol_list; 
 2974 |  
 2975 |    parser.dec().symbols(symbol_list); 
 2976 |  
 2977 |    for (std::size_t i = 0; i < symbol_list.size(); ++i) 
 2978 |    { 
 2979 |       const symbol_t& symbol = symbol_list[i]; 
 2980 |  
 2981 |       switch (symbol.second) 
 2982 |       { 
 2983 |          case parser_t::e_st_variable : ... break; 
 2984 |          case parser_t::e_st_vector   : ... break; 
 2985 |          case parser_t::e_st_string   : ... break; 
 2986 |          case parser_t::e_st_function : ... break; 
 2987 |       } 
 2988 |    } 
 2989 |  
 2990 |  
 2991 | Note22: The 'symbol_t'  type is a  std::pair comprising of  the symbol 
 2992 | name (std::string) and the associated type of the symbol as denoted by 
 2993 | the cases in the switch statement. 
 2994 |  
 2995 | Having  particular  symbols  (variable  or  function)  present  in  an 
 2996 | expression is one form of dependency. Another and just as  interesting 
 2997 | and important type of  dependency is that of  assignments. Assignments 
 2998 | are the set of dependent symbols that 'may' have their values modified 
 2999 | within an expression. The following are example expressions and  their 
 3000 | associated assignments: 
 3001 |  
 3002 |        Assignments   Expression 
 3003 |    (1) x             x := y + z 
 3004 |    (2) x, y          x += y += z 
 3005 |    (3) x, y, z       x := y += sin(z := w + 2) 
 3006 |    (4) w, z          if (x > y, z := x + 2, w := 'A String') 
 3007 |    (5) None          x + y + z 
 3008 |  
 3009 |  
 3010 | Note23: In  expression 4,  both variables  'w' and  'z' are denoted as 
 3011 | being assignments even though only one of them can ever be modified at 
 3012 | the time of evaluation. Furthermore the determination of which of  the 
 3013 | two variables the modification will occur upon can only be known  with 
 3014 | certainty at evaluation time and not beforehand, hence both are listed 
 3015 | as being candidates for assignment. 
 3016 |  
 3017 | The following builds upon the previous example demonstrating the usage 
 3018 | of the DEC in determining the 'assignments' of the given expression: 
 3019 |  
 3020 |    // Collect assignments 
 3021 |    parser.dec().collect_assignments() = true; 
 3022 |  
 3023 |    if (!parser.compile(expression_string,expression)) 
 3024 |    { 
 3025 |       // error.... 
 3026 |    } 
 3027 |  
 3028 |    std::deque<symbol_t> symbol_list; 
 3029 |  
 3030 |    parser.dec().assignment_symbols(symbol_list); 
 3031 |  
 3032 |    for (std::size_t i = 0; i < symbol_list.size(); ++i) 
 3033 |    { 
 3034 |       symbol_t& symbol = symbol_list[i]; 
 3035 |  
 3036 |       switch (symbol.second) 
 3037 |       { 
 3038 |          case parser_t::e_st_variable : ... break; 
 3039 |          case parser_t::e_st_vector   : ... break; 
 3040 |          case parser_t::e_st_string   : ... break; 
 3041 |       } 
 3042 |    } 
 3043 |  
 3044 |  
 3045 | Note24: The  assignments will  only consist  of variable  types and as 
 3046 | such will not contain symbols denoting functions. 
 3047 |  
 3048 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 3049 |  
 3050 | [SECTION 17 - HIERARCHIES OF SYMBOL TABLES] 
 3051 | Most situations will only require a single symbol_table instance to be 
 3052 | associated with a given expression instance. 
 3053 |  
 3054 | However as an expression can have more than one symbol table  instance 
 3055 | associated  with  itself,  when  building  more  complex  systems that 
 3056 | utilise many expressions  where each can  in turn utilise  one or more 
 3057 | variables  from  a  large set  of  potential  variables, functions  or 
 3058 | constants, it becomes evident  that grouping variables into  layers of 
 3059 | symbol_tables will simplify and streamline the overall process. 
 3060 |  
 3061 | A recommended hierarchy of symbol tables is the following: 
 3062 |  
 3063 |    (a) Global constant value symbol table 
 3064 |    (b) Global non side-effect functions symbol table 
 3065 |    (c) Global variable symbol table 
 3066 |    (d) Expression specific variable symbol table 
 3067 |  
 3068 |  
 3069 | (a) Global constant value symbol table 
 3070 | This symbol table will  contain constant variables denoting  immutable 
 3071 | values. These variables can be made available to all expressions,  and 
 3072 | in turn expressions  will assume the  values themselves will  never be 
 3073 | modified for the  duration of the  process run-time. Examples  of such 
 3074 | variables are: 
 3075 |  
 3076 |    (1) pi or e 
 3077 |    (2) speed_of_light 
 3078 |    (3) avogadro_number 
 3079 |    (4) num_cpus 
 3080 |  
 3081 |  
 3082 | (b) Global non side-effect functions symbol table 
 3083 | This symbol table will contain  only user defined functions that  will 
 3084 | not  incur  any  side-effects  that  are  observable  to  any  of  the 
 3085 | expressions that invoke them. These functions shall be  thread-safe or 
 3086 | threading invariant and  will not maintain  any form of  state between 
 3087 | invocations. Examples of such functions are: 
 3088 |  
 3089 |    (1) calc_volume_of_sphere(r) 
 3090 |    (2) distance(x0,y0,x1,y1) 
 3091 |  
 3092 |  
 3093 | (c) Global variable symbol table 
 3094 | This symbol table  will contain variables  that will be  accessible to 
 3095 | all associated expressions  and will not  be specific or  exclusive to 
 3096 | any one expression. This variant  differs from (a) in that  the values 
 3097 | of the  variables can  change (or  be updated)  between evaluations of 
 3098 | expressions  -   but  through   properly  scheduled   evaluations  are 
 3099 | guaranteed  to never  change during  the evaluation  of any  dependent 
 3100 | expressions. Furthermore it  is assumed that  these variables will  be 
 3101 | used in a  read-only context and  that no expressions  will attempt to 
 3102 | modify these variables via assignments or other means. 
 3103 |  
 3104 |    (1) price_of_stock_xyz 
 3105 |    (2) outside_temperature or inside_temperature 
 3106 |    (3) fuel_in_tank 
 3107 |    (4) num_customers_in_store 
 3108 |    (5) num_items_on_shelf 
 3109 |  
 3110 |  
 3111 | (d) Expression specific variable symbol table 
 3112 | This  symbol_table  is  the most  common form,  and is  used to  store 
 3113 | variables that are specific and exclusive to a particular  expression. 
 3114 | That is to say references  to variables in this symbol_table  will not 
 3115 | be  part of  another expression.  Though it  may be  possible to  have 
 3116 | expressions that  contain the  variables with  the same  name, in that 
 3117 | case those variables will be distinctly different. Which would mean if 
 3118 | a particular  expression were  to be  compiled twice,  each expression 
 3119 | would have its  own unique symbol_table  which in turn  would have its 
 3120 | own instances of those variables. Examples of such variables could be: 
 3121 |  
 3122 |    (1) x or y 
 3123 |    (2) customer_name 
 3124 |  
 3125 |  
 3126 | The following is a diagram depicting a possible variant of the denoted 
 3127 | symbol  table  hierarchies.  In  the  diagram  there  are  two  unique 
 3128 | expressions, each of  which have a  reference to the  Global constant, 
 3129 | functions and variables symbol tables and an exclusive reference to  a 
 3130 | local symbol table. 
 3131 |  
 3132 |   +-------------------------+    +-------------------------+ 
 3133 |   |     Global Constants    |    |     Global Functions    | 
 3134 |   |       Symbol Table      |    |       Symbol Table      | 
 3135 |   +----o--o-----------------+    +--------------------o----+ 
 3136 |        |  |                                           | 
 3137 |        |  |                                           +-------+ 
 3138 |        |  +------------------->----------------------------+  | 
 3139 |        |         +----------------------------+            |  | 
 3140 |        |         |      Global Variables      |            |  | 
 3141 |        |  +------o        Symbol Table        o-----+      |  V 
 3142 |        |  |      +----------------------------+     |      |  | 
 3143 |        |  |                                         |      |  | 
 3144 |        |  | +----------------+   +----------------+ |      |  | 
 3145 |        |  | | Symbol Table 0 |   | Symbol Table 1 | |      V  | 
 3146 |        |  | +--o-------------+   +--o-------------+ |      |  | 
 3147 |        |  |    |                    |               |      |  | 
 3148 |        |  |    |                    |               |      |  | 
 3149 |     +--V--V----V---------+        +-V---------------V--+   |  | 
 3150 |     |    Expression 0    |        |    Expression 1    |<--+--+ 
 3151 |     |  '2 * sin(x) - y'  |        |  'k + abs(x - y)'  | 
 3152 |     +--------------------+        +--------------------+ 
 3153 |  
 3154 |  
 3155 | Bringing  all of  the above  together, in  the following  example the 
 3156 | hierarchy  of  symbol  tables  are instantiated  and  initialised. An 
 3157 | expression that makes use of various elements of each symbol table is 
 3158 | then compiled and later on evaluated: 
 3159 |  
 3160 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 3161 |    typedef exprtk::expression<double>   expression_t; 
 3162 |  
 3163 |    // Setup global constants symbol table 
 3164 |    symbol_table_t glbl_const_symbol_table; 
 3165 |    glbl_const_symbtab.add_constants(); // pi, epsilon and inf 
 3166 |    glbl_const_symbtab.add_constant("speed_of_light",299e6); 
 3167 |    glbl_const_symbtab.add_constant("avogadro_number",6e23); 
 3168 |  
 3169 |    // Setup global function symbol table 
 3170 |    symbol_table_t glbl_funcs_symbol_table; 
 3171 |    glbl_func_symbtab.add_function('distance',distance); 
 3172 |    glbl_func_symbtab.add_function('calc_spherevol',calc_sphrvol); 
 3173 |  
 3174 |    ...... 
 3175 |  
 3176 |    // Setup global variable symbol table 
 3177 |    symbol_table_t glbl_variable_symbol_table; 
 3178 |    glbl_variable_symbtab.add_variable('temp_outside',thermo.outside); 
 3179 |    glbl_variable_symbtab.add_variable('temp_inside' ,thermo.inside ); 
 3180 |    glbl_variable_symbtab.add_variable('num_cstmrs',store.num_cstmrs); 
 3181 |  
 3182 |    ...... 
 3183 |  
 3184 |    double x,y,z; 
 3185 |  
 3186 |    // Setup expression specific symbol table 
 3187 |    symbol_table_t symbol_table; 
 3188 |    symbol_table.add_variable('x',x); 
 3189 |    symbol_table.add_variable('y',y); 
 3190 |    symbol_table.add_variable('z',z); 
 3191 |  
 3192 |    expression_t expression; 
 3193 |  
 3194 |    // Register the various symbol tables 
 3195 |    expression 
 3196 |       .register_symbol_table(symbol_table); 
 3197 |  
 3198 |    expression 
 3199 |       .register_symbol_table(glbl_funcs_symbol_table); 
 3200 |  
 3201 |    expression 
 3202 |       .register_symbol_table(glbl_const_symbol_table); 
 3203 |  
 3204 |    expression 
 3205 |       .register_symbol_table(glbl_variable_symbol_table); 
 3206 |  
 3207 |    const std::string expression_str = 
 3208 |       "abs(temp_inside - temp_outside) + 2 * speed_of_light / x" 
 3209 |  
 3210 |    parser_t parser; 
 3211 |    parser.compile(expression_str,expression); 
 3212 |  
 3213 |    ...... 
 3214 |  
 3215 |    while (keep_evaluating) 
 3216 |    { 
 3217 |      .... 
 3218 |  
 3219 |      T result = expression.value(); 
 3220 |  
 3221 |      .... 
 3222 |    } 
 3223 |  
 3224 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 3225 |  
 3226 | [SECTION 18 - UNKNOWN UNKNOWNS] 
 3227 | In this section  we will discuss  the process of  handling expressions 
 3228 | with a mix of known and unknown variables. Initially a discussion into 
 3229 | the types of expressions that exist will be provided, then a series of 
 3230 | possible solutions will be presented for each scenario. 
 3231 |  
 3232 | When parsing an expression, there  may be situations where one  is not 
 3233 | fully  aware  of what  if  any variables  will  be used  prior  to the 
 3234 | expression being compiled. 
 3235 |  
 3236 | This can become problematic, as in the default scenario it is  assumed 
 3237 | the symbol_table that is registered with the expression instance  will 
 3238 | already possess  the  externally  available  variables,  functions and 
 3239 | constants needed during the compilation of the expression. 
 3240 |  
 3241 | In the event there are symbols in the expression that can't be  mapped 
 3242 | to   either   a  reserved   word,   or  located   in   the  associated 
 3243 | symbol_table(s), an "Undefined  symbol" error will  be raised and  the 
 3244 | compilation process will fail. 
 3245 |  
 3246 | The numerous  scenarios that  can occur  when compiling  an expression 
 3247 | with ExprTk generally fall into one of the following three categories: 
 3248 |  
 3249 |    (a) No external variables 
 3250 |    (b) Predetermined set of external variables 
 3251 |    (c) Unknown set of variables 
 3252 |  
 3253 |  
 3254 | (a) No external variables 
 3255 | These  are  expressions that  contain  no external  variables  but may 
 3256 | contain  local  variables.  As  local  variables  cannot  be  accessed 
 3257 | externally from the  expression, it is  assumed that such  expressions 
 3258 | will not have  a need for  a symbol_table and  furthermore expressions 
 3259 | which  don't  make  use of  functions that  have side-effects  will be 
 3260 | evaluated completely at  compile time resulting  in a constant  return 
 3261 | value. The following are examples of such expressions: 
 3262 |  
 3263 |    (1) 1 + 2 
 3264 |    (2) var x := 3; 2 * x - 3 
 3265 |    (3) var x := 3; var y := abs(x - 8); x - y / 7 
 3266 |  
 3267 |  
 3268 | (b) Predetermined set of external variables 
 3269 | These  are  expressions  that are  comprised  of  externally available 
 3270 | variables  and functions  and will  only compile  successfully if  the 
 3271 | symbols that  correspond to  the variables  and functions  are already 
 3272 | defined in their associated symbol_table(s).  This is by far the  most 
 3273 | common scenario when using ExprTk. 
 3274 |  
 3275 | As an example, one may have three external variables: x, y and z which 
 3276 | have been registered with  the associated symbol_table, and  will then 
 3277 | need to compile  and evaluate expressions  comprised of any  subset of 
 3278 | these  three  variables. The  following  are a  few  examples of  such 
 3279 | expressions: 
 3280 |  
 3281 |    (1) 1 + x 
 3282 |    (2) x / y 
 3283 |    (3) 2 * x * y / z 
 3284 |  
 3285 |  
 3286 | In  this  scenario   one  can  use   the  'dependent_entity_collector' 
 3287 | component as described in [Section  16] to further determine which  of 
 3288 | the registered variables were  actually used in the  given expression. 
 3289 | As  an example  once the  set of  utilised  variables  are known,  any 
 3290 | further 'attention'  can be  restricted to  only those  variables when 
 3291 | evaluating the expression. This can be quite useful when dealing  with 
 3292 | expressions that can draw from a set of hundreds or even thousands  of 
 3293 | variables. 
 3294 |  
 3295 |  
 3296 | (c) Unknown set of variables 
 3297 | These are  expressions that  are comprised  of symbols  other than the 
 3298 | standard ExprTk reserved words or what has been registered with  their 
 3299 | associated symbol_table, and will normally fail compilation due to the 
 3300 | associated symbol_table not having a  reference to them. As such  this 
 3301 | scenario can be  seen as a  combination of scenario  B, where one  may 
 3302 | have a symbol_table with registered variables, but would also like  to 
 3303 | handle  the  situation  of  variables  that  aren't  present  in  said 
 3304 | symbol_table. 
 3305 |  
 3306 | When dealing with expressions of category (c), one must perform all of 
 3307 | the following: 
 3308 |  
 3309 |    (1) Determine the variables used in the expression 
 3310 |    (2) Populate a symbol_table(s) with the entities from (1) 
 3311 |    (3) Compile the expression 
 3312 |    (4) Provide a means by which the entities from (1) can be modified 
 3313 |  
 3314 |  
 3315 | Depending on the nature of processing,  steps (1) and (2) can be  done 
 3316 | either independently of each other or combined into one. The following 
 3317 | example  will  initially  look  at  solving  the  problem  of  unknown 
 3318 | variables with the  latter method using  the 'unknown_symbol_resolver' 
 3319 | component. 
 3320 |  
 3321 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 3322 |    typedef exprtk::expression<T>   expression_t; 
 3323 |    typedef exprtk::parser<T>       parser_t; 
 3324 |  
 3325 |    T x = T(123.456); 
 3326 |    T y = T(789.123); 
 3327 |  
 3328 |    symbol_table_t unknown_var_symbol_table; 
 3329 |  
 3330 |    symbol_table_t symbol_table; 
 3331 |    symbol_table.add_variable("x",x); 
 3332 |    symbol_table.add_variable("y",y); 
 3333 |  
 3334 |    expression_t expression; 
 3335 |    expression.register_symbol_table(unknown_var_symbol_table); 
 3336 |    expression.register_symbol_table(symbol_table); 
 3337 |  
 3338 |    parser_t parser; 
 3339 |    parser.enable_unknown_symbol_resolver(); 
 3340 |  
 3341 |    const std::string expression_str = "x + abs(y / 3k) * z + 2" 
 3342 |  
 3343 |    parser.compile(expression_str,expression); 
 3344 |  
 3345 |  
 3346 | In the  example above,  the symbols  'k' and  'z' will  be treated  as 
 3347 | unknown symbols. The  parser in the  example is set  to handle unknown 
 3348 | symbols using the built-in default unknown_symbol_resolver (USR).  The 
 3349 | default  USR  will  automatically resolve  any  unknown  symbols as  a 
 3350 | variable (scalar type). The new variables will be added to the primary 
 3351 | symbol_table,  which in  this case  is the  'unknown_var_symbol_table' 
 3352 | instance.  Once  the  compilation  has  completed  successfully,   the 
 3353 | variables that were resolved  during compilation can be  accessed from 
 3354 | the   primary   symbol_table   using   the   'get_variable_list'   and 
 3355 | 'variable_ref' methods and then if needed can be modified  accordingly 
 3356 | after which the expression itself can be evaluated. 
 3357 |  
 3358 |    std::vector<std::string> variable_list; 
 3359 |  
 3360 |    unknown_var_symbol_table.get_variable_list(variable_list); 
 3361 |  
 3362 |    for (const auto& var_name : variable_list) 
 3363 |    { 
 3364 |       T& v = unknown_var_symbol_table.variable_ref(var_name); 
 3365 |  
 3366 |       v = ...; 
 3367 |    } 
 3368 |  
 3369 |    ... 
 3370 |  
 3371 |    expression.value(); 
 3372 |  
 3373 |  
 3374 | Note25: As previously  mentioned the  default  USR  will automatically 
 3375 | assume any unknown symbol to be a valid scalar variable, and will then 
 3376 | proceed to add said symbol  as a variable to the  primary symbol_table 
 3377 | of the associated expression during the compilation process. However a 
 3378 | problem that may arise, is  that expressions that are parsed  with the 
 3379 | USR enabled,  but contain  'typos' or  otherwise syntactic  errors may 
 3380 | inadvertently compile successfully due to the simplistic nature of the 
 3381 | default USR. The following are some example expressions: 
 3382 |  
 3383 |    (1) 1 + abz(x + 1) 
 3384 |    (2) sine(y / 2) - coz(3x) 
 3385 |  
 3386 |  
 3387 | The two  expressions above contain misspelt  symbols (abz,  sine, coz) 
 3388 | which if implied  multiplications and default  USR are enabled  during 
 3389 | compilation will result in them being assumed to be valid 'variables', 
 3390 | which obviously is  not the intended  outcome by the  user. A possible 
 3391 | solution to this  problem is for  one to implement  their own specific 
 3392 | USR that will perform a user defined business logic in determining  if 
 3393 | an encountered unknown symbol should be treated as a variable or if it 
 3394 | should raise a compilation error. The following example demonstrates a 
 3395 | simple user defined USR: 
 3396 |  
 3397 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 3398 |    typedef exprtk::expression<T>   expression_t; 
 3399 |    typedef exprtk::parser<T>       parser_t; 
 3400 |  
 3401 |    template <typename T> 
 3402 |    struct my_usr final : public parser_t::unknown_symbol_resolver 
 3403 |    { 
 3404 |       typedef typename parser_t::unknown_symbol_resolver usr_t; 
 3405 |  
 3406 |       bool process(const std::string& unknown_symbol, 
 3407 |                    typename usr_t::usr_symbol_type& st, 
 3408 |                    T& default_value, 
 3409 |                    std::string& error_message) override 
 3410 |       { 
 3411 |          if (0 != unknown_symbol.find("var_")) 
 3412 |          { 
 3413 |             error_message = "Invalid symbol: " + unknown_symbol; 
 3414 |             return false; 
 3415 |          } 
 3416 |  
 3417 |          st = usr_t::e_usr_variable_type; 
 3418 |          default_value = T(123.123); 
 3419 |  
 3420 |          return true; 
 3421 |       } 
 3422 |    }; 
 3423 |  
 3424 |    ... 
 3425 |  
 3426 |    T x = T(123.456); 
 3427 |    T y = T(789.123); 
 3428 |  
 3429 |    symbol_table_t unknown_var_symbol_table; 
 3430 |  
 3431 |    symbol_table_t symbol_table; 
 3432 |    symbol_table.add_variable("x",x); 
 3433 |    symbol_table.add_variable("y",y); 
 3434 |  
 3435 |    expression_t expression; 
 3436 |    expression.register_symbol_table(unknown_var_symbol_table); 
 3437 |    expression.register_symbol_table(symbol_table); 
 3438 |  
 3439 |    my_usr<T> musr; 
 3440 |  
 3441 |    parser_t parser; 
 3442 |    parser.enable_unknown_symbol_resolver(&musr); 
 3443 |  
 3444 |    std::string expression_str = "var_x + abs(var_y - 3) * var_z" 
 3445 |  
 3446 |    parser.compile(expression_str,expression); 
 3447 |  
 3448 |  
 3449 | In  the  example  above,  a user  specified  USR  is  defined, and  is 
 3450 | registered   with   the  parser   enabling   the  USR   functionality. 
 3451 | Subsequently during the compilation process when an unknown symbol  is 
 3452 | encountered, the USR's process method will be invoked. The USR in  the 
 3453 | example  will only  'accept' unknown  symbols  that  have a  prefix of 
 3454 | 'var_' as being valid variables, all other unknown symbols will result 
 3455 | in a compilation error being raised. 
 3456 |  
 3457 | In the example above  the callback of the  USR that is invoked  during 
 3458 | the unknown symbol resolution process only allows for scalar variables 
 3459 | to be defined and resolved -  as that is the simplest and  most common 
 3460 | form. 
 3461 |  
 3462 | There is a further  extended  version  of  the  callback  that  can be 
 3463 | overridden that will allow for  more control and choice over  the type 
 3464 | of symbol being  resolved. The following  is an example  definition of 
 3465 | said extended callback: 
 3466 |  
 3467 |    template <typename T> 
 3468 |    struct my_usr final : public parser_t::unknown_symbol_resolver 
 3469 |    { 
 3470 |      typedef typename parser_t::unknown_symbol_resolver usr_t; 
 3471 |  
 3472 |      my_usr() 
 3473 |      : usr_t(usr_t::e_usrmode_extended) 
 3474 |      {} 
 3475 |  
 3476 |      bool process(const std::string& unknown_symbol, 
 3477 |                   symbol_table_t&    symbol_table, 
 3478 |                   std::string&       error_message) override 
 3479 |      { 
 3480 |         bool result = false; 
 3481 |  
 3482 |         if (0 == unknown_symbol.find("var_")) 
 3483 |         { 
 3484 |            // Default value of zero 
 3485 |            result = symbol_table.create_variable(unknown_symbol,0); 
 3486 |  
 3487 |            if (!result) 
 3488 |            { 
 3489 |               error_message = "Failed to create variable..." 
 3490 |            } 
 3491 |         } 
 3492 |         else if (0 == unknown_symbol.find("str_")) 
 3493 |         { 
 3494 |            // Default value of empty string 
 3495 |            result = symbol_table.create_stringvar(unknown_symbol,""); 
 3496 |  
 3497 |            if (!result) 
 3498 |            { 
 3499 |               error_message = "Failed to create string variable..." 
 3500 |            } 
 3501 |         } 
 3502 |         else 
 3503 |            error_message = "Indeterminable symbol type." 
 3504 |  
 3505 |         return result; 
 3506 |      } 
 3507 |    }; 
 3508 |  
 3509 |  
 3510 | In the  example above,  the USR  callback when  invoked will  pass the 
 3511 | primary symbol table associated with the expression being parsed.  The 
 3512 | symbol  resolution  business  logic  can  then  determine  under  what 
 3513 | conditions  a  symbol will  be  resolved including  its  type (scalar, 
 3514 | string, vector etc) and default value. When the callback  successfully 
 3515 | returns  the  symbol  parsing and  resolution  process  will again  be 
 3516 | executed by the parser. The idea here is that given the primary symbol 
 3517 | table will now have the previously detected unknown symbol registered, 
 3518 | it will be correctly resolved  and the general parsing processing  can 
 3519 | then resume as per normal. 
 3520 |  
 3521 | Note26: In order to have  the USR's extended mode callback  be invoked 
 3522 | it is necessary to pass  the e_usrmode_extended enum value during  the 
 3523 | constructor of the user defined USR. 
 3524 |  
 3525 | Note27: The primary symbol table for an expression is the first symbol 
 3526 | table to be registered with that instance of the expression. 
 3527 |  
 3528 | Note28: For a successful symbol resolution using the normal USR all of 
 3529 | the following are required: 
 3530 |  
 3531 |    (1) Only if successful shall the process method return TRUE 
 3532 |    (2) The default_value parameter will have been set 
 3533 |    (3) The error_message parameter will be empty 
 3534 |    (4) usr_symbol_type input parameter field will be set to either: 
 3535 |          (*) e_usr_variable_type 
 3536 |          (*) e_usr_constant_type 
 3537 |  
 3538 | Note29: For a successful symbol resolution using the extended USR  all 
 3539 | of the following are required: 
 3540 |  
 3541 |    (1) Only if successful shall the process method return TRUE 
 3542 |    (2) symbol_table parameter will have had the newly resolved 
 3543 |        variable or string added to it 
 3544 |    (3) error_message parameter will be empty 
 3545 |  
 3546 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 3547 |  
 3548 | [SECTION 19 - ENABLING & DISABLING FEATURES] 
 3549 | The parser can be configured via its settings instance to either allow 
 3550 | or  disallow certain  features that  are available  within the  ExprTk 
 3551 | grammar. The features fall  into one  of the following six categories: 
 3552 |  
 3553 |    (1) Base Functions 
 3554 |    (2) Control Flow Structures 
 3555 |    (3) Logical Operators 
 3556 |    (4) Arithmetic Operators 
 3557 |    (5) Inequality Operators 
 3558 |    (6) Assignment Operators 
 3559 |  
 3560 |  
 3561 | (1) Base Functions 
 3562 | The list of available base functions is as follows: 
 3563 |  
 3564 |    abs, acos, acosh, asin,  asinh, atan, atanh, atan2,  avg, ceil, 
 3565 |    clamp,  cos,  cosh, cot,  csc,  equal, erf,  erfc,  exp, expm1, 
 3566 |    floor,  frac,  hypot,  iclamp, like,  log,  log10,  log2, logn, 
 3567 |    log1p, mand, max, min, mod,  mor, mul, ncdf, pow, root,  round, 
 3568 |    roundn, sec, sgn, sin, sinc, sinh, sqrt, sum, swap, tan,  tanh, 
 3569 |    trunc, not_equal, inrange, deg2grad, deg2rad, rad2deg, grad2deg 
 3570 |  
 3571 |  
 3572 | The above mentioned base functions  can be either enabled or  disabled 
 3573 | 'all' at once, as is demonstrated below: 
 3574 |  
 3575 |    parser_t parser; 
 3576 |    expression_t expression; 
 3577 |  
 3578 |    parser.settings().disable_all_base_functions(); 
 3579 |  
 3580 |    parser 
 3581 |       .compile("2 * abs(2 - 3)",expression); // compilation failure 
 3582 |  
 3583 |    parser.settings().enable_all_base_functions(); 
 3584 |  
 3585 |    parser 
 3586 |       .compile("2 * abs(2 - 3)",expression); // compilation success 
 3587 |  
 3588 |  
 3589 | One can also enable or disable specific base functions. The  following 
 3590 | example  demonstrates  the disabling  of  the trigonometric  functions 
 3591 | 'sin' and 'cos': 
 3592 |  
 3593 |    parser_t parser; 
 3594 |    expression_t expression; 
 3595 |  
 3596 |    parser.settings() 
 3597 |       .disable_base_function(settings_t::e_bf_sin) 
 3598 |       .disable_base_function(settings_t::e_bf_cos); 
 3599 |  
 3600 |    parser 
 3601 |       .compile("(sin(x) / cos(x)) == tan(x)",expression); // failure 
 3602 |  
 3603 |    parser.settings() 
 3604 |       .enable_base_function(settings_t::e_bf_sin) 
 3605 |       .enable_base_function(settings_t::e_bf_cos); 
 3606 |  
 3607 |    parser 
 3608 |       .compile("(sin(x) / cos(x)) == tan(x)",expression); // success 
 3609 |  
 3610 |  
 3611 | (2) Control Flow Structures 
 3612 | The list of available control flow structures is as follows: 
 3613 |  
 3614 |    (a) If or If-Else 
 3615 |    (b) Switch statement 
 3616 |    (c) For Loop 
 3617 |    (d) While Loop 
 3618 |    (e) Repeat Loop 
 3619 |  
 3620 |  
 3621 | The  above  mentioned  control flow structures  can be  either enabled 
 3622 | or disabled 'all' at once, as is demonstrated below: 
 3623 |  
 3624 |    parser_t parser; 
 3625 |    expression_t expression; 
 3626 |  
 3627 |    const std::string program = 
 3628 |       " var x := 0;                      " 
 3629 |       " for (var i := 0; i < 10; i += 1) " 
 3630 |       " {                                " 
 3631 |       "   x += i;                        " 
 3632 |       " }                                " 
 3633 |  
 3634 |    parser.settings().disable_all_control_structures(); 
 3635 |  
 3636 |    parser 
 3637 |       .compile(program,expression); // compilation failure 
 3638 |  
 3639 |    parser.settings().enable_all_control_structures(); 
 3640 |  
 3641 |    parser 
 3642 |       .compile(program,expression); // compilation success 
 3643 |  
 3644 |  
 3645 | One can also enable or  disable specific control flow structures.  The 
 3646 | following example demonstrates the  disabling of the for-loop  control 
 3647 | flow structure: 
 3648 |  
 3649 |    parser_t parser; 
 3650 |    expression_t expression; 
 3651 |  
 3652 |    const std::string program = 
 3653 |       " var x := 0;                      " 
 3654 |       " for (var i := 0; i < 10; i += 1) " 
 3655 |       " {                                " 
 3656 |       "   x += i;                        " 
 3657 |       " }                                " 
 3658 |  
 3659 |    parser.settings() 
 3660 |       .disable_control_structure(settings_t::e_ctrl_for_loop); 
 3661 |  
 3662 |    parser 
 3663 |       .compile(program,expression); // failure 
 3664 |  
 3665 |    parser.settings() 
 3666 |       .enable_control_structure(settings_t::e_ctrl_for_loop); 
 3667 |  
 3668 |    parser 
 3669 |       .compile(program,expression); // success 
 3670 |  
 3671 |  
 3672 | (3) Logical Operators 
 3673 | The list of available logical operators is as follows: 
 3674 |  
 3675 |    and, nand, nor, not, or, xnor, xor, &, | 
 3676 |  
 3677 |  
 3678 | The  above  mentioned  logical  operators  can  be  either  enabled or 
 3679 | disabled 'all' at once, as is demonstrated below: 
 3680 |  
 3681 |    parser_t parser; 
 3682 |    expression_t expression; 
 3683 |  
 3684 |    parser.settings().disable_all_logic_ops(); 
 3685 |  
 3686 |    parser 
 3687 |       .compile("1 or not(0 and 1)",expression); // compilation failure 
 3688 |  
 3689 |    parser.settings().enable_all_logic_ops(); 
 3690 |  
 3691 |    parser 
 3692 |       .compile("1 or not(0 and 1)",expression); // compilation success 
 3693 |  
 3694 |  
 3695 | One  can  also  enable  or  disable  specific  logical  operators. The 
 3696 | following  example  demonstrates  the disabling  of the  'and' logical 
 3697 | operator: 
 3698 |  
 3699 |    parser_t parser; 
 3700 |    expression_t expression; 
 3701 |  
 3702 |    parser.settings() 
 3703 |       .disable_logic_operation(settings_t::e_logic_and); 
 3704 |  
 3705 |    parser 
 3706 |       .compile("1 or not(0 and 1)",expression); // failure 
 3707 |  
 3708 |    parser.settings() 
 3709 |       .enable_logic_operation(settings_t::e_logic_and); 
 3710 |  
 3711 |    parser 
 3712 |       .compile("1 or not(0 and 1)",expression); // success 
 3713 |  
 3714 |  
 3715 | (4) Arithmetic Operators 
 3716 | The list of available arithmetic operators is as follows: 
 3717 |  
 3718 |    +, -, *, /, %, ^ 
 3719 |  
 3720 |  
 3721 | The  above mentioned  arithmetic operators  can be  either enabled  or 
 3722 | disabled 'all' at once, as is demonstrated below: 
 3723 |  
 3724 |    parser_t parser; 
 3725 |    expression_t expression; 
 3726 |  
 3727 |    parser.settings().disable_all_arithmetic_ops(); 
 3728 |  
 3729 |    parser 
 3730 |       .compile("1 + 2 / 3",expression); // compilation failure 
 3731 |  
 3732 |    parser.settings().enable_all_arithmetic_ops(); 
 3733 |  
 3734 |    parser 
 3735 |       .compile("1 + 2 / 3",expression); // compilation success 
 3736 |  
 3737 |  
 3738 | One  can also  enable or  disable specific  arithmetic operators.  The 
 3739 | following  example  demonstrates  the disabling  of  the  addition '+' 
 3740 | arithmetic operator: 
 3741 |  
 3742 |    parser_t parser; 
 3743 |    expression_t expression; 
 3744 |  
 3745 |    parser.settings() 
 3746 |       .disable_arithmetic_operation(settings_t::e_arith_add); 
 3747 |  
 3748 |    parser 
 3749 |       .compile("1 + 2 / 3",expression); // failure 
 3750 |  
 3751 |    parser.settings() 
 3752 |       .enable_arithmetic_operation(settings_t::e_arith_add); 
 3753 |  
 3754 |    parser 
 3755 |       .compile("1 + 2 / 3",expression); // success 
 3756 |  
 3757 |  
 3758 | (5) Inequality Operators 
 3759 | The list of available inequality operators is as follows: 
 3760 |  
 3761 |    <, <=, >, >=, ==, =, != <> 
 3762 |  
 3763 |  
 3764 | The  above mentioned  inequality operators  can be  either enabled  or 
 3765 | disabled 'all' at once, as is demonstrated below: 
 3766 |  
 3767 |    parser_t parser; 
 3768 |    expression_t expression; 
 3769 |  
 3770 |    parser.settings().disable_all_inequality_ops(); 
 3771 |  
 3772 |    parser 
 3773 |       .compile("1 < 3",expression); // compilation failure 
 3774 |  
 3775 |    parser.settings().enable_all_inequality_ops(); 
 3776 |  
 3777 |    parser 
 3778 |       .compile("1 < 3",expression); // compilation success 
 3779 |  
 3780 |  
 3781 | One  can also  enable or  disable specific  inequality operators.  The 
 3782 | following  example demonstrates  the disabling  of  the  less-than '<' 
 3783 | inequality operator: 
 3784 |  
 3785 |    parser_t parser; 
 3786 |    expression_t expression; 
 3787 |  
 3788 |    parser.settings() 
 3789 |       .disable_inequality_operation(settings_t::e_ineq_lt); 
 3790 |  
 3791 |    parser 
 3792 |       .compile("1 < 3",expression); // failure 
 3793 |  
 3794 |    parser.settings() 
 3795 |       .enable_inequality_operation(settings_t::e_ineq_lt); 
 3796 |  
 3797 |    parser 
 3798 |       .compile("1 < 3",expression); // success 
 3799 |  
 3800 |  
 3801 | (6) Assignment Operators 
 3802 | The list of available assignment operators is as follows: 
 3803 |  
 3804 |    :=, +=, -=, *=, /=, %= 
 3805 |  
 3806 |  
 3807 | The  above mentioned  assignment operators  can be  either enabled  or 
 3808 | disabled 'all' at once, as is demonstrated below: 
 3809 |  
 3810 |    T x = T(0); 
 3811 |  
 3812 |    parser_t       parser; 
 3813 |    expression_t   expression; 
 3814 |    symbol_table_t symbol_table; 
 3815 |  
 3816 |    symbol_table.add_variable("x",x); 
 3817 |  
 3818 |    expression.register_symbol_table(symbol_table); 
 3819 |  
 3820 |    parser.settings().disable_all_assignment_ops(); 
 3821 |  
 3822 |    parser 
 3823 |       .compile("x := 3",expression); // compilation failure 
 3824 |  
 3825 |    parser.settings().enable_all_assignment_ops(); 
 3826 |  
 3827 |    parser 
 3828 |       .compile("x := 3",expression); // compilation success 
 3829 |  
 3830 |  
 3831 | One  can also  enable or  disable specific  assignment operators.  The 
 3832 | following  example demonstrates  the  disabling  of the  '+=' addition 
 3833 | assignment operator: 
 3834 |  
 3835 |    T x = T(0); 
 3836 |  
 3837 |    parser_t       parser; 
 3838 |    expression_t   expression; 
 3839 |    symbol_table_t symbol_table; 
 3840 |  
 3841 |    symbol_table.add_variable("x",x); 
 3842 |  
 3843 |    expression.register_symbol_table(symbol_table); 
 3844 |  
 3845 |    parser.settings() 
 3846 |       .disable_assignment_operation(settings_t::e_assign_addass); 
 3847 |  
 3848 |    parser 
 3849 |       .compile("x += 3",expression); // failure 
 3850 |  
 3851 |    parser.settings() 
 3852 |       .enable_assignment_operation(settings_t::e_assign_addass); 
 3853 |  
 3854 |    parser 
 3855 |       .compile("x += 3",expression); // success 
 3856 |  
 3857 |  
 3858 | Note30: In the  event of  a  base  function  being  disabled, one  can 
 3859 | redefine  the  base  function  using  the  standard  custom   function 
 3860 | definition process.  In the  following example  the 'sin'  function is 
 3861 | disabled then redefined as a function taking degree input. 
 3862 |  
 3863 |    template <typename T> 
 3864 |    struct sine_deg final : public exprtk::ifunction<T> 
 3865 |    { 
 3866 |       sine_deg() : exprtk::ifunction<T>(1) {} 
 3867 |  
 3868 |       inline T operator()(const T& v) override 
 3869 |       { 
 3870 |          const T pi = exprtk::details::numeric::constant::pi; 
 3871 |          return std::sin((v * T(pi)) / T(180)); 
 3872 |       } 
 3873 |    }; 
 3874 |  
 3875 |     ... 
 3876 |  
 3877 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 3878 |    typedef exprtk::expression<T>   expression_t; 
 3879 |    typedef exprtk::parser<T>       parser_t; 
 3880 |  
 3881 |    typedef typename parser_t::settings_store settings_t; 
 3882 |  
 3883 |    sine_deg<T> sine; 
 3884 |  
 3885 |    symbol_table.add_reserved_function("sin",sine); 
 3886 |  
 3887 |    expression_t expression; 
 3888 |  
 3889 |    expression.register_symbol_table(symbol_table); 
 3890 |  
 3891 |    parser_t parser; 
 3892 |  
 3893 |    parser.settings() 
 3894 |       .disable_base_function(settings_t::e_bf_sin); 
 3895 |  
 3896 |    parser.compile("1 + sin(30)",expression); 
 3897 |  
 3898 |  
 3899 | In the example above, the custom 'sin' function is registered with the 
 3900 | symbol_table using the method 'add_reserved_function'. This is done so 
 3901 | as to bypass the checks for reserved words that are carried out on the 
 3902 | provided symbol names when calling the standard 'add_function' method. 
 3903 | Normally if  a user  specified symbol  name conflicts  with any of the 
 3904 | ExprTk reserved words, the add_function call will fail. 
 3905 |  
 3906 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 3907 |  
 3908 | [SECTION 20 - EXPRESSION RETURN VALUES] 
 3909 | ExprTk expressions can return immediately from any point by  utilising 
 3910 | the return call. Furthermore the  return call can be used  to transfer 
 3911 | out multiple return values from within the expression. 
 3912 |  
 3913 | If an expression evaluation exits using a return point, the result  of 
 3914 | the call  to the 'value' method will be  NaN, and  it is expected that 
 3915 | the return values will be available from the results_context. 
 3916 |  
 3917 | In  the  following example  there  are  three  return  points  in  the 
 3918 | expression.  If  neither  of  the  return  points  are  hit,  then the 
 3919 | expression will return normally. 
 3920 |  
 3921 |    const std::string expression_string = 
 3922 |       " if (x < y)                                   " 
 3923 |       "    return [x + 1,'return-call 1'];           " 
 3924 |       " else if (x > y)                              " 
 3925 |       "    return [y / 2, y + 1, 'return-call 2'];   " 
 3926 |       " else if (equal(x,y))                         " 
 3927 |       "    x + y;                                    " 
 3928 |       " return [x, y, x + y, x - y, 'return-call 3'] " 
 3929 |  
 3930 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 3931 |    typedef exprtk::expression<double>   expression_t; 
 3932 |    typedef exprtk::parser<double>       parser_t; 
 3933 |  
 3934 |    symbol_table_t symbol_table; 
 3935 |    expression_t   expression; 
 3936 |    parser_t       parser; 
 3937 |  
 3938 |    double x = 0; 
 3939 |    double y = 0; 
 3940 |  
 3941 |    symbol_table.add_variable("x",x); 
 3942 |    symbol_table.add_variable("y",y); 
 3943 |  
 3944 |    expression.register_symbol_table(symbol_table); 
 3945 |  
 3946 |    parser.compile(expression_string,expression); 
 3947 |  
 3948 |    T result = expression.value(); 
 3949 |  
 3950 |    if (expression.return_invoked()) 
 3951 |    { 
 3952 |       typedef exprtk::results_context<T> results_context_t; 
 3953 |       typedef typename results_context_t::type_store_t type_t; 
 3954 |       typedef typename type_t::scalar_view scalar_t; 
 3955 |       typedef typename type_t::vector_view vector_t; 
 3956 |       typedef typename type_t::string_view string_t; 
 3957 |  
 3958 |       const results_context_t& results = expression.results(); 
 3959 |  
 3960 |       for (std::size_t i = 0; i < results.count(); ++i) 
 3961 |       { 
 3962 |          type_t t = results[i]; 
 3963 |  
 3964 |          switch (t.type) 
 3965 |          { 
 3966 |             case type_t::e_scalar : ... 
 3967 |                                     break; 
 3968 |  
 3969 |             case type_t::e_vector : ... 
 3970 |                                     break; 
 3971 |  
 3972 |             case type_t::e_string : ... 
 3973 |                                     break; 
 3974 |  
 3975 |             default               : continue; 
 3976 |          } 
 3977 |    } 
 3978 |  
 3979 |  
 3980 | In the above example, there are three possible "return" points and one 
 3981 | regular result. Only one of the four paths can ever be realised. Hence 
 3982 | it is necessary to capture  the result of the expression  value method 
 3983 | call. In the event,  the call to return_invoked  is not true then  the 
 3984 | non-return code  path was  executed and  the result  of the evaluation 
 3985 | will be the result of the expression's value method. 
 3986 |  
 3987 | Note31: Processing of  the return  results is  similar to  that of the 
 3988 | generic function call parameters. 
 3989 |  
 3990 | The results_context provides getter  methods for each of  the possible 
 3991 | return types (scalar, vector and string) and can be used as follows: 
 3992 |  
 3993 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 3994 |    typedef exprtk::expression<T>   expression_t; 
 3995 |    typedef exprtk::parser<T>       parser_t; 
 3996 |  
 3997 |    const std::string expression_str = 
 3998 |       " if (x > y)                                  " 
 3999 |       "    return [1];                              " 
 4000 |       " else                                        " 
 4001 |       "    return [ x, x + y, 2 * v, s + 'world' ]; " 
 4002 |  
 4003 |    symbol_table_t symbol_table; 
 4004 |    expression_t   expression; 
 4005 |    parser_t       parser; 
 4006 |  
 4007 |    symbol_table.add_variable ("x", x); 
 4008 |    symbol_table.add_variable ("y", y); 
 4009 |    symbol_table.add_variable ("z", z); 
 4010 |    symbol_table.add_vector   ("v", v); 
 4011 |    symbol_table.add_stringvar("s", s); 
 4012 |  
 4013 |    parser.compile(expression_str, expression); 
 4014 |  
 4015 |    expression.value(); 
 4016 |  
 4017 |    typedef exprtk::results_context<T> results_context_t; 
 4018 |    const results_context_t& results = expression.results(); 
 4019 |  
 4020 |    if (results.count() == 4) 
 4021 |    { 
 4022 |       T result_x0; 
 4023 |       T result_x1; 
 4024 |       std::string result_s; 
 4025 |       std::vector<T> result_v; 
 4026 |  
 4027 |       results.get_scalar(0, result_x0); 
 4028 |       results.get_scalar(1, result_x1); 
 4029 |       results.get_string(3, result_s ); 
 4030 |       results.get_vector(2, result_v ); 
 4031 |    } 
 4032 |  
 4033 |  
 4034 | It is however recommended that if there is to be only a single flow of 
 4035 | execution  through  the  expression,  that  the  simpler  approach  of 
 4036 | registering external variables of appropriate type be used. 
 4037 |  
 4038 | This method simply requires the variables that are to hold the various 
 4039 | results that are to be computed within the expression to be registered 
 4040 | with an associated symbol_table  instance. Then within the  expression 
 4041 | itself  to  have  the result  variables  be  assigned the  appropriate 
 4042 | values. 
 4043 |  
 4044 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 4045 |    typedef exprtk::expression<double>   expression_t; 
 4046 |    typedef exprtk::parser<double>       parser_t; 
 4047 |  
 4048 |    const std::string expression_string = 
 4049 |       " var x := 123.456;     " 
 4050 |       " var s := 'ijk';       " 
 4051 |       " result0 := x + 78.90; " 
 4052 |       " result1 := s + '123'  " 
 4053 |  
 4054 |    double      result0; 
 4055 |    std::string result1; 
 4056 |  
 4057 |    symbol_table_t symbol_table; 
 4058 |    symbol_table.add_variable ("result0",result0); 
 4059 |    symbol_table.add_stringvar("result1",result1); 
 4060 |  
 4061 |    expression_t expression; 
 4062 |    expression.register_symbol_table(symbol_table); 
 4063 |  
 4064 |    parser_t parser; 
 4065 |    parser.compile(expression_string,expression); 
 4066 |  
 4067 |    expression.value(); 
 4068 |  
 4069 |    printf("Result0: %15.5f\n", result0        ); 
 4070 |    printf("Result1: %s\n"    , result1.c_str()); 
 4071 |  
 4072 |  
 4073 | In the example above, the expression will compute two results. As such 
 4074 | two result variables are defined to hold the values named result0  and 
 4075 | result1 respectively. The first is of scalar type (double), the second 
 4076 | is of  string type.  Once the  expression has  been evaluated, the two 
 4077 | variables will have been updated  with the new result values,  and can 
 4078 | then be further utilised from within the calling host program. 
 4079 |  
 4080 | There will be times when  an expression may have multiple  exit paths, 
 4081 | where not all the paths will be return-statement based. The  following 
 4082 | example builds upon the previous examples, but this time at least  one 
 4083 | path is not return based. 
 4084 |  
 4085 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 4086 |    typedef exprtk::expression<double>   expression_t; 
 4087 |    typedef exprtk::parser<double>       parser_t; 
 4088 |  
 4089 |    double x = 100.0; 
 4090 |    double y = 200.0; 
 4091 |  
 4092 |    symbol_table_t symbol_table; 
 4093 |    expression_t   expression; 
 4094 |    parser_t       parser; 
 4095 |  
 4096 |    symbol_table.add_variable ("x", x); 
 4097 |    symbol_table.add_variable ("y", y); 
 4098 |  
 4099 |    expression.register_symbol_table(symbol_table); 
 4100 |  
 4101 |    const std::string expression_string = 
 4102 |       " for (var i := 0; i < 10; i += 1)       " 
 4103 |       " {                                      " 
 4104 |       "    if (i > x)                          " 
 4105 |       "    {                                   " 
 4106 |       "       return [x + y, 'return-call 1']; " 
 4107 |       "    }                                   " 
 4108 |       "    else if (i > y)                     " 
 4109 |       "    {                                   " 
 4110 |       "       return [x - y, 'return-call 2']; " 
 4111 |       "    }                                   " 
 4112 |       " };                                     " 
 4113 |       "                                        " 
 4114 |       " x / y                                  " 
 4115 |  
 4116 |    parser.compile(expression_str, expression); 
 4117 |  
 4118 |    const auto result = expression.value(); 
 4119 |  
 4120 |    if (expression.return_invoked()) 
 4121 |    { 
 4122 |       const auto results = expression.results(); 
 4123 |  
 4124 |       for (std::size_t i = 0; i <  results.count(); ++i) 
 4125 |       { 
 4126 |          const auto& rtrn_result = results[i]; 
 4127 |          . 
 4128 |          . 
 4129 |          . 
 4130 |       } 
 4131 |    } 
 4132 |    else 
 4133 |    { 
 4134 |       printf("result: %f\n",result); 
 4135 |    } 
 4136 |  
 4137 |  
 4138 | After having called  the value method  on the expression,  calling the 
 4139 | return_invoked method will determine  if the expression completed  due 
 4140 | to a return statement being invoked or if it finished normally. 
 4141 |  
 4142 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 4143 |  
 4144 | [SECTION 21 - COMPILATION ERRORS] 
 4145 | When attempting to compile  a malformed or otherwise  erroneous ExprTk 
 4146 | expression, the  compilation process  will result  in an  error, as is 
 4147 | indicated  by  the  'compile'  method  returning  a  false  value.   A 
 4148 | diagnostic indicating the first error encountered and its cause can be 
 4149 | obtained by  invoking the  'error' method,  as is  demonstrated in the 
 4150 | following example: 
 4151 |  
 4152 |    if (!parser.compile(expression_string,expression)) 
 4153 |    { 
 4154 |       printf("Error: %s\n", parser.error().c_str()); 
 4155 |       return false; 
 4156 |    } 
 4157 |  
 4158 |  
 4159 | Any error(s) resulting from a failed compilation will be stored in the 
 4160 | parser instance until the next time a compilation is performed. Before 
 4161 | then errors can be enumerated  in the order they occurred  by invoking 
 4162 | the 'get_error' method which itself will return a 'parser_error' type. 
 4163 | A parser_error object will contain an error diagnostic, an error  mode 
 4164 | (or class), and the character position of the error in the  expression 
 4165 | string. The following example demonstrates the enumeration of error(s) 
 4166 | in the event of a failed compilation. 
 4167 |  
 4168 |    typedef exprtk::parser<T>          parser_t; 
 4169 |    typedef exprtk::parser_error::type error_t; 
 4170 |  
 4171 |    if (!parser.compile(expression_string,expression)) 
 4172 |    { 
 4173 |       for (std::size_t i = 0; i < parser.error_count(); ++i) 
 4174 |       { 
 4175 |          typedef exprtk::parser_error::type error_t; 
 4176 |  
 4177 |          error_t error = parser.get_error(i); 
 4178 |  
 4179 |          printf("Error[%02d] Position: %02d Type: [%14s] Msg: %s\n", 
 4180 |                 i, 
 4181 |                 error.token.position, 
 4182 |                 exprtk::parser_error::to_str(error.mode).c_str(), 
 4183 |                 error.diagnostic.c_str()); 
 4184 |       } 
 4185 |  
 4186 |       return false; 
 4187 |    } 
 4188 |  
 4189 |  
 4190 | Assuming the  following expression '2 + (3 / log(1 + x))' which uses a 
 4191 | variable named 'x'  that has not been registered  with the appropriate 
 4192 | symbol_table  instance and  is not  a locally  defined variable,  once 
 4193 | compiled the  above denoted post compilation error handling code shall 
 4194 | produce the following output: 
 4195 |  
 4196 |   Error[00] Pos:17 Type:[Syntax] Msg: ERR184 - Undefined symbol: 'x' 
 4197 |  
 4198 |  
 4199 | For  expressions  comprised  of  multiple  lines,  the  error position 
 4200 | provided in the  parser_error object can  be converted into  a pair of 
 4201 | line and column numbers by invoking the 'update_error' function as  is 
 4202 | demonstrated by the following example: 
 4203 |  
 4204 |    if (!parser.compile(program_str,expression)) 
 4205 |    { 
 4206 |       for (std::size_t i = 0; i < parser.error_count(); ++i) 
 4207 |       { 
 4208 |          typedef exprtk::parser_error::type error_t; 
 4209 |  
 4210 |          error_t error = parser.get_error(i); 
 4211 |  
 4212 |          exprtk::parser_error::update_error(error,program_str); 
 4213 |  
 4214 |          printf("Error[%0lu] at line: %lu column: %lu\n", 
 4215 |                 i, 
 4216 |                 error.line_no, 
 4217 |                 error.column_no); 
 4218 |       } 
 4219 |  
 4220 |       return false; 
 4221 |    } 
 4222 |  
 4223 |  
 4224 | Note32: There are five distinct error modes in ExprTk which denote the 
 4225 | class of an error. These classes are as follows: 
 4226 |  
 4227 |    (a) Syntax 
 4228 |    (b) Token 
 4229 |    (c) Numeric 
 4230 |    (d) Symbol Table 
 4231 |    (e) Lexer 
 4232 |  
 4233 |  
 4234 | (a) Syntax Errors 
 4235 | These are errors  related to invalid  syntax found within  the denoted 
 4236 | expression. Examples are invalid sequences of operators and variables, 
 4237 | incorrect number  of parameters  to functions,  invalid conditional or 
 4238 | loop structures and invalid use of keywords. 
 4239 |  
 4240 |    eg:  'for := sin(x,y,z) + 2 * equal > until[2 - x,3]' 
 4241 |  
 4242 |  
 4243 | (b) Token Errors 
 4244 | Errors in this class relate to  token level errors detected by one  or 
 4245 | more of the following checkers: 
 4246 |  
 4247 |    (1) Bracket Checker 
 4248 |    (2) Numeric Checker 
 4249 |    (3) Sequence Checker 
 4250 |  
 4251 |  
 4252 | (c) Numeric Errors 
 4253 | This class of  error is related  to conversion of  numeric values from 
 4254 | their  string form  to the  underlying numerical  type (float,  double 
 4255 | etc). 
 4256 |  
 4257 | (d) Symbol Table Errors 
 4258 | This is the class of errors related to failures when interacting  with 
 4259 | the registered symbol_table instance. Errors such as not being able to 
 4260 | find,  within  the  symbol_table,  symbols  representing  variables or 
 4261 | functions, to being unable to create new variables in the symbol_table 
 4262 | via the 'unknown symbol resolver' mechanism. 
 4263 |  
 4264 | Note33: The function compositor  also supports  error message handling 
 4265 | similar to how it is  done via the parser. The  following demonstrates 
 4266 | how after a failed function  composition the associated errors can  be 
 4267 | enumerated. 
 4268 |  
 4269 |    typedef exprtk::function_compositor<T>  compositor_t; 
 4270 |    typedef typename compositor_t::function function_t; 
 4271 |  
 4272 |    compositor_t compositor; 
 4273 |  
 4274 |    const bool compositor_result = 
 4275 |    compositor.add( 
 4276 |       function_t("foobar") 
 4277 |       .vars("x","y") 
 4278 |       .expression 
 4279 |       ( " x + y / z " )); 
 4280 |  
 4281 |    if (!compositor_result) 
 4282 |    { 
 4283 |       printf("Error: %s\n", compositor.error().c_str()); 
 4284 |  
 4285 |       for (std::size_t i = 1; i < compositor.error_count(); ++i) 
 4286 |       { 
 4287 |          typedef exprtk::parser_error::type error_t; 
 4288 |  
 4289 |          error_t error = compositor.get_error(i); 
 4290 |  
 4291 |          printf("Err No.: %02d  Pos: %02d  Type: [%14s] Msg: %s\n", 
 4292 |                 static_cast<unsigned int>(i), 
 4293 |                 static_cast<unsigned int>(error.token.position), 
 4294 |                 exprtk::parser_error::to_str(error.mode).c_str(), 
 4295 |                 error.diagnostic.c_str()); 
 4296 |       } 
 4297 |    } 
 4298 |  
 4299 |  
 4300 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 4301 |  
 4302 | [SECTION 22 - RUNTIME LIBRARY PACKAGES] 
 4303 | ExprTk includes  a range  of extensions,  that provide functionalities 
 4304 | beyond simple numerical calculations. Currently the available packages 
 4305 | are: 
 4306 |  
 4307 |   +---+--------------------+-----------------------------------+ 
 4308 |   | # |    Package Name    |          Namespace/Type           | 
 4309 |   +---+--------------------+-----------------------------------+ 
 4310 |   | 1 | Basic I/O          | exprtk::rtl::io::package<T>       | 
 4311 |   | 2 | File I/O           | exprtk::rtl::io::file::package<T> | 
 4312 |   | 3 | Vector Operations  | exprtk::rtl::vecops::package<T>   | 
 4313 |   +---+--------------------+-----------------------------------+ 
 4314 |  
 4315 |  
 4316 | In order to make the  features of a specific package  available within 
 4317 | an  expression,  an instance  of  the package  must  be added  to  the 
 4318 | expression's associated  symbol table.  In the  following example, the 
 4319 | file I/O package is made available for the given expression: 
 4320 |  
 4321 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 4322 |    typedef exprtk::expression<T>   expression_t; 
 4323 |    typedef exprtk::parser<T>       parser_t; 
 4324 |  
 4325 |    exprtk::rtl::io::file::package<T> fileio_package; 
 4326 |  
 4327 |    const std::string expression_string = 
 4328 |       " var file_name := 'file.txt';       " 
 4329 |       " var stream    := null;             " 
 4330 |       "                                    " 
 4331 |       " stream := open(file_name,'w');     " 
 4332 |       "                                    " 
 4333 |       " write(stream,'Hello world....\n'); " 
 4334 |       "                                    " 
 4335 |       " close(stream);                     " 
 4336 |       "                                    " 
 4337 |  
 4338 |    symbol_table_t symbol_table; 
 4339 |    symbol_table.add_package(fileio_package); 
 4340 |  
 4341 |    expression_t expression; 
 4342 |    expression.register_symbol_table(symbol_table); 
 4343 |  
 4344 |    parser_t parser; 
 4345 |    parser.compile(expression_string,expression); 
 4346 |  
 4347 |    expression.value(); 
 4348 |  
 4349 |  
 4350 | (1) Basic I/O functions: 
 4351 |  
 4352 |    (a) print 
 4353 |    (b) println 
 4354 |  
 4355 | (2) File I/O functions: 
 4356 |  
 4357 |    (a) open    (b) close 
 4358 |    (c) write   (d) read 
 4359 |    (e) getline (f) eof 
 4360 |  
 4361 | (3) Vector Operations functions: 
 4362 |  
 4363 | (a) all_true     (b) all_false 
 4364 | (c) any_true     (d) any_false 
 4365 | (e) assign       (f) count 
 4366 | (g) copy         (h) reverse 
 4367 | (i) rotate-left  (j) rotate-right 
 4368 | (k) shift-left   (l) shift-right 
 4369 | (m) sort         (n) nth_element 
 4370 | (o) iota         (p) sumk 
 4371 | (q) axpy         (r) axpby 
 4372 | (s) axpyz        (t) axpbyz 
 4373 | (u) axpbz        (v) dot 
 4374 | (w) dotk         (x) diff 
 4375 |  
 4376 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 4377 |  
 4378 | [SECTION 23 - HELPERS & UTILS] 
 4379 | The  ExprTk library  provides a  series of  usage simplifications  via 
 4380 | helper routines that combine various processes into a single 'function 
 4381 | call'  making  certain  actions   easier  to  carry  out   though  not 
 4382 | necessarily in the most efficient way possible. A list of the routines 
 4383 | are as follows: 
 4384 |  
 4385 |    (a) collect_variables 
 4386 |    (b) collect_functions 
 4387 |    (c) compute 
 4388 |    (d) integrate 
 4389 |    (e) derivative 
 4390 |    (f) second_derivative 
 4391 |    (g) third_derivative 
 4392 |  
 4393 |  
 4394 | (a) collect_variables 
 4395 | This function will collect all the variable symbols in a given  string 
 4396 | representation of an expression and  return them in an STL  compatible 
 4397 | sequence  data structure  (eg: std::vector,  dequeue etc)  specialised 
 4398 | upon a std::string type. If an error occurs during the parsing of  the 
 4399 | expression  then  the return  value  of the  function  will be  false, 
 4400 | otherwise it will be  true. An example use  of the given routine is as 
 4401 | follows: 
 4402 |  
 4403 |    const std::string expression = "x + abs(y / z)" 
 4404 |  
 4405 |    std::vector<std::string> variable_list; 
 4406 |  
 4407 |    if (exprtk::collect_variables(expression, variable_list)) 
 4408 |    { 
 4409 |       for (const auto& var : variable_list) 
 4410 |       { 
 4411 |          ... 
 4412 |       } 
 4413 |    } 
 4414 |    else 
 4415 |      printf("An error occurred."); 
 4416 |  
 4417 |  
 4418 | (b) collect_functions 
 4419 | This function will collect all the function symbols in a given  string 
 4420 | representation of an expression and  return them in an STL  compatible 
 4421 | sequence  data structure  (eg: std::vector,  dequeue etc)  specialised 
 4422 | upon a std::string type. If an error occurs during the parsing of  the 
 4423 | expression  then  the return  value  of the  function  will be  false, 
 4424 | otherwise it  will be true. An example  use of the given routine is as 
 4425 | follows: 
 4426 |  
 4427 |    const std::string expression = "x + abs(y / cos(1 + z))" 
 4428 |  
 4429 |    std::deque<std::string> function_list; 
 4430 |  
 4431 |    if (exprtk::collect_functions(expression, function_list)) 
 4432 |    { 
 4433 |       for (const auto& func : function_list) 
 4434 |       { 
 4435 |          ... 
 4436 |       } 
 4437 |    } 
 4438 |    else 
 4439 |      printf("An error occurred."); 
 4440 |  
 4441 |  
 4442 | Note34: When  either the  'collect_variables'  or  'collect_functions' 
 4443 | free functions return  true - that  does not necessarily  indicate the 
 4444 | expression itself is  valid. It is  still possible that  when compiled 
 4445 | the expression may have certain  'type' related errors - though  it is 
 4446 | highly likely  that no  semantic errors  will occur  if either  return 
 4447 | true. 
 4448 |  
 4449 | Note35: The default interface provided for both the  collect_variables 
 4450 | and collect_functions  free_functions, assumes  that expressions  will 
 4451 | only be  utilising the  ExprTk reserved  functions (eg:  abs, cos, min 
 4452 | etc). When user defined functions are  to be used in an expression,  a 
 4453 | symbol_table  instance  containing  said functions  can  be  passed to 
 4454 | either routine, and  will be incorporated  during the compilation  and 
 4455 | Dependent Entity  Collection processes.  In the  following example,  a 
 4456 | user  defined  free  function   named  'foo'  is  registered   with  a 
 4457 | symbol_table.  Finally  the   symbol_table  instance  and   associated 
 4458 | expression string are passed to the exprtk::collect_functions routine. 
 4459 |  
 4460 |    template <typename T> 
 4461 |    T foo(T v) 
 4462 |    { 
 4463 |       return std::abs(v + T(2)) / T(3); 
 4464 |    } 
 4465 |  
 4466 |    ...... 
 4467 |  
 4468 |    exprtk::symbol_table<T> sym_tab; 
 4469 |  
 4470 |    symbol_table.add_function("foo",foo); 
 4471 |  
 4472 |    const std::string expression = "x + foo(y / cos(1 + z))" 
 4473 |  
 4474 |    std::deque<std::string> function_list; 
 4475 |  
 4476 |    if (exprtk::collect_functions(expression, sym_tab, function_list)) 
 4477 |    { 
 4478 |       for (const auto& func : function_list) 
 4479 |       { 
 4480 |          ... 
 4481 |       } 
 4482 |    } 
 4483 |    else 
 4484 |      printf("An error occurred."); 
 4485 |  
 4486 |  
 4487 | (c) compute 
 4488 | This free function  will compute the  value of an  expression from its 
 4489 | string form.  If an  invalid expression  is passed,  the result of the 
 4490 | function will be false indicating an error, otherwise the return value 
 4491 | will  be  true  indicating success.  The  compute  function has  three 
 4492 | overloads, the definitions of which are: 
 4493 |  
 4494 |    (1) No variables 
 4495 |    (2) One variable called x 
 4496 |    (3) Two variables called x and y 
 4497 |    (3) Three variables called x, y and z 
 4498 |  
 4499 |  
 4500 | Example uses of  each of the  three overloads for  the compute routine 
 4501 | are as follows: 
 4502 |  
 4503 |    T result = T(0); 
 4504 |  
 4505 |    // No variables overload 
 4506 |    const std::string no_vars = "abs(1 - (3 / pi)) * 5" 
 4507 |  
 4508 |    if (!exprtk::compute(no_vars,result)) 
 4509 |       printf("Failed to compute: %s",no_vars.c_str()); 
 4510 |    else 
 4511 |       printf("Result: %15.5f\n",result); 
 4512 |  
 4513 |    // One variable 'x' overload 
 4514 |    T x = T(123.456); 
 4515 |  
 4516 |    const std::string one_var = "abs(x - (3 / pi)) * 5" 
 4517 |  
 4518 |    if (!exprtk::compute(one_var, x, result)) 
 4519 |       printf("Failed to compute: %s",one_var.c_str()); 
 4520 |    else 
 4521 |       printf("Result: %15.5f\n",result); 
 4522 |  
 4523 |    // Two variables 'x' and 'y' overload 
 4524 |    T y = T(789.012); 
 4525 |  
 4526 |    const std::string two_var = "abs(x - (y / pi)) * 5" 
 4527 |  
 4528 |    if (!exprtk::compute(two_var, x, y, result)) 
 4529 |       printf("Failed to compute: %s",two_var.c_str()); 
 4530 |    else 
 4531 |       printf("Result: %15.5f\n",result); 
 4532 |  
 4533 |    // Three variables 'x', 'y' and 'z' overload 
 4534 |    T z = T(345.678); 
 4535 |  
 4536 |    const std::string three_var = "abs(x - (y / pi)) * z" 
 4537 |  
 4538 |    if (!exprtk::compute(three_var, x, y, z, result)) 
 4539 |       printf("Failed to compute: %s",three_var.c_str()); 
 4540 |    else 
 4541 |       printf("Result: %15.5f\n",result); 
 4542 |  
 4543 |  
 4544 | (d) integrate 
 4545 | This free function will attempt to perform a numerical integration  of 
 4546 | a single variable compiled expression over a specified range and  step 
 4547 | size. The numerical  integration is based  on the three  point form of 
 4548 | Simpson's rule. The  integrate function has  two overloads, where  the 
 4549 | variable of integration can  either be passed as  a reference or as  a 
 4550 | name in string form. Example usage of the function is as follows: 
 4551 |  
 4552 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 4553 |    typedef exprtk::expression<T>   expression_t; 
 4554 |    typedef exprtk::parser<T>       parser_t; 
 4555 |  
 4556 |    const std::string expression_string = "sqrt(1 - (x^2))" 
 4557 |  
 4558 |    T x = T(0); 
 4559 |  
 4560 |    symbol_table_t symbol_table; 
 4561 |    symbol_table.add_variable("x",x); 
 4562 |  
 4563 |    expression_t expression; 
 4564 |    expression.register_symbol_table(symbol_table); 
 4565 |  
 4566 |    parser_t parser; 
 4567 |    parser.compile(expression_string,expression); 
 4568 |  
 4569 |    .... 
 4570 |  
 4571 |    // Integrate in domain [-1,1] using a reference to x variable 
 4572 |    T area1 = exprtk::integrate(expression, x, T(-1), T(1)); 
 4573 |  
 4574 |    // Integrate in domain [-1,1] using name of x variable 
 4575 |    T area2 = exprtk::integrate(expression, "x", T(-1), T(1)); 
 4576 |  
 4577 |  
 4578 | (e) derivative 
 4579 | This free function will attempt to perform a numerical differentiation 
 4580 | of a single variable compiled expression at a given point for a  given 
 4581 | epsilon, using a  variant of Newton's  difference quotient called  the 
 4582 | five-point stencil method. The derivative function has two  overloads, 
 4583 | where  the  variable of  differentiation  can either  be  passed as  a 
 4584 | reference or as a name in string form. Example usage of the derivative 
 4585 | function is as follows: 
 4586 |  
 4587 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 4588 |    typedef exprtk::expression<T>   expression_t; 
 4589 |    typedef exprtk::parser<T>       parser_t; 
 4590 |  
 4591 |    const std::string expression_string = "sqrt(1 - (x^2))" 
 4592 |  
 4593 |    T x = T(0); 
 4594 |  
 4595 |    symbol_table_t symbol_table; 
 4596 |    symbol_table.add_variable("x",x); 
 4597 |  
 4598 |    expression_t expression; 
 4599 |    expression.register_symbol_table(symbol_table); 
 4600 |  
 4601 |    parser_t parser; 
 4602 |    parser.compile(expression_string,expression); 
 4603 |  
 4604 |    .... 
 4605 |  
 4606 |    // Differentiate expression at value of x = 12.3 using a reference 
 4607 |    // to the x variable 
 4608 |    x = T(12.3); 
 4609 |    T derivative1 = exprtk::derivative(expression, x); 
 4610 |  
 4611 |    // Differentiate expression where value x = 45.6 using name 
 4612 |    // of the x variable 
 4613 |    x = T(45.6); 
 4614 |    T derivative2 = exprtk::derivative(expression, "x"); 
 4615 |  
 4616 |  
 4617 | (f) second_derivative 
 4618 | This  free  function  will  attempt  to  perform  a  numerical  second 
 4619 | derivative of a single variable  compiled expression at a given  point 
 4620 | for a given epsilon, using  a variant of Newton's difference  quotient 
 4621 | method. The second_derivative function  has  two overloads, where  the 
 4622 | variable of differentiation can either be passed as a reference or  as 
 4623 | a name in string form. Example usage of the second_derivative function 
 4624 | is as follows: 
 4625 |  
 4626 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 4627 |    typedef exprtk::expression<T>   expression_t; 
 4628 |    typedef exprtk::parser<T>       parser_t; 
 4629 |  
 4630 |    const std::string expression_string = "sqrt(1 - (x^2))" 
 4631 |  
 4632 |    T x = T(0); 
 4633 |  
 4634 |    symbol_table_t symbol_table; 
 4635 |    symbol_table.add_variable("x",x); 
 4636 |  
 4637 |    expression_t expression; 
 4638 |    expression.register_symbol_table(symbol_table); 
 4639 |  
 4640 |    parser_t parser; 
 4641 |    parser.compile(expression_string,expression); 
 4642 |  
 4643 |    .... 
 4644 |  
 4645 |    // Second derivative of expression where value of x = 12.3 using a 
 4646 |    // reference to x variable 
 4647 |    x = T(12.3); 
 4648 |    T derivative1 = exprtk::second_derivative(expression,x); 
 4649 |  
 4650 |    // Second derivative of expression where value of x = 45.6 using 
 4651 |    // name of x variable 
 4652 |    x = T(45.6); 
 4653 |    T derivative2 = exprtk::second_derivative(expression, "x"); 
 4654 |  
 4655 |  
 4656 | (g) third_derivative 
 4657 | This  free  function  will  attempt  to  perform  a  numerical   third 
 4658 | derivative of a single variable  compiled expression at a given  point 
 4659 | for a given epsilon, using  a variant of Newton's difference  quotient 
 4660 | method. The  third_derivative function  has two  overloads, where  the 
 4661 | variable of differentiation can either be passed as a reference or  as 
 4662 | a name in string form. Example  usage of the third_derivative function 
 4663 | is as follows: 
 4664 |  
 4665 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 4666 |    typedef exprtk::expression<T>   expression_t; 
 4667 |    typedef exprtk::parser<T>       parser_t; 
 4668 |  
 4669 |    const std::string expression_string = "sqrt(1 - (x^2))" 
 4670 |  
 4671 |    T x = T(0); 
 4672 |  
 4673 |    symbol_table_t symbol_table; 
 4674 |    symbol_table.add_variable("x",x); 
 4675 |  
 4676 |    expression_t expression; 
 4677 |    expression.register_symbol_table(symbol_table); 
 4678 |  
 4679 |    parser_t parser; 
 4680 |    parser.compile(expression_string,expression); 
 4681 |  
 4682 |    .... 
 4683 |  
 4684 |    // Third derivative of expression where value of x = 12.3 using a 
 4685 |    // reference to the x variable 
 4686 |    x = T(12.3); 
 4687 |    T derivative1 = exprtk::third_derivative(expression, x); 
 4688 |  
 4689 |    // Third derivative of expression where value of x = 45.6 using 
 4690 |    // name of the x variable 
 4691 |    x = T(45.6); 
 4692 |    T derivative2 = exprtk::third_derivative(expression, "x"); 
 4693 |  
 4694 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 4695 |  
 4696 | [SECTION 24 - RUNTIME CHECKS] 
 4697 | The  ExprTk library   provides the ability  to perform runtime  checks 
 4698 | during expression evaluation so as to ensure memory access  violations 
 4699 | errors  are  caught and  handled  without causing further  issues. The 
 4700 | checks typically cover: 
 4701 |  
 4702 |    1. Vector access and handling 
 4703 |    2. String access and handling 
 4704 |    3. Loop iteration checks 
 4705 |    4. Compilation checkpointing 
 4706 |    5. Assert statements 
 4707 |  
 4708 |  
 4709 | (1) Vector Access Runtime Checks 
 4710 | Expressions that contain vectors where elements of the vectors may  be 
 4711 | accessed using  indexes that  can only  be determined  at runtime  may 
 4712 | result  in  memory  access violations  when the  index is  out of  the 
 4713 | vector's  bound.  Some  examples  of  problematic  expressions  are as 
 4714 | follows: 
 4715 |  
 4716 |    1. vec[i] 
 4717 |    2. vec[i + j] 
 4718 |    3. vec[i + 10] 
 4719 |    4. vec[i + vec[]] := x + y 
 4720 |    5. vec[i + j] <=> vec[i] 
 4721 |    6. vec[i + j] := (vec1 + vec2)[i + j] 
 4722 |  
 4723 |  
 4724 | In the above expressions,  it is assumed that  the values used in  the 
 4725 | index operator  may either  exceed the  vector bounds  or precede  the 
 4726 | vector's start, In  short, the indexes  may not necessarily  be within 
 4727 | the range [0,vec[]). 
 4728 |  
 4729 | ExprTk provides the ability to inject a runtime check at the point  of 
 4730 | index evaluation and  handle situations where  the index violates  the 
 4731 | vector's  bounds.  This  capability is  done  by  registering a  user- 
 4732 | implemented Vector Access Runtime  Check (VARTC) to the  parser before 
 4733 | expression compilation. Initially a VARTC can be defined as follows: 
 4734 |  
 4735 |    struct my_vector_access_rtc final : 
 4736 |       public exprtk::vector_access_runtime_check 
 4737 |    { 
 4738 |       bool handle_runtime_violation(violation_context& context) 
 4739 |       override 
 4740 |       { 
 4741 |          // Handling of the violation 
 4742 |          return ...; 
 4743 |       } 
 4744 |    }; 
 4745 |  
 4746 |  
 4747 | Then an instance of the VARTC can be registered with a parser instance 
 4748 | as follows: 
 4749 |  
 4750 |    my_vector_access_rtc vartc; 
 4751 |  
 4752 |    exprtk::symbol_table<T> symbol_table; 
 4753 |  
 4754 |    T i; 
 4755 |    T x; 
 4756 |    T y; 
 4757 |    std::vector<T> vec = { 0, 1, 2, 3, 4 }; 
 4758 |  
 4759 |    symbol_table.add_variable("i"  , i  ); 
 4760 |    symbol_table.add_variable("x"  , x  ); 
 4761 |    symbol_table.add_variable("y"  , y  ); 
 4762 |    symbol_table.add_vector  ("vec", vec); 
 4763 |  
 4764 |    exprtk::expression<T> expression; 
 4765 |    exprtk::parser<T> parser; 
 4766 |  
 4767 |    parser.register_vector_access_runtime_check(vartc); 
 4768 |  
 4769 |    std::string expression = "vec[i + vec[]] := x + y" 
 4770 |  
 4771 |    parser.compile(expression_str, expression); 
 4772 |  
 4773 |    try 
 4774 |    { 
 4775 |       expression.value(); 
 4776 |    } 
 4777 |    catch (std::runtime_error& rte) 
 4778 |    { 
 4779 |       printf("Exception: %s\n", rte.what()); 
 4780 |    } 
 4781 |  
 4782 |  
 4783 | Note36: The  lifetime of  any parser  or expression  instance must not 
 4784 | exceed that of any VARTC instance that has been registered with it. 
 4785 |  
 4786 | When a vector access violation occurs, the registered VARTC instance's 
 4787 | handle_runtime_violation method  will be  invoked, coupled  with it  a 
 4788 | violation_context shall  be provided  that will  contain the following 
 4789 | members: 
 4790 |  
 4791 |   1. base_ptr: Of type void*,  which points to the  first element 
 4792 |      of the vector.  The base_ptr can  also be used  as a key  to 
 4793 |      determine the  vector upon  which the  access violation  has 
 4794 |      occurred. 
 4795 |  
 4796 |   2. end_ptr : Of type void*, which points to one position  after 
 4797 |      the last element of the vector 
 4798 |  
 4799 |   3. access_ptr: Of  type void*,  points to  the memory  location 
 4800 |      which is the base_ptr offset by the derived index value. 
 4801 |  
 4802 |   4. type_size: Size of the vector's element type in bytes. This 
 4803 |      value can be used to  determine  the number of  elements in 
 4804 |      the vector based on the base_ptr and end_ptr. 
 4805 |  
 4806 |  
 4807 | The implementation of the handle_runtime_violation method can at this 
 4808 | point perform various actions such as: 
 4809 |  
 4810 |   1. Log the violation 
 4811 |   2. Throw an exception (eg: std::runtime_error) 
 4812 |   3. Remedy the access_ptr to allow for the evaluation to continue 
 4813 |  
 4814 |  
 4815 | Note37: When employing option [3],  handle_runtime_violation needs  to 
 4816 | return  true,  otherwise  the  caller  will assume an unhandled access 
 4817 | violation and default to using the base_ptr. 
 4818 |  
 4819 | It is  recommended, at  the  very least,  to throw an  exception  when 
 4820 | handling vector access violations and to only consider option [3] when 
 4821 | the the ramifications of changing the access_ptr are well understood. 
 4822 |  
 4823 | The following are simple examples of how the  handle_runtime_violation 
 4824 | can be implemented. 
 4825 |  
 4826 | Example 1: Log the access violation to stdout and then throw a runtime 
 4827 | error exception: 
 4828 |  
 4829 |    bool handle_runtime_violation(violation_context& context) override 
 4830 |    { 
 4831 |       printf("ERROR -  Runtime vector access violation. " 
 4832 |              "base: %p end: %p access: %p typesize: %lu\n", 
 4833 |              context.base_ptr  , 
 4834 |              context.end_ptr   , 
 4835 |              context.access_ptr, 
 4836 |              context.type_size); 
 4837 |  
 4838 |       throw std::runtime_error("Runtime vector access violation."); 
 4839 |       return false; 
 4840 |    } 
 4841 |  
 4842 |  
 4843 | Example 2: Handle the access violation by resetting the access pointer 
 4844 | to the last value in the vector. 
 4845 |  
 4846 |    bool handle_runtime_violation(violation_context& context) override 
 4847 |    { 
 4848 |       context.access_ptr = 
 4849 |          static_cast<char*>(context.end_ptr) - context.type_size; 
 4850 |       return true; 
 4851 |    } 
 4852 |  
 4853 |  
 4854 | Note38: The return value  of true  in the above handler method signals 
 4855 | the caller to continue the vector access using the updated access_ptr. 
 4856 |  
 4857 |  
 4858 | (2) String Access Runtime Checks 
 4859 | Expressions that contain strings  where elements or substrings  of the 
 4860 | strings may be accessed using  indexes that can only be  determined at 
 4861 | runtime may result in memory access violations when the index or range 
 4862 | is out of the string's bound. Examples of problematic expressions  are 
 4863 | as follows: 
 4864 |  
 4865 |    1. s[i : j + k] 
 4866 |    2. s[i : j + k][-x : y] 
 4867 |    3. (s1 + s2)[i : j + k] 
 4868 |    4. '01234'[5 + i] 
 4869 |    5. s += s[i : j + k] 
 4870 |    6. s[i : j + k] := 'chappy days'[1 : ] 
 4871 |  
 4872 |  
 4873 | To enable string access runtime checks all  one needs to  do is simply 
 4874 | use the following  define before the  ExprTk header is  included or as 
 4875 | part of the compilation define parameters: 
 4876 |  
 4877 |    exprtk_enable_range_runtime_checks 
 4878 |  
 4879 |  
 4880 | When  the above  define is used,  and a string  related runtime access 
 4881 | violation occurs  a std::runtime_error  exception will  be thrown. The 
 4882 | following  demonstrates  the  general  flow  of  handling  the  access 
 4883 | violation: 
 4884 |  
 4885 |    parser.compile(expression_string, expression) 
 4886 |    . 
 4887 |    . 
 4888 |    try 
 4889 |    { 
 4890 |       expression.value(); 
 4891 |    } 
 4892 |    catch (std::runtime_error& rte) 
 4893 |    { 
 4894 |       printf("Exception: %s\n", rte.what()); 
 4895 |    } 
 4896 |  
 4897 |  
 4898 | (3) Loop Iteration Checks 
 4899 | Expressions that contain loop structures (eg: for/while/repeat et  al) 
 4900 | can be problematic from a usage point of view due to the difficulty in 
 4901 | determining the following: 
 4902 |  
 4903 |    1. Will the loop ever complete (aka is this an infinite loop?) 
 4904 |    2. Maximum loop execution time 
 4905 |  
 4906 |  
 4907 | ExprTk provides  the ability  to inject  a runtime  check within  loop 
 4908 | conditionals, and to  have the result  of the check  either signal the 
 4909 | loop to continue or for the check to raise a loop violation error. 
 4910 |  
 4911 | The process involves instantiating a user defined   loop_runtime_check 
 4912 | (LRTC), registering  the instance  with a  exprtk::parser instance and 
 4913 | specifying  which  loop types  the  check is  to  performed upon.  The 
 4914 | following code demonstrates a how custom LRTC can be instantiated  and 
 4915 | registered with the associated parser: 
 4916 |  
 4917 |    typedef exprtk::parser<T> parser_t; 
 4918 |    typedef exprtk::loop_runtime_check loop_runtime_check_t; 
 4919 |  
 4920 |    my_loop_rtc loop_rtc; 
 4921 |    loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; 
 4922 |    loop_runtime_check.max_loop_iterations = 100000; 
 4923 |  
 4924 |    parser_t parser; 
 4925 |  
 4926 |    parser.register_loop_runtime_check(loop_rtc); 
 4927 |  
 4928 |  
 4929 | The following is an example of how one could derive from and implement 
 4930 | a custom loop_runtime_check: 
 4931 |  
 4932 |    struct my_loop_rtc final : exprtk::loop_runtime_check 
 4933 |    { 
 4934 |  
 4935 |       bool check() override 
 4936 |       { 
 4937 |          // 
 4938 |          return ... 
 4939 |       } 
 4940 |  
 4941 |       void handle_runtime_violation 
 4942 |          (const exprtk::violation_context&) override 
 4943 |       { 
 4944 |          throw std::runtime_error("Loop runtime violation."); 
 4945 |       } 
 4946 |    }; 
 4947 |  
 4948 |  
 4949 | In the above  code, if either  the check method  returns false or  the 
 4950 | loop  iteration  count  exceeds  the  max_loop_iterations  value,  the 
 4951 | handle_runtime_violation method  will be  invoked, coupled  with it  a 
 4952 | violation_context shall  be provided  that will  contain the following 
 4953 | members: 
 4954 |  
 4955 |    1. loop: Of  type loop_types.  This value  denotes the  type of 
 4956 |       loop that triggered the violation (e_for_loop, e_while_loop, 
 4957 |       e_repeat_until_loop). 
 4958 |  
 4959 |    2. violation:  Of type  type. This  value denotes  the type  of 
 4960 |       violation (e_iteration_count, e_timeout) 
 4961 |  
 4962 |    3. iteration_count: Of type uint64_t. The number of  iterations 
 4963 |       that the triggering loop has executed since the start of the 
 4964 |       expression. 
 4965 |  
 4966 |  
 4967 | Note39: The  lifetime of  any parser  or expression  instance must not 
 4968 | exceed that of any LRTC instance that has been registered with it. 
 4969 |  
 4970 | The following is an  example implementation of an  LRTC that 
 4971 | supports loop timeout violations: 
 4972 |  
 4973 |    struct timeout_loop_rtc final : exprtk::loop_runtime_check 
 4974 |    { 
 4975 |       using time_point_t = 
 4976 |          std::chrono::time_point<std::chrono::steady_clock>; 
 4977 |  
 4978 |       std::size_t iterations_ = 0; 
 4979 |       time_point_t timeout_tp_; 
 4980 |  
 4981 |       bool check() override 
 4982 |       { 
 4983 |          if (std::chrono::steady_clock::now() >= timeout_tp_) 
 4984 |          { 
 4985 |             // handle_runtime_violation shall be invoked 
 4986 |             return false; 
 4987 |          } 
 4988 |  
 4989 |          return true; 
 4990 |       } 
 4991 |  
 4992 |       void handle_runtime_violation 
 4993 |          (const exprtk::violation_context&) override 
 4994 |       { 
 4995 |          throw std::runtime_error("Loop timed out"); 
 4996 |       } 
 4997 |  
 4998 |       void set_timeout_time(const time_point_t& timeout_tp) 
 4999 |       { 
 5000 |          timeout_tp_ = timeout_tp; 
 5001 |       } 
 5002 |    }; 
 5003 |  
 5004 |  
 5005 | In the above code, the check method shall be invoked on each iteration 
 5006 | of the associated loop. Within the method the current time is compared 
 5007 | to the setup timeout time-point, in the event the current time exceeds 
 5008 | the timeout, the method returns false, triggering the violation, which 
 5009 | in turn will result in the handle_runtime_violation being invoked. 
 5010 |  
 5011 | The following code demonstrates how the above defined LRTC can be used 
 5012 | to ensure that at the very least the loop portion(s) of an  expression 
 5013 | will never exceed a given amount of execution time. 
 5014 |  
 5015 |    typedef exprtk::parser<T> parser_t; 
 5016 |    typedef exprtk::loop_runtime_check loop_runtime_check_t; 
 5017 |  
 5018 |    my_loop_rtc loop_rtc; 
 5019 |    loop_rtc.loop_set = loop_runtime_check_t::e_all_loops; 
 5020 |    loop_rtc.max_loop_iterations = 100000; 
 5021 |  
 5022 |    parser_t parser; 
 5023 |  
 5024 |    parser.register_loop_runtime_check(loop_rtc); 
 5025 |    . 
 5026 |    . 
 5027 |    . 
 5028 |    . 
 5029 |    using std::chrono; 
 5030 |    const auto max_duration = seconds(25); 
 5031 |  
 5032 |    try 
 5033 |    { 
 5034 |       loop_rtc.set_timeout_time(steady_clock::now() + max_duration); 
 5035 |       expression.value(); 
 5036 |  
 5037 |       loop_rtc.set_timeout_time(steady_clock::now() + max_duration); 
 5038 |       expression.value(); 
 5039 |  
 5040 |       loop_rtc.set_timeout_time(steady_clock::now() + max_duration); 
 5041 |       expression.value(); 
 5042 |  
 5043 |    } 
 5044 |    catch(std::runtime_error& exception) 
 5045 |    { 
 5046 |       printf("Exception: %s\n",exception.what()); 
 5047 |    } 
 5048 |  
 5049 |  
 5050 | (4) Compilation Process Checkpointing 
 5051 | When compiling an expression, one may require the compilation  process 
 5052 | to periodically  checkpoint its  internal state,  subsequently at  the 
 5053 | checkpoint one can then make the decision to continue the  compilation 
 5054 | process or to immediately terminate and return. 
 5055 |  
 5056 | The following are reasons one  may want to checkpoint the  compilation 
 5057 | process: 
 5058 |  
 5059 |    1. Determine if the compilation process has run for far too long 
 5060 |    2. Determine if the current stack frame size exceeds a limit 
 5061 |    3. Enforce an external termination request 
 5062 |  
 5063 |  
 5064 | ExprTk  provides  the  ability   to  inject  a  checkpoint   into  the 
 5065 | compilation  process  that   will  be  evaluated   periodically.  This 
 5066 | capability is achieved  by registering a  user-implemented compilation 
 5067 | check (CCK) to the parser  before expression  compilation. Initially a 
 5068 | CCK can be defined as follows: 
 5069 |  
 5070 |    struct compilation_timeout_check final : 
 5071 |       public exprtk::compilation_check 
 5072 |    { 
 5073 |       bool continue_compilation(compilation_context& context) 
 5074 |       override 
 5075 |       { 
 5076 |          // Determine if compilation should continue 
 5077 |          return ...; 
 5078 |       } 
 5079 |    }; 
 5080 |  
 5081 |  
 5082 | An  example checkpoint  use-case could  be that  we do  not want  the 
 5083 | compilation process to take longer than a maximum defined period,  eg: 
 5084 | five seconds. The associated compilation check implementation could be 
 5085 | as follows: 
 5086 |  
 5087 |    struct my_compilation_timeout_check final : 
 5088 |       public exprtk::compilation_check 
 5089 |    { 
 5090 |  
 5091 |       bool continue_compilation(compilation_context& context) 
 5092 |       override 
 5093 |       { 
 5094 |          static constexpr std::size_t max_iters_per_check = 1000; 
 5095 |  
 5096 |          if (++iterations_ >= max_iters_per_check) 
 5097 |          { 
 5098 |             if (std::chrono::steady_clock::now() >= timeout_tp_) 
 5099 |             { 
 5100 |                context.error_message = "Compilation has timed-out" 
 5101 |                return false; 
 5102 |             } 
 5103 |  
 5104 |             iterations_ = 0; 
 5105 |          } 
 5106 |  
 5107 |          return true; 
 5108 |       } 
 5109 |  
 5110 |       using time_point_t = std::chrono::time_point<std::chrono::steady_clock>; 
 5111 |  
 5112 |       void set_timeout_time(const time_point_t& timeout_tp) 
 5113 |       { 
 5114 |          timeout_tp_ = timeout_tp; 
 5115 |       } 
 5116 |  
 5117 |       std::size_t iterations_ = 0; 
 5118 |       time_point_t timeout_tp_; 
 5119 |    }; 
 5120 |  
 5121 |  
 5122 | Usage of the above defined compilation check will require  registering 
 5123 | the  check  with the  parser,  setting up  the  expiry time  and  then 
 5124 | proceeding  to  compile the  expression.  The following  is  a general 
 5125 | outline of what will be needed: 
 5126 |  
 5127 |    typedef exprtk::expression<T> expression_t; 
 5128 |    typedef exprtk::parser<T>     parser_t; 
 5129 |  
 5130 |    expression_t expression; 
 5131 |  
 5132 |    my_compilation_timeout_check compilation_timeout_check; 
 5133 |  
 5134 |    parser_t parser; 
 5135 |    parser. 
 5136 |       register_compilation_timeout_check(compilation_timeout_check); 
 5137 |  
 5138 |    const auto max_duration = std::chrono::seconds(5); 
 5139 |    const auto timeout_tp   = 
 5140 |       std::chrono::steady_clock::now() + max_duration; 
 5141 |  
 5142 |    compilation_timeout_check.set_timeout_time(timeout_tp); 
 5143 |  
 5144 |    if (!parser.compile(large_expression_string, expression)) 
 5145 |    { 
 5146 |       printf("Error: %s\t\n", parser.error().c_str()); 
 5147 |       return; 
 5148 |    } 
 5149 |  
 5150 |  
 5151 | (5) Assert statements 
 5152 | ExprTk supports the  use of assert  statements to verify  pre and post 
 5153 | conditions during the evaluation of expressions. The assert statements 
 5154 | are only active when a user defined assert handler is registered  with 
 5155 | the parser before expression compilation, otherwise they are  compiled 
 5156 | out,  this is  similar to  how asserts  are included/excluded  in C++ 
 5157 | coupled with  the definition  of NDEBUG.  The assert  syntax has three 
 5158 | variations as described below: 
 5159 |  
 5160 |    assert(x + y > i); 
 5161 |    assert(x + y > i, 'assert statement 1'); 
 5162 |    assert(x + y > i, 'assert statement 1', 'ASSERT01'); 
 5163 |  
 5164 |  
 5165 | The three assert statement input parameters are as follows: 
 5166 |  
 5167 |    1. assert condition (mandatory) 
 5168 |    2. assert message   (optional) 
 5169 |    3. assert id        (optional) 
 5170 |  
 5171 |  
 5172 | The  assert  condition  is essentially  a  boolean  statement that  is 
 5173 | expected to  be true  during evaluation.  The other  two parameters of 
 5174 | assert message and ID are  string values that are intended  to provide 
 5175 | feedback  to  the  handler  and  to  ensure the  uniqueness  of assert 
 5176 | statement respectively.  The three  parameters denoted  above and  the 
 5177 | offset of the  assert statement from  the beginning of  the expression 
 5178 | are  placed  inside  assert_context that  is provided  as part  of the 
 5179 | assert_check  handler.  A  user defined  assert_check  handler  can be 
 5180 | defined as follows: 
 5181 |  
 5182 |    struct my_assert_handler final : public exprtk::assert_check 
 5183 |    { 
 5184 |       void handle_assert(const assert_context& ctxt) override 
 5185 |       { 
 5186 |          printf("condition: [%s] \n", ctxt.condition.c_str()); 
 5187 |          printf("message:   [%s] \n", ctxt.message  .c_str()); 
 5188 |          printf("id:        [%s] \n", ctxt.id       .c_str()); 
 5189 |          printf("offset:    [%lu]\n", ctxt.offet            ); 
 5190 |          // throw std::runtime_error(.....); 
 5191 |       } 
 5192 |    }; 
 5193 |  
 5194 |  
 5195 | Once the  assert_check handler  has been  registered with  the parser, 
 5196 | expressions that  contain assert  statements will  have their  asserts 
 5197 | compiled in as part final evaluable expression instance: 
 5198 |  
 5199 |    typedef exprtk::symbol_table<T> symbol_table_t; 
 5200 |    typedef exprtk::expression<T>   expression_t; 
 5201 |    typedef exprtk::parser<T>       parser_t; 
 5202 |  
 5203 |    const std::string program = 
 5204 |       " var x := 4;                             " 
 5205 |       "                                         " 
 5206 |       " for (var i := 0; i < 10; i += 1)        " 
 5207 |       " {                                       " 
 5208 |       "    assert(i < x, 'assert statement 1'); " 
 5209 |       " }                                       " 
 5210 |  
 5211 |    my_assert_handler handler; 
 5212 |  
 5213 |    expression_t expression; 
 5214 |    parser_t parser; 
 5215 |  
 5216 |    parser.register_assert_check(handler); 
 5217 |    parser.compile(program, expression); 
 5218 |  
 5219 |  
 5220 | (6) Runtime Check Overheads 
 5221 | All of the above mentioned runtime checks will incur an execution time 
 5222 | overhead during the evaluation of expressions. This is an  unfortunate 
 5223 | but necessary  side-effect of  the process  when runtime  safety is of 
 5224 | concern. 
 5225 |  
 5226 | A recommendation to consider, that is not demonstrated above, is  that 
 5227 | in the check method of the  LRTC, one should not evaluate the  timeout 
 5228 | condition  on  every call  to  check (aka  on  every loop  iteration). 
 5229 | Instead a counter should be maintained  and incremented on each   call 
 5230 | and  when  the  counter  exceeds  some  predefined  amount  (eg: 10000 
 5231 | iterations),  then  the  timeout based  check  can  be preformed.  The 
 5232 | reasoning here  is that  incrementing an  integer should  be far  less 
 5233 | expensive than computing the current "now" time-point. 
 5234 |  
 5235 |  
 5236 | (7) Runtime Check Limitations 
 5237 | The available  RTC mechanisms  in ExprTk  are limited  to implementing 
 5238 | said checks only within ExprTk based syntax sections of an expression. 
 5239 | The  RTCs  will  not  be  active  within  user  defined  functions, or 
 5240 | composited functions  that have  been compiled  with parser  instances 
 5241 | that don't have the same set of RTC configurations enabled. 
 5242 |  
 5243 |  
 5244 | (8) Runtime Handlers 
 5245 |  
 5246 | When implementing stateful run-time check handlers one must be careful 
 5247 | to ensure the handler is setup correctly or reset between calls to the 
 5248 | expression::value or parser::compile methods. 
 5249 |  
 5250 | The following example  code utilises the  compilation timeout RTC  and 
 5251 | expression loop duration  RTC examples from  above to demonstrate  the 
 5252 | need  to  reset the  internal  state of  the  various handlers  before 
 5253 | compilation and valuation processes are invoked, as not doing so  will 
 5254 | affect the ability for  the next expression in  the list to either  be 
 5255 | correctly  compiled or  evaluated due  to the  potential of  erroneous 
 5256 | timeouts occurring. 
 5257 |  
 5258 |    typedef exprtk::expression<T> expression_t; 
 5259 |    typedef exprtk::parser<T>     parser_t; 
 5260 |  
 5261 |    my_compilation_timeout_check compilation_timeout_check; 
 5262 |  
 5263 |    my_loop_rtc loop_rtc; 
 5264 |    loop_rtc.loop_set = loop_runtime_check_t::e_all_loops; 
 5265 |    loop_rtc.max_loop_iterations = 100000; 
 5266 |  
 5267 |    parser_t parser; 
 5268 |    parser.register_loop_runtime_check(loop_rtc); 
 5269 |    parser. 
 5270 |       register_compilation_timeout_check(compilation_timeout_check); 
 5271 |  
 5272 |    const auto compile_timeout_tp = []() 
 5273 |    { 
 5274 |       const auto max_duration = std::chrono::seconds(5); 
 5275 |       return std::chrono::steady_clock::now() + max_duration; 
 5276 |    }; 
 5277 |  
 5278 |    const auto loop_timeout_tp = []() 
 5279 |    { 
 5280 |       const auto max_duration = std::chrono::seconds(10); 
 5281 |       return std::chrono::steady_clock::now() + max_duration; 
 5282 |    }; 
 5283 |  
 5284 |    const std::vector<std::string> expressions = 
 5285 |    { 
 5286 |       "x + y / 2", 
 5287 |       "sin(x) / cos(y) + 1", 
 5288 |       "clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)" 
 5289 |    }; 
 5290 |  
 5291 |    for (const auto& expr_str : expressions) 
 5292 |    { 
 5293 |       // Reset the timeout for the compilation RTC 
 5294 |       compilation_timeout_check 
 5295 |          .set_timeout_time(compile_timeout_tp()); 
 5296 |  
 5297 |       expression_t expression; 
 5298 |  
 5299 |       if (!parser.compile(large_expression_string, expression)) 
 5300 |       { 
 5301 |          printf("Error: %s\t\n", parser.error().c_str()); 
 5302 |          continue; 
 5303 |       } 
 5304 |  
 5305 |       try 
 5306 |       { 
 5307 |          // Reset the timeout for the loop duration RTC 
 5308 |          loop_rtc.set_timeout_time(loop_timeout_tp()); 
 5309 |  
 5310 |          expression.value(); 
 5311 |       } 
 5312 |       catch(std::runtime_error& exception) 
 5313 |       { 
 5314 |          printf("Exception: %s\n Expression: %s\n", 
 5315 |                 exception.what(), 
 5316 |                 expr_str.c_str()); 
 5317 |       } 
 5318 |    } 
 5319 |  
 5320 |  
 5321 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 5322 |  
 5323 | [SECTION 25 - BENCHMARKING] 
 5324 | As part of the ExprTk package there is an expression benchmark utility 
 5325 | named 'exprtk_benchmark'. The utility attempts to determine expression 
 5326 | evaluation  speed (or  rate of  evaluations -  evals  per  second), by 
 5327 | evaluating each expression numerous times and mutating the  underlying 
 5328 | variables  of  the  expression between  each  evaluation.  The utility 
 5329 | assumes any  valid ExprTk  expression (containing  conditionals, loops 
 5330 | etc), however  it will  only make  use of  a predefined  set of scalar 
 5331 | variables, namely: a, b, c, x, y, z and w. That being said expressions 
 5332 | themselves  can  contain any  number  of local  variables,  vectors or 
 5333 | strings. There are two modes of operation: 
 5334 |  
 5335 |    (1) Default 
 5336 |    (2) User Specified Expressions 
 5337 |  
 5338 |  
 5339 | (1) Default 
 5340 | The default mode is  enabled simply by executing  the exprtk_benchmark 
 5341 | binary with no command line parameters. In this mode a predefined  set 
 5342 | of expressions will be evaluated in three phases: 
 5343 |  
 5344 |    (a) ExprTk evaluation 
 5345 |    (b) Native evaluation 
 5346 |    (c) ExprTk parse 
 5347 |  
 5348 |  
 5349 | In the first two  phases (a and b)  a list of predefined  (hard-coded) 
 5350 | expressions  will  be  evaluated using  both  ExprTk  and native  mode 
 5351 | implementations.  This  is  done so  as  to  compare evaluation  times 
 5352 | between ExprTk and native implementations. The set of expressions used 
 5353 | are as follows: 
 5354 |  
 5355 |    (01) (y + x) 
 5356 |    (02) 2 * (y + x) 
 5357 |    (03) (2 * y + 2 * x) 
 5358 |    (04) ((1.23 * x^2) / y) - 123.123 
 5359 |    (05) (y + x / y) * (x - y / x) 
 5360 |    (06) x / ((x + y) + (x - y)) / y 
 5361 |    (07) 1 - ((x * y) + (y / x)) - 3 
 5362 |    (08) (5.5 + x) + (2 * x - 2 / 3 * y) * (x / 3 + y / 4) + (y + 7.7) 
 5363 |    (09) 1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^15 - 5.5x^23 + 6.6y^55 
 5364 |    (10) sin(2 * x) + cos(pi / y) 
 5365 |    (11) 1 - sin(2 * x) + cos(pi / y) 
 5366 |    (12) sqrt(111.111 - sin(2 * x) + cos(pi / y) / 333.333) 
 5367 |    (13) (x^2 / sin(2 * pi / y)) - x / 2 
 5368 |    (14) x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y 
 5369 |    (15) clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0) 
 5370 |    (16) max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11)) 
 5371 |    (17) if((y + (x * 2.2)) <= (x + y + 1.1), x - y, x*y) + 2 * pi / x 
 5372 |  
 5373 |  
 5374 | The  third  and  final  phase  (c),  is  used  to  determine   average 
 5375 | compilation rates  (compiles per  second) for  expressions of  varying 
 5376 | complexity. Each expression is compiled 100K times and the average for 
 5377 | each expression is output. 
 5378 |  
 5379 |  
 5380 | (2) User Specified Expressions 
 5381 | In this mode two parameters are passed to the utility via the  command 
 5382 | line: 
 5383 |  
 5384 |    (a) A name of a text file containing one expression per line 
 5385 |    (b) An integer representing the number of evaluations per expression 
 5386 |  
 5387 |  
 5388 | An  example execution  of the  benchmark utility  in this  mode is  as 
 5389 | follows: 
 5390 |  
 5391 |    ./exprtk_benchmark my_expressions.txt 1000000 
 5392 |  
 5393 |  
 5394 | The  above  invocation  will  load  the  expressions  from  the   file 
 5395 | 'my_expressions.txt' and will then proceed to evaluate each expression 
 5396 | one million  times, varying  the above  mentioned variables  (x, y,  z 
 5397 | etc.) between each evaluation, and at the end of each expression round 
 5398 | a print out of  running times, result of a single evaluation and total 
 5399 | sum of results is provided as demonstrated below: 
 5400 |  
 5401 |    Expression 1 of 7 4.770 ns 47700 ns  ( 9370368.0) '((((x+y)+z)))' 
 5402 |    Expression 2 of 7 4.750 ns 47500 ns  ( 1123455.9) '((((x+y)-z)))' 
 5403 |    Expression 3 of 7 4.766 ns 47659 ns  (21635410.7) '((((x+y)*z)))' 
 5404 |    Expression 4 of 7 5.662 ns 56619 ns  ( 1272454.9) '((((x+y)/z)))' 
 5405 |    Expression 5 of 7 4.950 ns 49500 ns  ( 4123455.9) '((((x-y)+z)))' 
 5406 |    Expression 6 of 7 7.581 ns 75810 ns  (-4123455.9) '((((x-y)-z)))' 
 5407 |    Expression 7 of 7 4.801 ns 48010 ns  (       0.0) '((((x-y)*z)))' 
 5408 |  
 5409 |  
 5410 | The benchmark utility can be very useful when investigating evaluation 
 5411 | efficiency  issues with  ExprTk or  simply during  the prototyping  of 
 5412 | expressions. As an example, lets take the following expression: 
 5413 |  
 5414 |    1 / sqrt(2x) * e^(3y) 
 5415 |  
 5416 |  
 5417 | Lets say we would like to determine which sub-part  of the  expression 
 5418 | takes the  most time  to evaluate  and perhaps  attempt to  rework the 
 5419 | expression based on the results. In order to do this we will create  a 
 5420 | text file  called 'test.txt'  and then  proceed to  make some educated 
 5421 | guesses  about  how  to  break   the  expression  up  into  its   more 
 5422 | 'interesting' sub-parts which we will  then add as one expression  per 
 5423 | line to the file. An example breakdown may be as follows: 
 5424 |  
 5425 |    1 / sqrt(2x) * e^(3y) 
 5426 |    1 / sqrt(2x) 
 5427 |    e^(3y) 
 5428 |  
 5429 |  
 5430 | The  benchmark with  the given  file, where  each expression  will be 
 5431 | evaluated 100K times can be executed as follows: 
 5432 |  
 5433 |    ./exprtk_benchmark test.txt 100000 
 5434 |    Expr 1 of 3 90.340 ns 9034000 ns (296417859.3) '1/sqrt(2x)*e^(3y)' 
 5435 |    Expr 2 of 3 11.100 ns 1109999 ns (    44267.3) '1/sqrt(2x)' 
 5436 |    Expr 3 of 3 77.830 ns 7783000 ns (615985286.6) 'e^(3y)' 
 5437 |    [*] Number Of Evals:         300000 
 5438 |    [*] Total Time:              0.018sec 
 5439 |    [*] Total Single Eval Time:  0.000ms 
 5440 |  
 5441 |  
 5442 | From the results above we conclude that the third expression  (e^(3y)) 
 5443 | consumes the largest amount of time. The variable 'e', as used in both 
 5444 | the  benchmark  and  in the  expression,  is  an approximation  of the 
 5445 | transcendental mathematical constant e (2.71828182845904...) hence the 
 5446 | sub-expression  should perhaps be  modified  to use the generally more 
 5447 | efficient built-in 'exp' function. 
 5448 |  
 5449 |    ./exprtk_benchmark test.txt 1000000 
 5450 |    Expr 1 of 5 86.563 ns 8656300ns (296417859.6) '1/sqrt(2x)*e^(3y)' 
 5451 |    Expr 2 of 5 40.506 ns 4050600ns (296417859.6) '1/sqrt(2x)*exp(3y)' 
 5452 |    Expr 3 of 5 14.248 ns 1424799ns (    44267.2) '1/sqrt(2x)' 
 5453 |    Expr 4 of 5 88.840 ns 8884000ns (615985286.9) 'e^(3y)' 
 5454 |    Expr 5 of 5 29.267 ns 2926699ns (615985286.9) 'exp(3y)' 
 5455 |    [*] Number Of Evals:        5000000 
 5456 |    [*] Total Time:             0.260sec 
 5457 |    [*] Total Single Eval Time: 0.000ms 
 5458 |  
 5459 |  
 5460 | The above output demonstrates the  results from  making the previously 
 5461 | mentioned modification to the expression. As can be seen the new  form 
 5462 | of the expression using the 'exp' function reduces the evaluation time 
 5463 | by over 50%, in other words increases the evaluation rate by two fold. 
 5464 |  
 5465 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 5466 |  
 5467 | [SECTION 26 - EXPRTK NOTES] 
 5468 | The following is a list of facts and suggestions one may want to take 
 5469 | into account when using ExprTk: 
 5470 |  
 5471 |  (00) Precision  and performance  of expression  evaluations are  the 
 5472 |       dominant principles of the ExprTk library. 
 5473 |  
 5474 |  (01) ExprTk  uses a  rudimentary imperative  programming model  with 
 5475 |       syntax based  on languages  such as  Pascal and  C. Furthermore 
 5476 |       ExprTk  is  an LL(2)  type  grammar and  is  processed using  a 
 5477 |       recursive descent parsing algorithm. 
 5478 |  
 5479 |  (02) Supported types  are float,  double, long  double and MPFR/GMP. 
 5480 |       Generally any user defined numerical type that supports all the 
 5481 |       basic floating  point arithmetic  operations: -,+,*,/,^,%  etc; 
 5482 |       unary and binary operations: sin,cos,min,max,equal etc and  any 
 5483 |       other ExprTk dependent operations can be used to specialise the 
 5484 |       various components: expression, parser and symbol_table. 
 5485 |  
 5486 |  (03) Standard arithmetic operator precedence is applied (BEDMAS). In 
 5487 |       general C, Pascal or Rust equivalent unary, binary, logical and 
 5488 |       equality/inequality operator precedence rules apply. 
 5489 |       eg: a == b and c > d + 1  --->  (a == b) and (c > (d + 1)) 
 5490 |           x - y <= z / 2        --->  (x - y) <= (z / 2) 
 5491 |           a - b / c * d^2^3     --->  a - ((b / c) * d^(2^3)) 
 5492 |  
 5493 |  (04) Results of expressions that are deemed as being 'valid' are  to 
 5494 |       exist within the set of Real numbers. All other results will be 
 5495 |       of  the  value:  Not-A-Number  (NaN).  However  this  may   not 
 5496 |       necessarily be a requirement for user defined numerical  types, 
 5497 |       eg: complex number type. 
 5498 |  
 5499 |  (05) Supported   user  defined   types   are   numeric  and   string 
 5500 |       variables, numeric vectors and functions. 
 5501 |  
 5502 |  (06) All  reserved words,  keywords, variable,  vector, string   and 
 5503 |       function names are case-insensitive. 
 5504 |  
 5505 |  (07) Variable, vector, string variable and function names must begin 
 5506 |       with  a letter  (A-Z or  a-z), then  can  be  comprised of  any 
 5507 |       combination of letters, digits, underscores and dots, ending in 
 5508 |       either a letter (A-Z or a-z), digit or underscore. (eg: x,  y2, 
 5509 |       var1,  power_func99,  person.age,  item.size.0). The associated 
 5510 |       regex pattern is: [a-zA-Z][a-zA-Z0-9_.]*[a-zA-Z0-9_]+ 
 5511 |  
 5512 |  (08) Expression lengths and sub-expression lists are limited only by 
 5513 |       storage capacity. 
 5514 |  
 5515 |  (09) The  life-time of  objects registered  with or  created from  a 
 5516 |       specific symbol-table must  span at least  the lifetime of  the 
 5517 |       symbol  table  instance  and  all  compiled  expressions  which 
 5518 |       utilise objects, such as variables, strings, vectors,  function 
 5519 |       compositor  functions  and  functions  of  that   symbol-table, 
 5520 |       otherwise the result will be undefined behaviour. 
 5521 |  
 5522 |  (10) Equal and not_equal  are  normalised-epsilon equality routines, 
 5523 |       which use epsilons of 0.0000000001 and 0.000001 for double  and 
 5524 |       float types respectively. 
 5525 |  
 5526 |  (11) All trigonometric functions  assume radian input  unless stated 
 5527 |       otherwise. 
 5528 |  
 5529 |  (12) Expressions may contain  white-space characters such  as space, 
 5530 |       tabs, new-lines, control-feed et al. 
 5531 |       ('\n', '\r', '\t', '\b', '\v', '\f') 
 5532 |  
 5533 |  (13) Strings may be comprised of any  combination of letters, digits 
 5534 |       special characters including (~!@#$%^&*()[]|=+ ,./?<>;:"`~_) or 
 5535 |       hexadecimal escaped sequences (eg: \0x30) and must be enclosed 
 5536 |       with single-quotes. 
 5537 |       eg: 'Frankly my dear, \0x49 do n0t give a damn!' 
 5538 |  
 5539 |  (14) User defined  normal functions  can have  up to  20 parameters, 
 5540 |       where as  user defined  generic-functions and  vararg-functions 
 5541 |       can have an unlimited number of parameters. 
 5542 |  
 5543 |  (15) The inbuilt polynomial functions can be at most of degree 12. 
 5544 |  
 5545 |  (16) Where appropriate constant folding optimisations may be applied. 
 5546 |       (eg: The expression '2 + (3 - (x / y))' becomes '5 - (x / y)') 
 5547 |  
 5548 |  (17) If the strength  reduction compilation option has  been enabled, 
 5549 |       then where applicable  strength reduction  optimisations  may be 
 5550 |       applied. 
 5551 |  
 5552 |  (18) String  processing capabilities  are available  by default.  To 
 5553 |       turn them  off, the  following needs  to be  defined at compile 
 5554 |       time: exprtk_disable_string_capabilities 
 5555 |  
 5556 |  (19) Composited functions can call themselves or any other functions 
 5557 |       that have been defined prior to their own definition. 
 5558 |  
 5559 |  (20) Recursive calls made from within composited functions will have 
 5560 |       a stack size bound by the stack of the executing architecture. 
 5561 |  
 5562 |  (21) User  defined functions  by default  are assumed  to have  side 
 5563 |       effects. As such an "all constant parameter" invocation of such 
 5564 |       functions wont result in constant folding. If the function  has 
 5565 |       no side-effects then that  can be noted during the  constructor 
 5566 |       of  the  ifunction  allowing it  to  be  constant folded  where 
 5567 |       appropriate. 
 5568 |  
 5569 |  (22) The entity relationship between symbol_table and an  expression 
 5570 |       is many-to-many. However the intended 'typical' use-case  where 
 5571 |       possible, is to have a single symbol table manage the  variable 
 5572 |       and function requirements of multiple expressions. 
 5573 |  
 5574 |  (23) The common use-case  for an expression  is to have  it compiled 
 5575 |       only  ONCE  and  then subsequently  have it  evaluated multiple 
 5576 |       times. An extremely  inefficient and suboptimal  approach would 
 5577 |       be to recompile an expression  from its string form every  time 
 5578 |       it requires evaluating. 
 5579 |  
 5580 |  (24) It is  strongly recommended  that  the  return value  of method 
 5581 |       invocations from  the parser  and symbol_table  types be  taken 
 5582 |       into account. Specifically the  'compile' method of the  parser 
 5583 |       and the 'add_xxx'  set of methods  of the symbol_table  as they 
 5584 |       denote either the success or failure state of the invoked call. 
 5585 |       Continued processing from  a failed  state without having first 
 5586 |       rectified the underlying issue  will in turn result  in further 
 5587 |       failures and undefined behaviours. 
 5588 |  
 5589 |  (25) The following are examples of compliant floating point value 
 5590 |       representations: 
 5591 |  
 5592 |       (01) 12345         (06) -123.456 
 5593 |       (02) +123.456e+12  (07) 123.456E-12 
 5594 |       (03) +012.045e+07  (08) .1234 
 5595 |       (04) 1234.         (09) -56789. 
 5596 |       (05) 123.456f      (10) -321.654E+3L 
 5597 |  
 5598 |  (26) Expressions may contain any of the following comment styles: 
 5599 |  
 5600 |       (1) // .... \n 
 5601 |       (2) #  .... \n 
 5602 |       (3) /* .... */ 
 5603 |  
 5604 |  (27) The  'null'  value  type  is  a  special  non-zero  type   that 
 5605 |       incorporates specific semantics when undergoing operations with 
 5606 |       the standard numeric type. The following is a list of type  and 
 5607 |       boolean results associated with the use of 'null': 
 5608 |  
 5609 |       (1) null  +,-,*,/,%  x    --> x 
 5610 |       (2) x     +,-,*,/,%  null --> x 
 5611 |       (3) null  +,-,*,/,%  null --> null 
 5612 |       (4) null     ==      null --> true 
 5613 |       (5) null     ==      x    --> true 
 5614 |       (6) x        ==      null --> true 
 5615 |       (7) x        !=      null --> false 
 5616 |       (8) null     !=      null --> false 
 5617 |       (9) null     !=      x    --> false 
 5618 |  
 5619 |  (28) The following is a list  of reserved words and symbols  used by 
 5620 |       ExprTk. Attempting to  add a variable  or custom function  to a 
 5621 |       symbol table using any of  the reserved words will result  in a 
 5622 |       failure. 
 5623 |  
 5624 |       abs, acos,  acosh, and, asin,  asinh,  assert, atan,  atan2, 
 5625 |       atanh, avg, break, case,  ceil, clamp, continue, cosh,  cos, 
 5626 |       cot,  csc, default,  deg2grad, deg2rad,  else, equal,  erfc, 
 5627 |       erf, exp, expm1, false,  floor, for, frac, grad2deg,  hypot, 
 5628 |       iclamp, if, ilike, in, inrange, in, like, log, log10, log1p, 
 5629 |       log2, logn, mand, max, min, mod, mor, mul, nand, ncdf,  nor, 
 5630 |       not, not_equal, not, null, or, pow, rad2deg, repeat, return, 
 5631 |       root, roundn, round,  sec, sgn, shl,  shr, sinc, sinh,  sin, 
 5632 |       sqrt, sum, swap, switch, tanh, tan, true, trunc, until, var, 
 5633 |       while, xnor, xor 
 5634 |  
 5635 |  (29) Every valid ExprTk statement is a "value returning" expression. 
 5636 |       Unlike some languages that limit the types of expressions  that 
 5637 |       can be  performed in  certain situations,  in ExprTk  any valid 
 5638 |       expression can be used in any "value consuming" context. eg: 
 5639 |  
 5640 |       var y := 3; 
 5641 |       for (var x := switch 
 5642 |                     { 
 5643 |                       case 1  :  7; 
 5644 |                       case 2  : -1 + ~{var x{};}; 
 5645 |                       default :  y > 2 ? 3 : 4; 
 5646 |                     }; 
 5647 |            x != while (y > 0) { y -= 1; }; 
 5648 |            x -= { 
 5649 |                   if (min(x,y) < 2 * max(x,y)) 
 5650 |                     x + 2; 
 5651 |                   else 
 5652 |                     x + y - 3; 
 5653 |                 } 
 5654 |           ) 
 5655 |       { 
 5656 |         (x + y) / (x - y); 
 5657 |       }; 
 5658 |  
 5659 |  (30) It is recommended when prototyping expressions that the  ExprTk 
 5660 |       REPL be utilised, as it supports all the features available  in 
 5661 |       the library,  including complete  error analysis,  benchmarking 
 5662 |       and   dependency   dumps    etc   which   allows    for   rapid 
 5663 |       coding/prototyping  and  debug  cycles  without  the  hassle of 
 5664 |       having to  recompile test  programs with  expressions that have 
 5665 |       been hard-coded. It is also a  good source of truth for how the 
 5666 |       library's various features can be applied. 
 5667 |  
 5668 |  (31) For performance considerations,  one should assume  the actions 
 5669 |       of expression, symbol  table and parser  instance instantiation 
 5670 |       and destruction, and the expression compilation process  itself 
 5671 |       to be of high latency. Hence none of them should be part of any 
 5672 |       performance  critical  code  paths, and  should  instead  occur 
 5673 |       entirely either before or after such code paths. 
 5674 |  
 5675 |  (32) Deep  copying  an  expression  instance  for  the  purposes  of 
 5676 |       persisting to disk or otherwise transmitting elsewhere with the 
 5677 |       intent to 'resurrect' the  expression instance later on  is not 
 5678 |       possible due  to the  reasons described  in the  final note  of 
 5679 |       Section 10. The recommendation is to instead simply persist the 
 5680 |       string form  of the  expression and  compile the  expression at 
 5681 |       run-time on the target. 
 5682 |  
 5683 |  (33) The  correctness  and  robustness  of  the  ExprTk  library  is 
 5684 |       maintained by having  a comprehensive suite  of unit tests  and 
 5685 |       functional tests all of  which are run using  sanitizers (ASAN, 
 5686 |       UBSAN, LSAN, MSAN, TSAN). Additionally, continuous fuzz-testing 
 5687 |       provided by Google  OSS Fuzz, and static analysis via  Synopsis 
 5688 |       Coverity. 
 5689 |  
 5690 |  (34) The library  name ExprTk  is pronounced  "Ex-Pee-Ar-Tee-Kay" or 
 5691 |       simply "Mathematical Expression Toolkit" 
 5692 |  
 5693 |  
 5694 |  (35) For general support, inquires or bug/issue reporting: 
 5695 |       https://www.partow.net/programming/exprtk/index.html#support 
 5696 |  
 5697 |  (36) Before jumping in and using ExprTk, do take the time to  peruse 
 5698 |       the documentation and all of the examples, both in the main and 
 5699 |       the extras  distributions. Having  an informed  general view of 
 5700 |       what can and  can't be done,  and how something  should be done 
 5701 |       with ExprTk, will  likely result in  a far more  productive and 
 5702 |       enjoyable programming experience. 
 5703 |  
 5704 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 5705 |  
 5706 | [SECTION 27 - SIMPLE EXPRTK EXAMPLE] 
 5707 | The following is a  simple yet complete example  demonstrating typical 
 5708 | usage of the ExprTk Library.  The example instantiates a symbol  table 
 5709 | object, adding to it  three variables named x,  y and z, and  a custom 
 5710 | user defined function, that accepts only two parameters, named myfunc. 
 5711 | The  example then  proceeds to  instantiate an  expression object  and 
 5712 | register to it the symbol table instance. 
 5713 |  
 5714 | A parser is  then instantiated, and  the string representation  of the 
 5715 | expression  and  the  expression object  are  passed  to the  parser's 
 5716 | compile  method   for  compilation.   If  an   error  occurred  during 
 5717 | compilation, the compile method will return false, leading to a series 
 5718 | of  error diagnostics  being printed  to stdout.  Otherwise the  newly 
 5719 | compiled expression is evaluated  by invoking  the expression object's 
 5720 | value method, and subsequently printing the result  of the computation 
 5721 | to stdout. 
 5722 |  
 5723 |  
 5724 | --- snip --- 
 5725 | #include  
 5726 | #include  
 5727 |  
 5728 | #include "exprtk.hpp" 
 5729 |  
 5730 | template  
 5731 | struct myfunc final : public exprtk::ifunction<T> 
 5732 | { 
 5733 |    myfunc() : exprtk::ifunction<T>(2) {} 
 5734 |  
 5735 |    T operator()(const T& v1, const T& v2) override 
 5736 |    { 
 5737 |       return T(1) + (v1 * v2) / T(3); 
 5738 |    } 
 5739 | }; 
 5740 |  
 5741 | int main() 
 5742 | { 
 5743 |    typedef exprtk::symbol_table<double> symbol_table_t; 
 5744 |    typedef exprtk::expression<double>   expression_t; 
 5745 |    typedef exprtk::parser<double>       parser_t; 
 5746 |    typedef exprtk::parser_error::type   error_t; 
 5747 |  
 5748 |    const std::string expression_string = 
 5749 |       "z := 2 myfunc([4 + sin(x / pi)^3],y ^ 2)" 
 5750 |  
 5751 |    double x = 1.1; 
 5752 |    double y = 2.2; 
 5753 |    double z = 3.3; 
 5754 |  
 5755 |    myfunc<double> mf; 
 5756 |  
 5757 |    symbol_table_t symbol_table; 
 5758 |    symbol_table.add_constants(); 
 5759 |    symbol_table.add_variable("x",x); 
 5760 |    symbol_table.add_variable("y",y); 
 5761 |    symbol_table.add_variable("z",z); 
 5762 |    symbol_table.add_function("myfunc",mf); 
 5763 |  
 5764 |    expression_t expression; 
 5765 |    expression.register_symbol_table(symbol_table); 
 5766 |  
 5767 |    parser_t parser; 
 5768 |  
 5769 |    if (!parser.compile(expression_string,expression)) 
 5770 |    { 
 5771 |       // A compilation error has occurred. Attempt to 
 5772 |       // print all errors to stdout. 
 5773 |  
 5774 |       printf("Error: %s\tExpression: %s\n", 
 5775 |              parser.error().c_str(), 
 5776 |              expression_string.c_str()); 
 5777 |  
 5778 |       for (std::size_t i = 0; i < parser.error_count(); ++i) 
 5779 |       { 
 5780 |          // Include the specific nature of each error 
 5781 |          // and its position in the expression string. 
 5782 |  
 5783 |          error_t error = parser.get_error(i); 
 5784 |  
 5785 |          printf("Error: %02d Position: %02d " 
 5786 |                 "Type: [%s] " 
 5787 |                 "Message: %s " 
 5788 |                 "Expression: %s\n", 
 5789 |                 static_cast<int>(i), 
 5790 |                 static_cast<int>(error.token.position), 
 5791 |                 exprtk::parser_error::to_str(error.mode).c_str(), 
 5792 |                 error.diagnostic.c_str(), 
 5793 |                 expression_string.c_str()); 
 5794 |       } 
 5795 |  
 5796 |       return 1; 
 5797 |    } 
 5798 |  
 5799 |    // Evaluate the expression and obtain its result. 
 5800 |  
 5801 |    double result = expression.value(); 
 5802 |  
 5803 |    printf("Result: %10.5f\n",result); 
 5804 |  
 5805 |    return 0; 
 5806 | } 
 5807 | --- snip --- 
 5808 |  
 5809 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 5810 |  
 5811 | [SECTION 28 - BUILD OPTIONS] 
 5812 | When building ExprTk there are a number of defines that will enable or 
 5813 | disable certain features and  capabilities. The defines can  either be 
 5814 | part of a compiler command line switch or scoped around the include to 
 5815 | the ExprTk header. The defines are as follows: 
 5816 |  
 5817 |    (01) exprtk_enable_debugging 
 5818 |    (02) exprtk_disable_cardinal_pow_optimisation 
 5819 |    (03) exprtk_disable_comments 
 5820 |    (04) exprtk_disable_break_continue 
 5821 |    (05) exprtk_disable_sc_andor 
 5822 |    (06) exprtk_disable_return_statement 
 5823 |    (07) exprtk_disable_enhanced_features 
 5824 |    (08) exprtk_disable_string_capabilities 
 5825 |    (09) exprtk_disable_superscalar_unroll 
 5826 |    (10) exprtk_disable_rtl_io 
 5827 |    (11) exprtk_disable_rtl_io_file 
 5828 |    (12) exprtk_disable_rtl_vecops 
 5829 |    (13) exprtk_disable_caseinsensitivity 
 5830 |    (14) exprtk_enable_range_runtime_checks 
 5831 |  
 5832 | (01) exprtk_enable_debugging 
 5833 | This define will enable printing of debug information to stdout during 
 5834 | the compilation process. 
 5835 |  
 5836 | (02) exprtk_disable_cardinal_pow_optimisation 
 5837 | This  define   will  disable  the optimisation  invoked when  constant 
 5838 | integers are used as powers in exponentiation expressions (eg: x^7). 
 5839 |  
 5840 | (03) exprtk_disable_comments 
 5841 | This define will disable the ability for expressions to have comments. 
 5842 | Expressions that have comments when parsed with a build that has  this 
 5843 | option, will result in a compilation failure. 
 5844 |  
 5845 | (04) exprtk_disable_break_continue 
 5846 | This  define  will  disable  the  loop-wise  'break'  and   'continue' 
 5847 | capabilities. Any expression that contains those keywords will  result 
 5848 | in a compilation failure. 
 5849 |  
 5850 | (05) exprtk_disable_sc_andor 
 5851 | This define  will disable  the short-circuit  '&' (and)  and '|'  (or) 
 5852 | operators 
 5853 |  
 5854 | (06) exprtk_disable_return_statement 
 5855 | This define will disable use of return statements within expressions. 
 5856 |  
 5857 | (07) exprtk_disable_enhanced_features 
 5858 | This  define  will  disable all  enhanced  features  such as  strength 
 5859 | reduction and special  function optimisations and  expression specific 
 5860 | type instantiations.  This feature  will reduce  compilation times and 
 5861 | binary sizes but will  also result in massive  performance degradation 
 5862 | of expression evaluations. 
 5863 |  
 5864 | (08) exprtk_disable_string_capabilities 
 5865 | This  define  will  disable all  string  processing  capabilities. Any 
 5866 | expression that contains a string or string related syntax will result 
 5867 | in a compilation failure. 
 5868 |  
 5869 | (09) exprtk_disable_superscalar_unroll 
 5870 | This define will set  the loop unroll batch  size to 4 operations  per 
 5871 | loop  instead of  the default  8 operations.  This define  is used  in 
 5872 | operations that  involve vectors  and aggregations  over vectors. When 
 5873 | targeting  non-superscalar  architectures, it  may  be recommended  to 
 5874 | build using this particular option if efficiency of evaluations is  of 
 5875 | concern. 
 5876 |  
 5877 | (10) exprtk_disable_rtl_io 
 5878 | This define will  disable all of  basic IO RTL  package features. When 
 5879 | present, any attempt to register the basic IO RTL package with a given 
 5880 | symbol table will fail causing a compilation error. 
 5881 |  
 5882 | (11) exprtk_disable_rtl_io_file 
 5883 | This  define will  disable  the  file I/O  RTL package  features. When 
 5884 | present, any  attempts to register  the file I/O package with  a given 
 5885 | symbol table will fail causing a compilation error. 
 5886 |  
 5887 | (12) exprtk_disable_rtl_vecops 
 5888 | This define will  disable the extended  vector operations RTL  package 
 5889 | features. When present, any attempts to register the vector operations 
 5890 | package with  a given  symbol table  will fail  causing a  compilation 
 5891 | error. 
 5892 |  
 5893 | (13) exprtk_disable_caseinsensitivity 
 5894 | This define  will disable  case-insensitivity when  matching variables 
 5895 | and  functions. Furthermore  all reserved  and keywords  will only  be 
 5896 | acknowledged when in all lower-case. 
 5897 |  
 5898 | (14) exprtk_enable_range_runtime_checks 
 5899 | This define will enable run-time checks pertaining to vector  indexing 
 5900 | operations used  in any  of the  vector-to-vector and vector-to-scalar 
 5901 | operations. 
 5902 |  
 5903 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 5904 |  
 5905 | [SECTION 29 - FILES] 
 5906 | The source distribution of ExprTk is comprised of the following set of 
 5907 | files: 
 5908 |  
 5909 |    (00) Makefile 
 5910 |    (01) readme.txt 
 5911 |    (02) exprtk.hpp 
 5912 |    (03) exprtk_test.cpp 
 5913 |    (04) exprtk_benchmark.cpp 
 5914 |    (05) exprtk_simple_example_01.cpp 
 5915 |    (06) exprtk_simple_example_02.cpp 
 5916 |    (07) exprtk_simple_example_03.cpp 
 5917 |    (08) exprtk_simple_example_04.cpp 
 5918 |    (09) exprtk_simple_example_05.cpp 
 5919 |    (10) exprtk_simple_example_06.cpp 
 5920 |    (11) exprtk_simple_example_07.cpp 
 5921 |    (12) exprtk_simple_example_08.cpp 
 5922 |    (13) exprtk_simple_example_09.cpp 
 5923 |    (14) exprtk_simple_example_10.cpp 
 5924 |    (15) exprtk_simple_example_11.cpp 
 5925 |    (16) exprtk_simple_example_12.cpp 
 5926 |    (17) exprtk_simple_example_13.cpp 
 5927 |    (18) exprtk_simple_example_14.cpp 
 5928 |    (19) exprtk_simple_example_15.cpp 
 5929 |    (20) exprtk_simple_example_16.cpp 
 5930 |    (21) exprtk_simple_example_17.cpp 
 5931 |    (22) exprtk_simple_example_18.cpp 
 5932 |    (23) exprtk_simple_example_19.cpp 
 5933 |    (24) exprtk_simple_example_20.cpp 
 5934 |    (25) exprtk_simple_example_21.cpp 
 5935 |    (26) exprtk_simple_example_22.cpp 
 5936 |    (27) exprtk_simple_example_23.cpp 
 5937 |    (28) exprtk_simple_example_24.cpp 
 5938 |  
 5939 |  
 5940 | Details for each of the above examples can be found here: 
 5941 |  
 5942 |   https://www.partow.net/programming/exprtk/index.html#examples 
 5943 |  
 5944 |  
 5945 | Various extended and advanced examples using ExprTk are available 
 5946 | via the following: 
 5947 |  
 5948 |    (00) exprtk_american_option_binomial_model.cpp 
 5949 |    (01) exprtk_binomial_coefficient.cpp 
 5950 |    (02) exprtk_bsm_benchmark.cpp 
 5951 |    (03) exprtk_calc.cpp 
 5952 |    (04) exprtk_collatz.cpp 
 5953 |    (05) exprtk_compilation_timeout.cpp 
 5954 |    (06) exprtk_degree_trigonometry_example.cpp 
 5955 |    (07) exprtk_exprgen.cpp 
 5956 |    (08) exprtk_extract_dependents.cpp 
 5957 |    (09) exprtk_e_10kdigits.cpp 
 5958 |    (10) exprtk_factorize_fermat.cpp 
 5959 |    (11) exprtk_factorize_pollard.cpp 
 5960 |    (12) exprtk_fizzbuzz.cpp 
 5961 |    (13) exprtk_funcall_benchmark.cpp 
 5962 |    (14) exprtk_game_of_life.cpp 
 5963 |    (15) exprtk_gcd.cpp 
 5964 |    (16) exprtk_gnuplot.cpp 
 5965 |    (17) exprtk_gnuplot_multi.cpp 
 5966 |    (18) exprtk_groups_examples.cpp 
 5967 |    (19) exprtk_immutable_symbol_table_example.cpp 
 5968 |    (20) exprtk_import_packages.cpp 
 5969 |    (21) exprtk_instruction_primer.cpp 
 5970 |    (22) exprtk_jump_diffusion_process.cpp 
 5971 |    (23) exprtk_loop_timeout_rtc.cpp 
 5972 |    (24) exprtk_magic_square.cpp 
 5973 |    (25) exprtk_mandelbrot.cpp 
 5974 |    (26) exprtk_max_subarray_sum.cpp 
 5975 |    (27) exprtk_maze_generator.cpp 
 5976 |    (28) exprtk_miller_rabin_primality_test.cpp 
 5977 |    (29) exprtk_montecarlo_e.cpp 
 5978 |    (30) exprtk_montecarlo_option_pricing_model.cpp 
 5979 |    (31) exprtk_montecarlo_pi.cpp 
 5980 |    (32) exprtk_naive_primes.cpp 
 5981 |    (33) exprtk_normal_random_marsaglia_method.cpp 
 5982 |    (34) exprtk_nqueens_problem.cpp 
 5983 |    (35) exprtk_nthroot_bisection.cpp 
 5984 |    (36) exprtk_ornstein_uhlenbeck_process.cpp 
 5985 |    (37) exprtk_pascals_triangle.cpp 
 5986 |    (38) exprtk_pi_10kdigits.cpp 
 5987 |    (39) exprtk_prime_sieve.cpp 
 5988 |    (40) exprtk_prime_sieve_vectorized.cpp 
 5989 |    (41) exprtk_pythagorean_triples.cpp 
 5990 |    (42) exprtk_recursive_fibonacci.cpp 
 5991 |    (43) exprtk_repl.cpp 
 5992 |    (44) exprtk_riddle.cpp 
 5993 |    (45) exprtk_rtc_overhead.cpp 
 5994 |    (46) exprtk_sudoku_solver.cpp 
 5995 |    (47) exprtk_sumofprimes.cpp 
 5996 |    (48) exprtk_symtab_functions.cpp 
 5997 |    (49) exprtk_testgen.cpp 
 5998 |    (50) exprtk_tower_of_hanoi.cpp 
 5999 |    (51) exprtk_truthtable_gen.cpp 
 6000 |    (52) exprtk_vectorized_binomial_model.cpp 
 6001 |    (53) exprtk_vectornorm.cpp 
 6002 |    (54) exprtk_vector_benchmark.cpp 
 6003 |    (55) exprtk_vector_benchmark_multithreaded.cpp 
 6004 |    (56) exprtk_vector_resize_example.cpp 
 6005 |    (57) exprtk_vector_resize_inline_example.cpp 
 6006 |    (58) exprtk_wiener_process_pi.cpp 
 6007 |  
 6008 |  
 6009 | Details for each of the above examples can be found here: 
 6010 |  
 6011 |    https://partow.net/programming/exprtk/index.html#variousexamples 
 6012 |  
 6013 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 6014 |  
 6015 | [SECTION 30 - LANGUAGE STRUCTURE] 
 6016 | The following  are the  various language  structures available  within 
 6017 | ExprTk and their structural representations. 
 6018 |  
 6019 |    (00) If Statement 
 6020 |    (01) Else Statement 
 6021 |    (02) Ternary Statement 
 6022 |    (03) While Loop 
 6023 |    (04) Repeat Until Loop 
 6024 |    (05) For Loop 
 6025 |    (06) Switch Statement 
 6026 |    (07) Multi Subexpression Statement 
 6027 |    (08) Multi Case-Consequent Statement 
 6028 |    (09) Variable Definition Statement 
 6029 |    (10) Vector Definition Statement 
 6030 |    (11) String Definition Statement 
 6031 |    (12) Range Statement 
 6032 |    (13) Return Statement 
 6033 |  
 6034 |  
 6035 | (00) - If Statement 
 6036 | +-------------------------------------------------------------+ 
 6037 | |                                                             | 
 6038 | |   [if] ---> [(] ---> [condition] -+-> [,] -+                | 
 6039 | |                                   |        |                | 
 6040 | |   +---------------<---------------+        |                | 
 6041 | |   |                                        |                | 
 6042 | |   |  +------------------<------------------+                | 
 6043 | |   |  |                                                      | 
 6044 | |   |  +--> [consequent] ---> [,] ---> [alternative] ---> [)] | 
 6045 | |   |                                                         | 
 6046 | |   +--> [)] --+-> [{] ---> [expression*] ---> [}] --+        | 
 6047 | |              |                                     |        | 
 6048 | |              |                +---------<----------+        | 
 6049 | |   +----<-----+                |                             | 
 6050 | |   |                           v                             | 
 6051 | |   +--> [consequent] --> [;] -{*}-> [else-statement]         | 
 6052 | |                                                             | 
 6053 | +-------------------------------------------------------------+ 
 6054 |  
 6055 |  
 6056 | (01) - Else Statement 
 6057 | +-------------------------------------------------------------+ 
 6058 | |                                                             | 
 6059 | |   [else] -+-> [alternative] ---> [;]                        | 
 6060 | |           |                                                 | 
 6061 | |           +--> [{] ---> [expression*] ---> [}]              | 
 6062 | |           |                                                 | 
 6063 | |           +--> [if-statement]                               | 
 6064 | |                                                             | 
 6065 | +-------------------------------------------------------------+ 
 6066 |  
 6067 |  
 6068 | (02) - Ternary Statement 
 6069 | +-------------------------------------------------------------+ 
 6070 | |                                                             | 
 6071 | |   [condition] ---> [?] ---> [consequent] ---> [:] --+       | 
 6072 | |                                                     |       | 
 6073 | |   +------------------------<------------------------+       | 
 6074 | |   |                                                         | 
 6075 | |   +--> [alternative] --> [;]                                | 
 6076 | |                                                             | 
 6077 | +-------------------------------------------------------------+ 
 6078 |  
 6079 |  
 6080 | (03) - While Loop 
 6081 | +-------------------------------------------------------------+ 
 6082 | |                                                             | 
 6083 | |   [while] ---> [(] ---> [condition] ---> [)] ---+           | 
 6084 | |                                                 |           | 
 6085 | |   +----------------------<----------------------+           | 
 6086 | |   |                                                         | 
 6087 | |   +--> [{] ---> [expression*] ---> [}]                      | 
 6088 | |                                                             | 
 6089 | +-------------------------------------------------------------+ 
 6090 |  
 6091 |  
 6092 | (04) - Repeat Until Loop 
 6093 | +-------------------------------------------------------------+ 
 6094 | |                                                             | 
 6095 | |   [repeat] ---> [expression*] ---+                          | 
 6096 | |                                  |                          | 
 6097 | |   +--------------<---------------+                          | 
 6098 | |   |                                                         | 
 6099 | |   +--> [until] ---> [(] ---> [condition] --->[)]            | 
 6100 | |                                                             | 
 6101 | +-------------------------------------------------------------+ 
 6102 |  
 6103 |  
 6104 | (05) - For Loop 
 6105 | +-------------------------------------------------------------+ 
 6106 | |                                                             | 
 6107 | |   [for] ---> [(] -+-> [initialise expression] --+--+        | 
 6108 | |                   |                             |  |        | 
 6109 | |                   +------------->---------------+  v        | 
 6110 | |                                                    |        | 
 6111 | |   +-----------------------<------------------------+        | 
 6112 | |   |                                                         | 
 6113 | |   +--> [;] -+-> [condition] -+-> [;] ---+                   | 
 6114 | |             |                |          |                   | 
 6115 | |             +------->--------+          v                   | 
 6116 | |                                         |                   | 
 6117 | |   +------------------<---------+--------+                   | 
 6118 | |   |                            |                            | 
 6119 | |   +--> [increment expression] -+-> [)] --+                  | 
 6120 | |                                          |                  | 
 6121 | |   +------------------<-------------------+                  | 
 6122 | |   |                                                         | 
 6123 | |   +--> [{] ---> [expression*] ---> [}]                      | 
 6124 | |                                                             | 
 6125 | +-------------------------------------------------------------+ 
 6126 |  
 6127 |  
 6128 | (06) - Switch Statement 
 6129 | +-------------------------------------------------------------+ 
 6130 | |                                                             | 
 6131 | |   [switch] ---> [{] ---+                                    | 
 6132 | |                        |                                    | 
 6133 | |   +---------<----------+-----------<-----------+            | 
 6134 | |   |                                            |            | 
 6135 | |   +--> [case] ---> [condition] ---> [:] ---+   |            | 
 6136 | |                                            |   |            | 
 6137 | |   +-------------------<--------------------+   |            | 
 6138 | |   |                                            |            | 
 6139 | |   +--> [consequent] ---> [;] --------->--------+            | 
 6140 | |   |                                            |            | 
 6141 | |   |                                            |            | 
 6142 | |   +--> [default] ---> [consequent] ---> [;] ---+            | 
 6143 | |   |                                            |            | 
 6144 | |   +---------------------<----------------------+            | 
 6145 | |   |                                                         | 
 6146 | |   +--> [}]                                                  | 
 6147 | |                                                             | 
 6148 | +-------------------------------------------------------------+ 
 6149 |  
 6150 |  
 6151 | (07) - Multi Subexpression Statement 
 6152 | +-------------------------------------------------------------+ 
 6153 | |                                                             | 
 6154 | |                   +--------------<---------------+          | 
 6155 | |                   |                              |          | 
 6156 | |   [~] ---> [{\(] -+-> [expression] -+-> [;\,] ---+          | 
 6157 | |                                     |                       | 
 6158 | |   +----------------<----------------+                       | 
 6159 | |   |                                                         | 
 6160 | |   +--> [}\)]                                                | 
 6161 | |                                                             | 
 6162 | +-------------------------------------------------------------+ 
 6163 |  
 6164 |  
 6165 | (08) - Multi Case-Consequent Statement 
 6166 | +-------------------------------------------------------------+ 
 6167 | |                                                             | 
 6168 | |   [[*]] ---> [{] ---+                                       | 
 6169 | |                     |                                       | 
 6170 | |   +--------<--------+--------------<----------+             | 
 6171 | |   |                                           |             | 
 6172 | |   +--> [case] ---> [condition] ---> [:] ---+  |             | 
 6173 | |                                            |  |             | 
 6174 | |   +-------------------<--------------------+  |             | 
 6175 | |   |                                           |             | 
 6176 | |   +--> [consequent] ---> [;] ---+------>------+             | 
 6177 | |                                 |                           | 
 6178 | |                                 +--> [}]                    | 
 6179 | |                                                             | 
 6180 | +-------------------------------------------------------------+ 
 6181 |  
 6182 |  
 6183 | (09) - Variable Definition Statement 
 6184 | +-------------------------------------------------------------+ 
 6185 | |                                                             | 
 6186 | |   [var] ---> [symbol] -+-> [:=] -+-> [expression] -+-> [;]  | 
 6187 | |                        |         |                 |        | 
 6188 | |                        |         +-----> [{}] -->--+        | 
 6189 | |                        |                           |        | 
 6190 | |                        +------------->-------------+        | 
 6191 | |                                                             | 
 6192 | +-------------------------------------------------------------+ 
 6193 |  
 6194 |  
 6195 | (10) - Vector Definition Statement 
 6196 | +-------------------------------------------------------------+ 
 6197 | |                                                             | 
 6198 | |   [var] ---> [symbol] ---> [[] ---> [constant] ---> []] --+ | 
 6199 | |                                                           | | 
 6200 | |   +---------------------------<---------------------------+ | 
 6201 | |   |                                                         | 
 6202 | |   |                   +--------->---------+                 | 
 6203 | |   |                   |                   |                 | 
 6204 | |   +--> [:=] ---> [{] -+-+-> [expression] -+-> [}] ---> [;]  | 
 6205 | |                         |                 |                 | 
 6206 | |                         +--<--- [,] <-----+                 | 
 6207 | |                                                             | 
 6208 | +-------------------------------------------------------------+ 
 6209 |  
 6210 |  
 6211 | (11) - String Definition Statement 
 6212 | +-------------------------------------------------------------+ 
 6213 | |                                                             | 
 6214 | |   [var] --> [symbol] --> [:=] --> [str-expression] ---> [;] | 
 6215 | |                                                             | 
 6216 | +-------------------------------------------------------------+ 
 6217 |  
 6218 |  
 6219 | (12) - Range Statement 
 6220 | +-------------------------------------------------------------+ 
 6221 | |                                                             | 
 6222 | |      +-------->--------+                                    | 
 6223 | |      |                 |                                    | 
 6224 | | [[] -+-> [expression] -+-> [:] -+-> [expression] -+--> []]  | 
 6225 | |                                 |                 |         | 
 6226 | |                                 +-------->--------+         | 
 6227 | |                                                             | 
 6228 | +-------------------------------------------------------------+ 
 6229 |  
 6230 |  
 6231 | (13) - Return Statement 
 6232 | +-------------------------------------------------------------+ 
 6233 | |                                                             | 
 6234 | |   [return] ---> [[] -+-> [expression] -+-> []] ---> [;]     | 
 6235 | |                      |                 |                    | 
 6236 | |                      +--<--- [,] <-----+                    | 
 6237 | |                                                             | 
 6238 | +-------------------------------------------------------------+