2012-01-28 05:25:39 +00:00
|
|
|
C++ Mathematical Expression Toolkit Library
|
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[00 - INTRODUCTION]
|
2013-04-04 09:45:19 +00:00
|
|
|
The C++ Mathematical Expression Toolkit Library (ExprTk) is a simple
|
2014-12-01 17:48:39 +00:00
|
|
|
to use, easy to integrate and extremely efficient run-time
|
|
|
|
mathematical expression parsing and evaluation engine. The parsing
|
|
|
|
engine supports numerous forms of functional and logic processing
|
|
|
|
semantics and is easily extendible.
|
2012-01-28 05:25:39 +00:00
|
|
|
|
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[01 - CAPABILITIES]
|
2014-02-11 09:39:45 +00:00
|
|
|
The ExprTk expression evaluator supports the following fundamental
|
|
|
|
arithmetic operations, functions and processes:
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(00) Types: Scalar, Vector, String
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(01) Basic operators: +, -, *, /, %, ^
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(02) Assignment: :=, +=, -=, *=, /=, %=
|
2013-07-16 22:21:06 +00:00
|
|
|
|
2014-05-03 21:49:15 +00:00
|
|
|
(03) Equalities &
|
|
|
|
Inequalities: =, ==, <>, !=, <, <=, >, >=
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-05-03 21:49:15 +00:00
|
|
|
(04) Boolean logic: and, mand, mor, nand, nor, not, or, shl, shr,
|
|
|
|
xnor, xor, true, false
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(05) Functions: abs, avg, ceil, clamp, equal, erf, erfc, exp,
|
|
|
|
expm1, floor, frac, log, log10, log1p, log2,
|
|
|
|
logn, max, min, mul, ncdf, nequal, root,
|
|
|
|
round, roundn, sgn, sqrt, sum, swap, trunc
|
|
|
|
|
|
|
|
(06) Trigonometry: acos, acosh, asin, asinh, atan, atanh, atan2,
|
|
|
|
cos, cosh, cot, csc, sec, sin, sinc, sinh,
|
|
|
|
tan, tanh, hypot, rad2deg, deg2grad, deg2rad,
|
|
|
|
grad2deg
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(07) Control
|
|
|
|
structures: if-then-else, ternary conditional, switch-case
|
2013-01-30 13:28:22 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(08) Loop statements: while, for, repeat-until, break, continue
|
2013-01-30 13:28:22 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(09) String
|
2014-12-07 19:33:10 +00:00
|
|
|
processing: in, like, ilike, concatenation
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(10) Optimisations: constant-folding and simple strength reduction
|
2014-05-03 21:49:15 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(11) Calculus: numerical integration and differentiation
|
2014-01-22 20:32:55 +00:00
|
|
|
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[02 - EXAMPLE EXPRESSIONS]
|
2014-12-14 06:38:05 +00:00
|
|
|
The following is a short listing of the types of mathematical
|
2012-05-05 11:07:37 +00:00
|
|
|
expressions that can be parsed and evaluated using the ExprTk library.
|
|
|
|
|
2014-02-11 09:39:45 +00:00
|
|
|
(01) sqrt(1 - (3 / x^2))
|
2014-02-09 09:20:15 +00:00
|
|
|
(02) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)
|
|
|
|
(03) sin(2.34e-3 * x)
|
2014-04-21 01:16:33 +00:00
|
|
|
(04) if(((x[2] + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)
|
2014-02-09 09:20:15 +00:00
|
|
|
(05) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)
|
|
|
|
(06) ({1/1}*[1/2]+(1/3))-{1/4}^[1/5]+(1/6)-({1/7}+[1/8]*(1/9))
|
|
|
|
(07) a * exp(2.2 / 3.3 * t) + c
|
|
|
|
(08) z := x + sin(2.567 * pi / y)
|
2014-02-11 09:39:45 +00:00
|
|
|
(09) u := 2.123 * {pi * z} / (w := x + cos(y / pi))
|
2014-02-09 09:20:15 +00:00
|
|
|
(10) 2x + 3y + 4z + 5w == 2 * x + 3 * y + 4 * z + 5 * w
|
|
|
|
(11) 3(x + y) / 2.9 + 1.234e+12 == 3 * (x + y) / 2.9 + 1.234e+12
|
2014-02-11 09:39:45 +00:00
|
|
|
(12) (x + y)3.3 + 1 / 4.5 == [x + y] * 3.3 + 1 / 4.5
|
2014-04-21 01:16:33 +00:00
|
|
|
(13) (x + y[i])z + 1.1 / 2.7 == (x + y[i]) * z + 1.1 / 2.7
|
2014-02-09 09:20:15 +00:00
|
|
|
(14) (sin(x / pi) cos(2y) + 1) == (sin(x / pi) * cos(2 * y) + 1)
|
|
|
|
(15) 75x^17 + 25.1x^5 - 35x^4 - 15.2x^3 + 40x^2 - 15.3x + 1
|
2014-04-06 21:01:02 +00:00
|
|
|
(16) (avg(x,y) <= x + y ? x - y : x * y) + 2.345 * pi / x
|
2014-11-17 11:03:10 +00:00
|
|
|
(17) while (x <= 100) { x -= 1; }
|
|
|
|
(18) x <= 'abc123' and (y in 'AString') or ('1x2y3z' != z)
|
2014-12-10 15:59:06 +00:00
|
|
|
(19) ((x + 'abc') like '*123*') or ('a123b' ilike y)
|
2014-11-17 11:03:10 +00:00
|
|
|
(20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x }
|
2012-05-05 11:07:37 +00:00
|
|
|
|
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[03 - COPYRIGHT NOTICE]
|
2013-04-04 09:45:19 +00:00
|
|
|
Free use of the C++ Mathematical Expression Toolkit Library is
|
|
|
|
permitted under the guidelines and in accordance with the most current
|
|
|
|
version of the Common Public License.
|
2012-01-28 05:25:39 +00:00
|
|
|
|
|
|
|
http://www.opensource.org/licenses/cpl1.0.php
|
|
|
|
|
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[04 - DOWNLOADS & UPDATES]
|
2014-04-13 21:36:26 +00:00
|
|
|
The most recent version of the C++ Mathematical Expression Toolkit
|
2013-04-04 09:45:19 +00:00
|
|
|
Library including all updates and tests can be found at the following
|
|
|
|
locations:
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
(a) Download: http://www.partow.net/programming/exprtk/index.html
|
|
|
|
(b) Repository: https://exprtk.googlecode.com/svn/
|
2012-01-28 05:25:39 +00:00
|
|
|
|
2012-05-05 11:07:37 +00:00
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[05 - INSTALLATION]
|
2014-04-13 21:36:26 +00:00
|
|
|
The header file exprtk.hpp should be placed in a project or system
|
2013-04-04 09:45:19 +00:00
|
|
|
include path (e.g: /usr/include/).
|
2012-01-28 05:25:39 +00:00
|
|
|
|
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[06 - COMPILATION]
|
2014-11-17 11:03:10 +00:00
|
|
|
(a) For a complete build: make clean all
|
|
|
|
(b) For a PGO build: make clean pgo
|
|
|
|
(c) To strip executables: make strip_bin
|
|
|
|
(d) Execute valgrind check: make valgrind_check
|
2012-01-28 05:25:39 +00:00
|
|
|
|
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[07 - COMPILER COMPATIBILITY]
|
2014-05-27 21:10:40 +00:00
|
|
|
ExprTk has been built error and warning free using the following set
|
|
|
|
of C++ compilers:
|
|
|
|
|
2014-04-19 11:10:15 +00:00
|
|
|
(*) GNU Compiler Collection (3.3+)
|
|
|
|
(*) Intel C++ Compiler (8.x+)
|
2014-02-09 09:20:15 +00:00
|
|
|
(*) Clang/LLVM (1.1+)
|
|
|
|
(*) PGI C++ (10.x+)
|
|
|
|
(*) Microsoft Visual Studio C++ Compiler (8.1+)
|
|
|
|
(*) Comeau C++ Compiler (4.3+)
|
2014-04-19 11:10:15 +00:00
|
|
|
(*) IBM XL C/C++ (9.x+)
|
2014-02-11 09:39:45 +00:00
|
|
|
(*) C++ Builder (XE4+)
|
2012-01-28 05:25:39 +00:00
|
|
|
|
|
|
|
|
2012-05-16 22:14:45 +00:00
|
|
|
|
2013-04-23 11:30:49 +00:00
|
|
|
[08 - BUILT-IN OPERATIONS & FUNCTIONS]
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-04-19 11:10:15 +00:00
|
|
|
(0) Arithmetic & Assignment Operators
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| OPERATOR | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| + | Addition between x and y. (eg: x + y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| - | Subtraction between x and y. (eg: x - y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| * | Multiplication between x and y. (eg: x * y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| / | Division between x and y. (eg: x / y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| % | Modulus of x with respect to y. (eg: x % y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| ^ | x to the power of y. (eg: x ^ y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-21 01:16:33 +00:00
|
|
|
| := | Assign the value of x to y. Where y is either a variable|
|
|
|
|
| | or vector type. (eg: y := x) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-19 11:10:15 +00:00
|
|
|
| += | Increment x to by the value of the expression on the |
|
2014-04-21 01:16:33 +00:00
|
|
|
| | right-hand side. Where x is either a variable or vector |
|
|
|
|
| | type. (eg: x += abs(y - z)) |
|
2014-04-19 11:10:15 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| -= | Decrement x to by the value of the expression on the |
|
2014-04-21 01:16:33 +00:00
|
|
|
| | right-hand side. Where x is either a variable or vector |
|
|
|
|
| | type. (eg: x[i] -= abs(y + z)) |
|
2014-04-19 11:10:15 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| *= | Assign the multiplication of x by the value of the |
|
2014-04-21 01:16:33 +00:00
|
|
|
| | expression on the righthand side to x. Where x is either|
|
2014-05-27 21:10:40 +00:00
|
|
|
| | a variable or vector type. |
|
2014-04-19 11:10:15 +00:00
|
|
|
| | (eg: x *= abs(y / z)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| /= | Assign the division of x by the value of the expression |
|
2014-04-21 01:16:33 +00:00
|
|
|
| | on the right-hand side to x. Where x is either a |
|
2014-11-17 11:03:10 +00:00
|
|
|
| | variable or vector type. (eg: x[i + j] /= abs(y * z)) |
|
2014-04-19 11:10:15 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-05-27 21:10:40 +00:00
|
|
|
| %= | Assign x modulo the value of the expression on the right|
|
|
|
|
| | hand side to x. Where x is either a variable or vector |
|
|
|
|
| | type. (eg: x[2] %= y ^ 2) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
(1) Equalities & Inequalities
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| OPERATOR | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| == or = | True only if x is strictly equal to y. (eg: x == y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-28 11:35:06 +00:00
|
|
|
| <> or != | True only if x does not equal y. (eg: x <> y or x != y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| < | True only if x is less than y. (eg: x < y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| <= | True only if x is less than or equal to y. (eg: x <= y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| > | True only if x is greater than y. (eg: x > y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-28 11:35:06 +00:00
|
|
|
| >= | True only if x greater than or equal to y. (eg: x >= y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
(2) Boolean Operations
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| OPERATOR | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| true | True state or any value other than zero (typically 1). |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| false | False state, value of zero. |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| and | Logical AND, True only if x and y are both true. |
|
|
|
|
| | (eg: x and y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| mand | Multi-input logical AND, True only if all inputs are |
|
|
|
|
| | true. Left to right short-circuiting of expressions. |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: mand(x > y, z < w, u or v, w and x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| mor | Multi-input logical OR, True if at least one of the |
|
|
|
|
| | inputs are true. Left to right short-circuiting of |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | expressions. (eg: mor(x > y, z < w, u or v, w and x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| nand | Logical NAND, True only if either x or y is false. |
|
|
|
|
| | (eg: x nand y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| nor | Logical NOR, True only if the result of x or y is false |
|
|
|
|
| | (eg: x nor y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| not | Logical NOT, Negate the logical sense of the input. |
|
|
|
|
| | (eg: not(x and y) == x nand y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| or | Logical OR, True if either x or y is true. (eg: x or y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| xor | Logical XOR, True only if the logical states of x and y |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | differ. (eg: x xor y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| xnor | Logical XNOR, True iff the biconditional of x and y is |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | satisfied. (eg: x xnor y) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| & | Similar to AND but with left to right expression short |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | circuiting optimisation. (eg: (x & y) == (y and x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| | | Similar to OR but with left to right expression short |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | circuiting optimisation. (eg: (x | y) == (y or x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
(3) General Purpose Functions
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| FUNCTION | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| abs | Absolute value of x. (eg: abs(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| avg | Average of all the inputs. |
|
|
|
|
| | (eg: avg(x,y,z,w,u,v) == (x + y + z + w + u + v) / 6) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| ceil | Smallest integer that is greater than or equal to x. |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| clamp | Clamp x in range between r0 and r1, where r0 < r1. |
|
|
|
|
| | (eg: clamp(r0,x,r1) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| equal | Equality test between x and y using normalized epsilon |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| erf | Error function of x. (eg: erf(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| erfc | Complimentary error function of x. (eg: erfc(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| exp | e to the power of x. (eg: exp(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-12 13:08:57 +00:00
|
|
|
| expm1 | e to the power of x minus 1, where x is very small. |
|
|
|
|
| | (eg: expm1(x)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-08 22:32:08 +00:00
|
|
|
| floor | Largest integer that is less than or equal to x. |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: floor(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| frac | Fractional portion of x. (eg: frac(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| hypot | Hypotenuse of x and y (eg: hypot(x,y) = sqrt(x*x + y*y))|
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-01-14 20:13:18 +00:00
|
|
|
| iclamp | Inverse-clamp x outside of the range r0 and r1. Where |
|
|
|
|
| | r0 < r1. If x is within the range it will snap to the |
|
|
|
|
| | closest bound. (eg: iclamp(r0,x,r1) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-06-01 03:03:29 +00:00
|
|
|
| inrange | In-range returns 'true' when x is within the range r0 |
|
|
|
|
| | and r1. Where r0 < r1. (eg: inrange(r0,x,r1) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| log | Natural logarithm of x. (eg: log(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| log10 | Base 10 logarithm of x. (eg: log10(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| log1p | Natural logarithm of 1 + x, where x is very small. |
|
|
|
|
| | (eg: log1p(x)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| log2 | Base 2 logarithm of x. (eg: log2(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| logn | Base N logarithm of x. where n is a positive integer. |
|
|
|
|
| | (eg: logn(x,8)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| max | Largest value of all the inputs. (eg: max(x,y,z,w,u,v)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| min | Smallest value of all the inputs. (eg: min(x,y,z,w,u)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| mul | Product of all the inputs. |
|
|
|
|
| | (eg: mul(x,y,z,w,u,v,t) == (x * y * z * w * u * v * t)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-06-09 07:36:58 +00:00
|
|
|
| ncdf | Normal cumulative distribution function. (eg: ncdf(x)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-08 22:32:08 +00:00
|
|
|
| nequal | Not-equal test between x and y using normalized epsilon |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| root | Nth-Root of x. where n is a positive integer. |
|
|
|
|
| | (eg: root(x,3)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| round | Round x to the nearest integer. (eg: round(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| roundn | Round x to n decimal places (eg: roundn(x,3)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | where n > 0 and is an integer. |
|
|
|
|
| | (eg: roundn(1.2345678,4) == 1.2346) |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| sgn | Sign of x, -1 where x < 0, +1 where x > 0, else zero. |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: sgn(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| sqrt | Square root of x, where x > 0. (eg: sqrt(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| sum | Sum of all the inputs. |
|
|
|
|
| | (eg: sum(x,y,z,w,u,v,t) == (x + y + z + w + u + v + t)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-05-27 21:10:40 +00:00
|
|
|
| swap | Swap the values of the variables x and y and return the |
|
|
|
|
| <=> | current value of y. (eg: swap(x,y) or x <=> y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| trunc | Integer portion of x. (eg: trunc(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
(4) Trigonometry Functions
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| FUNCTION | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| acos | Arc cosine of x expressed in radians. Interval [-1,+1] |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: acos(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-01-03 10:42:54 +00:00
|
|
|
| acosh | Inverse hyperbolic cosine of x expressed in radians. |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: acosh(x)) |
|
2014-01-03 10:42:54 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-08 22:32:08 +00:00
|
|
|
| asin | Arc sine of x expressed in radians. Interval [-1,+1] |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: asin(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-01-03 10:42:54 +00:00
|
|
|
| asinh | Inverse hyperbolic sine of x expressed in radians. |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: asinh(x)) |
|
2014-01-03 10:42:54 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-08 22:32:08 +00:00
|
|
|
| atan | Arc tangent of x expressed in radians. Interval [-1,+1] |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: atan(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-13 21:36:26 +00:00
|
|
|
| atan2 | Arc tangent of (x / y) expressed in radians. [-pi,+pi] |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | eg: atan2(x,y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-01-03 10:42:54 +00:00
|
|
|
| atanh | Inverse hyperbolic tangent of x expressed in radians. |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | (eg: atanh(x)) |
|
2014-01-03 10:42:54 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| cos | Cosine of x. (eg: cos(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| cosh | Hyperbolic cosine of x. (eg: cosh(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| cot | Cotangent of x. (eg: cot(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| csc | Cosecant of x. (eg: csc(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| sec | Secant of x. (eg: sec(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| sin | Sine of x. (eg: sin(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-05-03 21:49:15 +00:00
|
|
|
| sinc | Sine cardinal of x. (eg: sinc(x)) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| sinh | Hyperbolic sine of x. (eg: sinh(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| tan | Tangent of x. (eg: tan(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| tanh | Hyperbolic tangent of x. (eg: tanh(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| deg2rad | Convert x from degrees to radians. (eg: deg2rad(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| deg2grad | Convert x from degrees to gradians. (eg: deg2grad(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| rad2deg | Convert x from radians to degrees. (eg: rad2deg(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| grad2deg | Convert x from gradians to degrees. (eg: grad2deg(x)) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
(5) String Processing
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| FUNCTION | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-02-11 09:39:45 +00:00
|
|
|
| = , == | All common equality/inequality operators are applicable |
|
|
|
|
| !=, <> | to strings and are applied in a case sensitive manner. |
|
|
|
|
| <=, >= | In the following example x, y and z are of type string. |
|
|
|
|
| < , > | (eg: not((x <= 'AbC') and ('1x2y3z' <> y)) or (z == x) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-28 11:35:06 +00:00
|
|
|
| in | True only if x is a substring of y. |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | (eg: x in y or 'abc' in 'abcdefgh') |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| like | True only if the string x matches the pattern y. |
|
|
|
|
| | Available wildcard characters are '*' and '?' denoting |
|
|
|
|
| | zero or more and zero or one matches respectively. |
|
|
|
|
| | (eg: x like y or 'abcdefgh' like 'a?d*h') |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| ilike | True only if the string x matches the pattern y in a |
|
|
|
|
| | case insensitive manner. Available wildcard characters |
|
|
|
|
| | are '*' and '?' denoting zero or more and zero or one |
|
|
|
|
| | matches respectively. |
|
|
|
|
| | (eg: x ilike y or 'a1B2c3D4e5F6g7H' ilike 'a?d*h') |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| [r0:r1] | The closed interval [r0,r1] of the specified string. |
|
|
|
|
| | eg: Given a string x with a value of 'abcdefgh' then: |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | 1. x[1:4] == 'bcde' |
|
|
|
|
| | 2. x[ :5] == x[:5] == 'abcdef' |
|
|
|
|
| | 3. x[3: ] == x[3:] =='cdefgh' |
|
|
|
|
| | 4. x[ : ] == x[:] == 'abcdefgh' |
|
|
|
|
| | 5. x[4/2:3+2] == x[2:5] == 'cdef' |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | |
|
2013-07-12 13:08:57 +00:00
|
|
|
| | Note: Both r0 and r1 are assumed to be integers, where |
|
|
|
|
| | r0 <= r1. They may also be the result of an expression, |
|
|
|
|
| | in the event they have fractional components truncation |
|
2014-02-11 09:39:45 +00:00
|
|
|
| | will be performed. (eg: 1.67 --> 1) |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-12-03 20:51:26 +00:00
|
|
|
| := | Assign the value of x to y. Where x is a mutable string |
|
|
|
|
| | and y is either a string or a string range. eg: |
|
|
|
|
| | 1. x := y |
|
|
|
|
| | 2. x := 'abc' |
|
|
|
|
| | 3. x := y[:i + j] |
|
|
|
|
| | 4. x := '0123456789'[2:7] |
|
|
|
|
| | 5. x := '0123456789'[2i + 1:7] |
|
|
|
|
| | 6. x := (y := '0123456789'[2:7]) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-12-07 19:33:10 +00:00
|
|
|
| + | Concatenation of x and y. Where x and y are strings or |
|
|
|
|
| | string ranges. eg |
|
|
|
|
| | 1. x + y |
|
|
|
|
| | 2. x + 'abc' |
|
|
|
|
| | 3. x + y[:i + j] |
|
|
|
|
| | 4. x[i:j] + y[2:3] + '0123456789'[2:7] |
|
|
|
|
| | 5. 'abc' + x + y |
|
|
|
|
| | 6. 'abc' + '1234567' |
|
2014-12-08 13:45:32 +00:00
|
|
|
| | 7. (x + 'a1B2c3D4' + y)[i:2j] |
|
2014-12-07 19:33:10 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-12-09 14:42:42 +00:00
|
|
|
| += | Append to x the value of y. Where x is a mutable string |
|
|
|
|
| | and y is either a string or a string range. eg: |
|
|
|
|
| | 1. x += y |
|
|
|
|
| | 2. x += 'abc' |
|
|
|
|
| | 3. x += y[:i + j] + 'abc' |
|
|
|
|
| | 4. x += '0123456789'[2:7] |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-12-09 21:06:54 +00:00
|
|
|
| <=> | Swap the values of x and y. Where x and y are mutable |
|
|
|
|
| | strings. (eg: x <=> y) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-06-08 09:24:53 +00:00
|
|
|
| [] | The string size operator returns the size of the string |
|
|
|
|
| | being actioned. |
|
|
|
|
| | eg: |
|
|
|
|
| | 1. 'abc'[] == 3 |
|
|
|
|
| | 2. var max_str_length := max(s0[],s1[],s2[],s3[]) |
|
2014-12-08 13:45:32 +00:00
|
|
|
| | 3. ('abc' + 'xyz')[] == 3 |
|
|
|
|
| | 4. (('abc' + 'xyz')[1:4])[] == 4 |
|
2014-06-08 09:24:53 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2013-04-27 03:55:23 +00:00
|
|
|
(6) Control Structures
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
|STRUCTURE | DEFINITION |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| if | If x is true then return y else return z. |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | eg: |
|
|
|
|
| | 1. if(x, y, z) |
|
|
|
|
| | 2. if((x + 1) > 2y, z + 1, w / v) |
|
2014-12-07 19:33:10 +00:00
|
|
|
| | 3. if(x > y) z; |
|
|
|
|
| | 4. if(x <= 2*y) { z + w }; |
|
2014-04-13 21:36:26 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| if-else | The if-else/else-if statement. Subject to the condition |
|
|
|
|
| | branch the statement will return either the value of the|
|
|
|
|
| | consequent or the alternative branch. |
|
|
|
|
| | eg: |
|
|
|
|
| | 1. if (x > y) z; else w; |
|
|
|
|
| | 2. if (x > y) z; else if (w != u) v; |
|
2014-11-17 11:03:10 +00:00
|
|
|
| | 3. if (x < y) {z; w + 1;} else u; |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | 4. if ((x != y) and (z > w)) |
|
|
|
|
| | { |
|
|
|
|
| | y := sin(x) / u; |
|
2014-11-17 11:03:10 +00:00
|
|
|
| | z := w + 1; |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | } |
|
|
|
|
| | else if (x > (z + 1)) |
|
|
|
|
| | { |
|
|
|
|
| | w := abs (x - y) + z; |
|
|
|
|
| | u := (x + 1) > 2y ? 2u : 3u; |
|
|
|
|
| | } |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| switch | The first true case condition that is encountered will |
|
|
|
|
| | determine the result of the switch. If none of the case |
|
|
|
|
| | conditions hold true, the default action is assumed as |
|
|
|
|
| | the final return value. This is sometimes also known as |
|
|
|
|
| | a multi-way branch mechanism. |
|
|
|
|
| | eg: |
|
|
|
|
| | switch |
|
|
|
|
| | { |
|
|
|
|
| | case x > (y + z) : 2 * x / abs(y - z); |
|
2013-10-16 21:44:15 +00:00
|
|
|
| | case x < 3 : sin(x + y); |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | default : 1 + x; |
|
|
|
|
| | } |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| while | The structure will repeatedly evaluate the internal |
|
|
|
|
| | statement(s) 'while' the condition is true. The final |
|
|
|
|
| | statement in the final iteration will be used as the |
|
|
|
|
| | return value of the loop. |
|
|
|
|
| | eg: |
|
2014-04-19 11:10:15 +00:00
|
|
|
| | while ((x -= 1) > 0) |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | { |
|
|
|
|
| | y := x + z; |
|
2014-04-19 11:10:15 +00:00
|
|
|
| | w := u + y; |
|
2013-07-08 22:32:08 +00:00
|
|
|
| | } |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| repeat/ | The structure will repeatedly evaluate the internal |
|
|
|
|
| until | statement(s) 'until' the condition is true. The final |
|
|
|
|
| | statement in the final iteration will be used as the |
|
|
|
|
| | return value of the loop. |
|
|
|
|
| | eg: |
|
|
|
|
| | repeat |
|
|
|
|
| | y := x + z; |
|
2014-04-19 11:10:15 +00:00
|
|
|
| | w := u + y; |
|
2014-04-21 01:16:33 +00:00
|
|
|
| | until ((x += 1) > 100) |
|
2014-04-19 11:10:15 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| for | The structure will repeatedly evaluate the internal |
|
|
|
|
| | statement(s) while the condition is true. On each loop |
|
|
|
|
| | iteration, an 'incrementing' expression is evaluated. |
|
2014-11-17 11:03:10 +00:00
|
|
|
| | The conditional is mandatory whereas the initialiser |
|
2014-04-19 11:10:15 +00:00
|
|
|
| | and incrementing expressions are optional. |
|
|
|
|
| | eg: |
|
2014-07-01 10:46:51 +00:00
|
|
|
| | for (var x := 0; (x < n) and (x != y); x += 1) |
|
2014-04-19 11:10:15 +00:00
|
|
|
| | { |
|
|
|
|
| | y := y + x / 2 - z; |
|
|
|
|
| | w := u + y; |
|
|
|
|
| | } |
|
2013-07-08 22:32:08 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-27 04:15:43 +00:00
|
|
|
| break | Break terminates the execution of the nearest enclosed |
|
|
|
|
| break[] | loop, allowing for the execution to continue on external|
|
|
|
|
| | to the loop. The default break statement will set the |
|
|
|
|
| | return value of the loop to NaN, where as the return |
|
|
|
|
| | based form will set the value to that of the break |
|
|
|
|
| | expression. |
|
|
|
|
| | eg: |
|
|
|
|
| | while ((i += 1) < 10) |
|
|
|
|
| | { |
|
|
|
|
| | if (i < 5) |
|
|
|
|
| | j -= i + 2; |
|
|
|
|
| | else if (i % 2 == 0) |
|
|
|
|
| | break; |
|
|
|
|
| | else |
|
|
|
|
| | break[2i + 3]; |
|
|
|
|
| | } |
|
|
|
|
+----------+---------------------------------------------------------+
|
|
|
|
| continue | Continue results in the remaining portion of the nearest|
|
|
|
|
| | enclosing loop body to be skipped. |
|
|
|
|
| | eg: |
|
2014-07-01 10:46:51 +00:00
|
|
|
| | for (var i := 0; i < 10; i += 1) |
|
2014-04-27 04:15:43 +00:00
|
|
|
| | { |
|
|
|
|
| | if (i < 5) |
|
|
|
|
| | continue; |
|
|
|
|
| | j -= i + 2; |
|
|
|
|
| | } |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-04-06 21:01:02 +00:00
|
|
|
| ?: | Ternary conditional statement, similar to that of the |
|
|
|
|
| | above denoted if-statement. |
|
|
|
|
| | eg: |
|
2014-04-13 21:36:26 +00:00
|
|
|
| | 1. x ? y : z |
|
|
|
|
| | 2. x + 1 > 2y ? z + 1 : (w / v) |
|
|
|
|
| | 3. min(x,y) > z ? (x < y + 1) ? x : y : (w * v) |
|
2014-04-06 21:01:02 +00:00
|
|
|
+----------+---------------------------------------------------------+
|
2013-07-08 22:32:08 +00:00
|
|
|
| ~ | Evaluate each sub-expression, then return as the result |
|
|
|
|
| | the value of the last sub-expression. This is sometimes |
|
|
|
|
| | known as multiple sequence point evaluation. |
|
|
|
|
| | eg: |
|
|
|
|
| | ~(i := x + 1, j := y / z, k := sin(w/u)) == (sin(w/u))) |
|
|
|
|
| | ~{i := x + 1; j := y / z; k := sin(w/u)} == (sin(w/u))) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-01-05 08:49:26 +00:00
|
|
|
| [*] | Evaluate any consequent for which its case statement is |
|
|
|
|
| | true. The return value will be either zero or the result|
|
|
|
|
| | of the last consequent to have been evaluated. |
|
|
|
|
| | eg: |
|
|
|
|
| | [*] |
|
|
|
|
| | { |
|
2014-01-14 20:13:18 +00:00
|
|
|
| | case (x + 1) > (y - 2) : x := z / 2 + sin(y / pi); |
|
|
|
|
| | case (x + 2) < abs(y + 3): w / 4 + min(5y,9); |
|
|
|
|
| | case (x + 3) = (y * 4) : y := abs(z / 6) + 7y; |
|
2014-01-05 08:49:26 +00:00
|
|
|
| | } |
|
|
|
|
+----------+---------------------------------------------------------+
|
2014-05-27 21:10:40 +00:00
|
|
|
| [] | The vector size operator returns the size of the vector |
|
|
|
|
| | being actioned. |
|
|
|
|
| | eg: |
|
|
|
|
| | 1. v[] |
|
|
|
|
| | 2. max_size := max(v0[],v1[],v2[],v3[]) |
|
|
|
|
+----------+---------------------------------------------------------+
|
2013-04-27 03:55:23 +00:00
|
|
|
|
2014-04-13 21:36:26 +00:00
|
|
|
Note: In the above tables, the symbols x, y, z, w, u and v where
|
|
|
|
appropriate may represent any of one the following:
|
2014-02-11 09:39:45 +00:00
|
|
|
|
|
|
|
1. Literal numeric/string value
|
|
|
|
2. A variable
|
2014-04-21 01:16:33 +00:00
|
|
|
3. A vector element
|
2014-06-08 09:24:53 +00:00
|
|
|
4. A vector
|
2014-12-10 15:59:06 +00:00
|
|
|
5. A string
|
2014-12-10 18:23:16 +00:00
|
|
|
6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3])
|
2014-02-11 09:39:45 +00:00
|
|
|
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
[09 - Fundamental Types]
|
|
|
|
ExprTk supports three fundamental types which can be used freely in
|
|
|
|
expressions. The types are as follows:
|
|
|
|
|
|
|
|
1. Scalar
|
|
|
|
2. Vector
|
|
|
|
3. String
|
|
|
|
|
|
|
|
|
|
|
|
(1) Scalar Type
|
|
|
|
The scalar type is a singular numeric value. The underlying type is
|
|
|
|
that used to specialize the ExprTk components (float, double, long
|
|
|
|
double MPFR et al).
|
|
|
|
|
|
|
|
|
|
|
|
(2) Vector Type
|
|
|
|
The vector type is a fixed size sequence of scalar values. A vector
|
|
|
|
can be indexed resulting in a scalar value. Operations between a
|
|
|
|
vector and scalar will result in a vector with a size equal to that of
|
|
|
|
the original vector, whereas operations between vectors will result in
|
|
|
|
a vector of size equal to that of the smaller of the two.
|
|
|
|
|
|
|
|
|
|
|
|
(3) String Type
|
|
|
|
The string type is a variable length sequence of 8-bit chars. Strings
|
|
|
|
can be assigned and concatenated to one another, they can also be
|
|
|
|
manipulated via sub-ranges using the range definition syntax. Strings
|
|
|
|
however can not interact with scalar or vector types.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[10 - COMPONENTS]
|
2013-10-16 21:44:15 +00:00
|
|
|
There are three primary components, that are specialized upon a given
|
|
|
|
numeric type, which make up the core of ExprTk. The components are as
|
|
|
|
follows:
|
|
|
|
|
2014-04-13 21:36:26 +00:00
|
|
|
1. Symbol Table exprtk::symbol_table<NumericType>
|
|
|
|
2. Expression exprtk::expression<NumericType>
|
|
|
|
3. Parser exprtk::parser<NumericType>
|
2013-10-16 21:44:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
(1) Symbol Table
|
|
|
|
A structure that is used to store references to variables, constants
|
2014-02-09 09:20:15 +00:00
|
|
|
and functions that are to be used within expressions. Furthermore in
|
|
|
|
the context of composited recursive functions the symbol table can
|
|
|
|
also be thought of as a simple representation of a stack specific for
|
2014-02-11 09:39:45 +00:00
|
|
|
the expression(s) that reference it. The following is a list of the
|
|
|
|
types a symbol table can handle:
|
|
|
|
|
|
|
|
(a) Numeric variables
|
|
|
|
(b) Numeric constants
|
2014-04-21 01:16:33 +00:00
|
|
|
(c) Numeric vector elements
|
|
|
|
(d) String variables
|
|
|
|
(e) String constants
|
|
|
|
(f) Functions
|
|
|
|
(g) Vararg functions
|
2014-02-09 09:20:15 +00:00
|
|
|
|
2014-04-06 21:01:02 +00:00
|
|
|
During the compilation process if an expression is found to require
|
|
|
|
any of the elements noted above, the expression's associated
|
|
|
|
symbol_table will be queried for the element and if present a
|
|
|
|
reference to the element will be embedded within the expression's AST.
|
|
|
|
This allows for the original element to be modified independently of
|
|
|
|
the expression instance and to also allow the expression to be
|
|
|
|
evaluated using the current value of the element.
|
|
|
|
|
|
|
|
The example below demonstrates the relationship between variables,
|
|
|
|
symbol_table and expression. Note the variables are modified as they
|
|
|
|
normally would in a program, and when the expression is evaluated the
|
|
|
|
current values assigned to the variables will be used.
|
|
|
|
|
|
|
|
typedef exprtk::symbol_table<double> symbol_table_t;
|
|
|
|
typedef exprtk::expression<double> expression_t;
|
|
|
|
typedef exprtk::parser<double> parser_t;
|
|
|
|
|
|
|
|
symbol_table_t symbol_table;
|
|
|
|
expression_t expression;
|
|
|
|
parser_t parser;
|
|
|
|
|
|
|
|
double x = 0;
|
|
|
|
double y = 0;
|
|
|
|
|
|
|
|
std::string expression_string = "x * y + 3";
|
|
|
|
symbol_table.add_variable("x",x);
|
|
|
|
symbol_table.add_variable("y",y);
|
|
|
|
|
|
|
|
expression.register_symbol_table(symbol_table);
|
|
|
|
|
|
|
|
parser.compile(expression_string,expression);
|
|
|
|
|
|
|
|
x = 1.0;
|
|
|
|
y = 2.0;
|
2014-05-27 21:10:40 +00:00
|
|
|
expression.value(); // 1 * 2 + 3
|
|
|
|
|
2014-04-06 21:01:02 +00:00
|
|
|
x = 3.7;
|
2014-05-27 21:10:40 +00:00
|
|
|
expression.value(); // 3.7 * 2 + 3
|
|
|
|
|
2014-04-06 21:01:02 +00:00
|
|
|
y = -9.0;
|
2014-05-27 21:10:40 +00:00
|
|
|
expression.value(); // 3.7 * -9 + 3
|
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
// 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001
|
2014-07-01 10:46:51 +00:00
|
|
|
for (var x = 0; x < 100; x += 0.0001)
|
2014-05-27 21:10:40 +00:00
|
|
|
{
|
|
|
|
expression.value(); // x * -9 + 3
|
|
|
|
}
|
2014-04-06 21:01:02 +00:00
|
|
|
|
2013-10-16 21:44:15 +00:00
|
|
|
|
|
|
|
(2) Expression
|
2014-12-07 19:33:10 +00:00
|
|
|
A structure that holds an abstract syntax tree or AST for a specified
|
|
|
|
expression and is used to evaluate said expression. Evaluation of the
|
|
|
|
expression is accomplished by performing a post-order traversal of the
|
|
|
|
AST. If a compiled Expression uses variables or user defined
|
|
|
|
functions, it will have an associated Symbol Table, which will contain
|
|
|
|
references to said variables, functions or string. An example AST
|
|
|
|
structure for the denoted expression is as follows:
|
2014-01-03 10:42:54 +00:00
|
|
|
|
|
|
|
Expression: z := (x + y^-2.345) * sin(pi / min(w - 7.3,v))
|
|
|
|
|
|
|
|
[Root]
|
|
|
|
|
|
|
|
|
[Assignment]
|
|
|
|
________/ \_____
|
|
|
|
/ \
|
2014-04-06 21:01:02 +00:00
|
|
|
Variable(z) [Multiplication]
|
2014-01-03 10:42:54 +00:00
|
|
|
____________/ \___________
|
|
|
|
/ \
|
|
|
|
/ [Unary-Func(sin)]
|
|
|
|
[Addition] |
|
|
|
|
____/ \____ [Division]
|
|
|
|
/ \ ___/ \___
|
2014-04-06 21:01:02 +00:00
|
|
|
Variable(x) [Exponentiation] / \
|
2014-01-03 10:42:54 +00:00
|
|
|
______/ \______ Constant(pi) [Binary-Func(min)]
|
2014-01-21 21:13:37 +00:00
|
|
|
/ \ ____/ \____
|
2014-04-06 21:01:02 +00:00
|
|
|
Variable(y) [Negation] / \
|
2014-01-21 21:13:37 +00:00
|
|
|
| / Variable(v)
|
|
|
|
Constant(2.345) /
|
|
|
|
/
|
2014-04-06 21:01:02 +00:00
|
|
|
[Subtraction]
|
2014-01-21 21:13:37 +00:00
|
|
|
____/ \____
|
|
|
|
/ \
|
|
|
|
Variable(w) Constant(7.3)
|
2013-10-16 21:44:15 +00:00
|
|
|
|
2014-02-09 09:20:15 +00:00
|
|
|
|
2013-10-16 21:44:15 +00:00
|
|
|
(3) Parser
|
2014-12-10 15:59:06 +00:00
|
|
|
A structure which takes as input a string representation of an
|
|
|
|
expression and attempts to compile said input with the result
|
|
|
|
being an instance of Expression. If an error is encountered
|
|
|
|
during the compilation process, the parser will stop compiling
|
|
|
|
and return an error status code, with a more detailed
|
|
|
|
description of the error(s) and its location within the input
|
|
|
|
provided by the 'get_error' interface.
|
2013-10-16 21:44:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
[11 - COMPILATION OPTIONS]
|
2014-02-09 09:20:15 +00:00
|
|
|
The exprtk::parser when being instantiated takes as input a set of
|
|
|
|
options to be used during the compilation process of expressions.
|
|
|
|
An example instantiation of exprtk::parser where only the joiner,
|
|
|
|
commutative and strength reduction options are enabled is as follows:
|
|
|
|
|
2014-02-19 17:59:57 +00:00
|
|
|
typedef exprtk::parser<NumericType> parser_t;
|
2014-02-09 09:20:15 +00:00
|
|
|
|
2014-02-19 17:59:57 +00:00
|
|
|
std::size_t compile_options = parser_t::e_joiner +
|
|
|
|
parser_t::e_commutative_check +
|
|
|
|
parser_t::e_strength_reduction;
|
|
|
|
|
|
|
|
parser_t parser(compile_options);
|
2014-02-09 09:20:15 +00:00
|
|
|
|
|
|
|
|
2014-02-11 09:39:45 +00:00
|
|
|
Currently seven types of compile time options are supported, and
|
|
|
|
enabled by default. The options and their explanations are as follows:
|
2014-02-09 09:20:15 +00:00
|
|
|
|
|
|
|
(1) Replacer (e_replacer)
|
|
|
|
Enable replacement of specific tokens with other tokens. For example
|
|
|
|
the token "true" of type symbol will be replaced with the numeric
|
|
|
|
token of value one.
|
|
|
|
|
|
|
|
(a) (x < y) == true ---> (x < y) == 1
|
|
|
|
(b) false == (x > y) ---> 0 == (x > y)
|
|
|
|
|
|
|
|
|
|
|
|
(2) Joiner (e_joiner)
|
|
|
|
Enable joining of multi-character operators that may have been
|
|
|
|
incorrectly disjoint in the string representation of the specified
|
|
|
|
expression. For example the consecutive tokens of ">" "=" will become
|
|
|
|
">=" representing the "greater than or equal to" operator. If not
|
|
|
|
properly resolved the original form will cause a compilation error.
|
2014-11-30 09:48:19 +00:00
|
|
|
The following is a listing of the scenarios that the joiner can
|
2014-02-09 09:20:15 +00:00
|
|
|
handle:
|
|
|
|
|
2014-10-14 11:06:52 +00:00
|
|
|
(a) '>' '=' ---> '>=' (gte)
|
|
|
|
(b) '<' '=' ---> '<=' (lte)
|
|
|
|
(c) '=' '=' ---> '==' (equal)
|
|
|
|
(d) '!' '=' ---> '!=' (not-equal)
|
|
|
|
(e) '<' '>' ---> '<>' (not-equal)
|
|
|
|
(f) ':' '=' ---> ':=' (assignment)
|
|
|
|
(g) '+' '=' ---> '+=' (addition assignment)
|
|
|
|
(h) '-' '=' ---> '-=' (subtraction assignment)
|
|
|
|
(i) '*' '=' ---> '*=' (multiplication assignment)
|
|
|
|
(j) '/' '=' ---> '/=' (division assignment)
|
|
|
|
(k) '%' '=' ---> '%=' (modulo assignment)
|
|
|
|
(l) '<=' '>' ---> '<=>' (swap)
|
|
|
|
|
2014-02-09 09:20:15 +00:00
|
|
|
|
|
|
|
An example of the transformation that takes place is as follows:
|
|
|
|
|
|
|
|
(a) (x > = y) and (z ! = w) ---> (x >= y) and (z != w)
|
|
|
|
|
|
|
|
|
|
|
|
(3) Numeric Check (e_numeric_check)
|
|
|
|
Enable validation of tokens representing numeric types so as to catch
|
|
|
|
any errors prior to the costly process of the main compilation step
|
|
|
|
commencing.
|
|
|
|
|
|
|
|
|
|
|
|
(4) Bracket Check (e_bracket_check)
|
|
|
|
Enable the check for validating the ordering of brackets in the
|
|
|
|
specified expression.
|
|
|
|
|
|
|
|
|
|
|
|
(5) Sequence Check (e_sequence_check)
|
|
|
|
Enable the check for validating that sequences of either pairs or
|
|
|
|
triplets of tokens make sense. For example the following sequence of
|
|
|
|
tokens when encountered will raise an error:
|
|
|
|
|
|
|
|
(a) (x + * 3) ---> sequence error
|
|
|
|
|
|
|
|
|
|
|
|
(6) Commutative Check (e_commutative_check)
|
|
|
|
Enable the check that will transform sequences of pairs of tokens that
|
|
|
|
imply a multiplication operation. The following are some examples of
|
|
|
|
such transformations:
|
|
|
|
|
|
|
|
(a) 2x ---> 2 * x
|
|
|
|
(b) 25x^3 ---> 25 * x^3
|
|
|
|
(c) 3(x + 1) ---> 3 * (x + 1)
|
|
|
|
(d) (x + 1)4 ---> (x + 1) * 4
|
|
|
|
(e) 5foo(x,y) ---> 5 * foo(x,y)
|
|
|
|
(f) foo(x,y)6 + 1 ---> foo(x,y) * 6 + 1
|
2014-02-11 09:39:45 +00:00
|
|
|
(g) (4((2x)3)) ---> 4 * ((2 * x) * 3)
|
2014-12-17 16:43:27 +00:00
|
|
|
(h) w(x) + (y)z ---> w * x + y * z
|
2014-02-09 09:20:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
(7) Strength Reduction Check (e_strength_reduction)
|
|
|
|
Enable the use of strength reduction optimisations during the
|
|
|
|
compilation process. In ExprTk strength reduction optimisations
|
|
|
|
predominantly involve transforming sub-expressions into other forms
|
|
|
|
that are algebraically equivalent yet less costly to compute. The
|
|
|
|
following are examples of the various transformations that can occur:
|
|
|
|
|
|
|
|
(a) (x / y) / z ---> x / (y * z)
|
|
|
|
(b) (x / y) / (z / w) ---> (x * w) / (y * z)
|
|
|
|
(c) (2 * x) - (2 * y) ---> 2 * (x - y)
|
|
|
|
(d) (2 / x) / (3 / y) ---> (2 / 3) / (x * y)
|
|
|
|
(e) (2 * x) * (3 * y) ---> (2 * 3) * (x * y)
|
|
|
|
|
|
|
|
Note:
|
|
|
|
When using strength reduction in conjunction with expressions whose
|
|
|
|
inputs or sub-expressions may result in values nearing either of the
|
|
|
|
bounds of the underlying numeric type (eg: double), there may be the
|
|
|
|
possibility of a decrease in the precision of results.
|
|
|
|
|
|
|
|
In the following example the given expression which represents an
|
|
|
|
attempt at computing the average between x and y will be transformed
|
|
|
|
as follows:
|
|
|
|
|
|
|
|
(x * 0.5) + (y * 0.5) ---> 0.5 * (x + y)
|
|
|
|
|
|
|
|
There may be situations where the above transformation will cause
|
|
|
|
numerical overflows and that the original form of the expression is
|
|
|
|
desired over the strength reduced form. In these situations it is best
|
|
|
|
to turn off strength reduction optimisations or to use a type with a
|
|
|
|
larger numerical bound.
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
[12 - SPECIAL FUNCTIONS]
|
2013-03-26 14:35:51 +00:00
|
|
|
The purpose of special functions in ExprTk is to provide compiler
|
|
|
|
generated equivalents of common mathematical expressions which can be
|
|
|
|
invoked by using the 'special function' syntax (eg: $f12(x,y,z) or
|
2013-07-08 22:32:08 +00:00
|
|
|
$f82(x,y,z,w)).
|
2012-05-11 22:18:14 +00:00
|
|
|
|
|
|
|
Special functions dramatically decrease the total evaluation time of
|
|
|
|
expressions which would otherwise have been written using the common
|
|
|
|
form by reducing the total number of nodes in the evaluation tree of
|
|
|
|
an expression and by also leveraging the compiler's ability to
|
|
|
|
correctly optimize such expressions for a given architecture.
|
|
|
|
|
2013-03-04 13:21:28 +00:00
|
|
|
3-Parameter 4-Parameter
|
|
|
|
+-------------+-------------+ +--------------+------------------+
|
|
|
|
| Prototype | Operation | | Prototype | Operation |
|
|
|
|
+-------------+-------------+ +--------------+------------------+
|
2014-01-21 21:13:37 +00:00
|
|
|
$f00(x,y,z) | (x + y) / z $f48(x,y,z,w) | x + ((y + z) / w)
|
|
|
|
$f01(x,y,z) | (x + y) * z $f49(x,y,z,w) | x + ((y + z) * w)
|
|
|
|
$f02(x,y,z) | (x + y) - z $f50(x,y,z,w) | x + ((y - z) / w)
|
|
|
|
$f03(x,y,z) | (x + y) + z $f51(x,y,z,w) | x + ((y - z) * w)
|
|
|
|
$f04(x,y,z) | (x - y) + z $f52(x,y,z,w) | x + ((y * z) / w)
|
|
|
|
$f05(x,y,z) | (x - y) / z $f53(x,y,z,w) | x + ((y * z) * w)
|
|
|
|
$f06(x,y,z) | (x - y) * z $f54(x,y,z,w) | x + ((y / z) + w)
|
|
|
|
$f07(x,y,z) | (x * y) + z $f55(x,y,z,w) | x + ((y / z) / w)
|
|
|
|
$f08(x,y,z) | (x * y) - z $f56(x,y,z,w) | x + ((y / z) * w)
|
|
|
|
$f09(x,y,z) | (x * y) / z $f57(x,y,z,w) | x - ((y + z) / w)
|
|
|
|
$f10(x,y,z) | (x * y) * z $f58(x,y,z,w) | x - ((y + z) * w)
|
|
|
|
$f11(x,y,z) | (x / y) + z $f59(x,y,z,w) | x - ((y - z) / w)
|
|
|
|
$f12(x,y,z) | (x / y) - z $f60(x,y,z,w) | x - ((y - z) * w)
|
|
|
|
$f13(x,y,z) | (x / y) / z $f61(x,y,z,w) | x - ((y * z) / w)
|
|
|
|
$f14(x,y,z) | (x / y) * z $f62(x,y,z,w) | x - ((y * z) * w)
|
|
|
|
$f15(x,y,z) | x / (y + z) $f63(x,y,z,w) | x - ((y / z) / w)
|
|
|
|
$f16(x,y,z) | x / (y - z) $f64(x,y,z,w) | x - ((y / z) * w)
|
|
|
|
$f17(x,y,z) | x / (y * z) $f65(x,y,z,w) | ((x + y) * z) - w
|
|
|
|
$f18(x,y,z) | x / (y / z) $f66(x,y,z,w) | ((x - y) * z) - w
|
|
|
|
$f19(x,y,z) | x * (y + z) $f67(x,y,z,w) | ((x * y) * z) - w
|
|
|
|
$f20(x,y,z) | x * (y - z) $f68(x,y,z,w) | ((x / y) * z) - w
|
|
|
|
$f21(x,y,z) | x * (y * z) $f69(x,y,z,w) | ((x + y) / z) - w
|
|
|
|
$f22(x,y,z) | x * (y / z) $f70(x,y,z,w) | ((x - y) / z) - w
|
|
|
|
$f23(x,y,z) | x - (y + z) $f71(x,y,z,w) | ((x * y) / z) - w
|
|
|
|
$f24(x,y,z) | x - (y - z) $f72(x,y,z,w) | ((x / y) / z) - w
|
|
|
|
$f25(x,y,z) | x - (y / z) $f73(x,y,z,w) | (x * y) + (z * w)
|
|
|
|
$f26(x,y,z) | x - (y * z) $f74(x,y,z,w) | (x * y) - (z * w)
|
|
|
|
$f27(x,y,z) | x + (y * z) $f75(x,y,z,w) | (x * y) + (z / w)
|
|
|
|
$f28(x,y,z) | x + (y / z) $f76(x,y,z,w) | (x * y) - (z / w)
|
|
|
|
$f29(x,y,z) | x + (y + z) $f77(x,y,z,w) | (x / y) + (z / w)
|
|
|
|
$f30(x,y,z) | x + (y - z) $f78(x,y,z,w) | (x / y) - (z / w)
|
|
|
|
$f31(x,y,z) | x * y^2 + z $f79(x,y,z,w) | (x / y) - (z * w)
|
|
|
|
$f32(x,y,z) | x * y^3 + z $f80(x,y,z,w) | x / (y + (z * w))
|
|
|
|
$f33(x,y,z) | x * y^4 + z $f81(x,y,z,w) | x / (y - (z * w))
|
|
|
|
$f34(x,y,z) | x * y^5 + z $f82(x,y,z,w) | x * (y + (z * w))
|
|
|
|
$f35(x,y,z) | x * y^6 + z $f83(x,y,z,w) | x * (y - (z * w))
|
|
|
|
$f36(x,y,z) | x * y^7 + z $f84(x,y,z,w) | x*y^2 + z*w^2
|
|
|
|
$f37(x,y,z) | x * y^8 + z $f85(x,y,z,w) | x*y^3 + z*w^3
|
|
|
|
$f38(x,y,z) | x * y^9 + z $f86(x,y,z,w) | x*y^4 + z*w^4
|
|
|
|
$f39(x,y,z) | x * log(y)+z $f87(x,y,z,w) | x*y^5 + z*w^5
|
|
|
|
$f40(x,y,z) | x * log(y)-z $f88(x,y,z,w) | x*y^6 + z*w^6
|
|
|
|
$f41(x,y,z) | x * log10(y)+z $f89(x,y,z,w) | x*y^7 + z*w^7
|
|
|
|
$f42(x,y,z) | x * log10(y)-z $f90(x,y,z,w) | x*y^8 + z*w^8
|
|
|
|
$f43(x,y,z) | x * sin(y)+z $f91(x,y,z,w) | x*y^9 + z*w^9
|
|
|
|
$f44(x,y,z) | x * sin(y)-z $f92(x,y,z,w) | (x and y) ? z : w
|
|
|
|
$f45(x,y,z) | x * cos(y)+z $f93(x,y,z,w) | (x or y) ? z : w
|
|
|
|
$f46(x,y,z) | x * cos(y)-z $f94(x,y,z,w) | (x < y) ? z : w
|
|
|
|
$f47(x,y,z) | x ? y : z $f95(x,y,z,w) | (x <= y) ? z : w
|
|
|
|
$f96(x,y,z,w) | (x > y) ? z : w
|
|
|
|
$f97(x,y,z,w) | (x >= y) ? z : w
|
|
|
|
$f98(x,y,z,w) | (x == y) ? z : w
|
2014-02-09 09:20:15 +00:00
|
|
|
$f99(x,y,z,w) | x*sin(y)+z*cos(w)
|
2012-05-16 22:14:45 +00:00
|
|
|
|
|
|
|
|
2012-05-01 12:43:33 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
[13 - VARIABLE & VECTOR DEFINITION]
|
2014-05-27 21:10:40 +00:00
|
|
|
ExprTk supports the definition of expression local variables and
|
|
|
|
vectors. The definitions must be unique as shadowing is not allowed
|
|
|
|
and object life-times are based on scope. Definitions use the
|
|
|
|
following general form:
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
var <name> := <initialiser>;
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
(1) Variable Definition
|
|
|
|
Variables are of numeric type denoting a single value. They can be
|
|
|
|
explicitly initialised to a value, otherwise they will be defaulted to
|
|
|
|
zero. The following are examples of variable definitions:
|
|
|
|
|
|
|
|
(a) Initialise x to zero
|
|
|
|
var x;
|
|
|
|
|
|
|
|
(b) Initialise y to three
|
|
|
|
var y := 3;
|
|
|
|
|
|
|
|
(c) Initialise z to the expression
|
|
|
|
var z := if(max(1,x + y) > 2,w,v);
|
|
|
|
|
|
|
|
|
|
|
|
(2) Vector Definition
|
|
|
|
Vectors are arrays of a common numeric type. The elements in a vector
|
|
|
|
can be explicitly initialised, otherwise they will all be defaulted to
|
|
|
|
zero. The following are examples of vector definitions:
|
|
|
|
|
|
|
|
(a) Initialise all values to zero
|
|
|
|
var x[3];
|
|
|
|
|
|
|
|
(b) Initialise all values to zero
|
|
|
|
var x[3] := {};
|
|
|
|
|
|
|
|
(c) Initialise all values to given expression
|
|
|
|
var x[3] := [123 + 3y + sin(w/z)];
|
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
(d) Initialise the first two values, all other elements to zero
|
2014-11-17 11:03:10 +00:00
|
|
|
var x[3] := { 1 + x[2], sin(y[0] / x[]) + 3 };
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
(e) Initialise the first three (all) values
|
2014-11-17 11:03:10 +00:00
|
|
|
var x[3] := { 1, 2, 3 };
|
2014-05-27 21:10:40 +00:00
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
(f) Error as there are too many initialisers
|
|
|
|
var x[3] := { 1, 2, 3, 4 };
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
(g) Error as a vector of size zero is not allowed.
|
|
|
|
var x[0];
|
|
|
|
|
|
|
|
|
|
|
|
(3) Return Value
|
|
|
|
Variable and vector definitions have a return value. In the case of
|
2014-11-17 11:03:10 +00:00
|
|
|
variable definitions, the value to which the variable is initialised
|
2014-05-27 21:10:40 +00:00
|
|
|
will be returned. Where as for vectors, the value of the first element
|
|
|
|
(eg: v[0]) will be returned.
|
|
|
|
|
|
|
|
|
2014-10-14 11:06:52 +00:00
|
|
|
(4) Variable/Vector Assignment
|
|
|
|
The value of a variable can be assigned to a vector and a vector or a
|
|
|
|
vector expression can be assigned to a variable.
|
|
|
|
|
|
|
|
(a) Variable To Vector:
|
|
|
|
Every element of the vector is assigned the value of the variable
|
|
|
|
or expression.
|
|
|
|
var x := 3;
|
2014-11-17 11:03:10 +00:00
|
|
|
var y[3] := { 1, 2, 3 };
|
2014-10-14 11:06:52 +00:00
|
|
|
y := x + 1;
|
|
|
|
|
|
|
|
(b) Vector To Variable:
|
|
|
|
The variable is assigned the value of the first element of the
|
|
|
|
vector (aka vec[0])
|
|
|
|
var x := 3;
|
2014-11-17 11:03:10 +00:00
|
|
|
var y[3] := { 1, 2, 3 };
|
2014-10-14 11:06:52 +00:00
|
|
|
x := y + 1;
|
|
|
|
|
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
[14 - VECTOR PROCESSING]
|
2014-06-08 09:24:53 +00:00
|
|
|
ExprTk provides support for various forms of vector oriented
|
|
|
|
arithmetic, inequalities and processing. The various supported pairs
|
|
|
|
are as follows:
|
|
|
|
|
|
|
|
(a) vector and vector (eg: v0 + v1)
|
|
|
|
(b) vector and scalar (eg: v + 33)
|
|
|
|
(c) scalar and vector (eg: 22 * v)
|
|
|
|
|
|
|
|
The following is a list of operations that can be used in conjunction
|
|
|
|
with vectors:
|
|
|
|
|
|
|
|
(a) Arithmetic: +, -, *, /, %
|
|
|
|
(b) Exponentiation: vector ^ scalar
|
2014-10-14 11:06:52 +00:00
|
|
|
(c) Assignment: :=, +=, -=, *=, /=, %=, <=>
|
2014-06-08 09:24:53 +00:00
|
|
|
(d) Inequalities: <, <=, >, >=, ==, =
|
|
|
|
(e) Unary operations:
|
2014-12-22 11:00:49 +00:00
|
|
|
abs, acos, acosh, asin, asinh, atan, atanh, ceil, cos, cosh,
|
|
|
|
cot, csc, deg2grad, deg2rad, erf, erfc, exp, expm1, floor,
|
2014-10-14 11:06:52 +00:00
|
|
|
frac, grad2deg, log, log10, log1p, log2, rad2deg, round, sec,
|
|
|
|
sgn, sin, sinc, sinh, sqrt, swap, tan, tanh, trunc
|
|
|
|
(f) Aggregate and Reduce operations:
|
|
|
|
avg, max, min, mul, sum
|
2014-06-08 09:24:53 +00:00
|
|
|
|
|
|
|
Note: When one of the above described operations is being performed
|
|
|
|
between two vectors, the operation will only span the size of the
|
|
|
|
smallest vector. The elements of the larger vector outside of the
|
|
|
|
range will not be included.
|
|
|
|
|
|
|
|
The following simple example demonstrates the vector processing
|
|
|
|
capabilities by computing the dot-product of the vectors v0 and v1 and
|
|
|
|
then assigning it to the variable v0dotv1:
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
var v0[3] := { 1, 2, 3 };
|
|
|
|
var v1[3] := { 4, 5, 6 };
|
2014-06-08 09:24:53 +00:00
|
|
|
var v0dotv1 := sum(v0 * v1);
|
|
|
|
|
|
|
|
|
|
|
|
The following is a for-loop based implementation that is equivalent to
|
|
|
|
the previously mentioned dot-product computation expression:
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
var v0[3] := { 1, 2, 3 };
|
|
|
|
var v1[3] := { 4, 5, 6 };
|
2014-06-08 09:24:53 +00:00
|
|
|
var v0dotv1;
|
|
|
|
|
2014-07-01 10:46:51 +00:00
|
|
|
for (var i := 0; i < min(v0[],v1[]); i += 1)
|
2014-06-08 09:24:53 +00:00
|
|
|
{
|
|
|
|
v0dotv1 += (v0[i] * v1[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-14 11:06:52 +00:00
|
|
|
Note: In the scenario of inequalities between two vectors, the result
|
|
|
|
is not a vector but rather a singular variable denoting a boolean
|
|
|
|
state of either 'true' or 'false' depending on the nature of the
|
|
|
|
inequality.
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
var x[3] := { 1, 1, 1 };
|
|
|
|
var y[3] := { 3, 2, 1 };
|
2014-10-14 11:06:52 +00:00
|
|
|
|
|
|
|
y > x == false
|
|
|
|
|
|
|
|
|
|
|
|
Note: When the aggregate operations denoted above are used in
|
|
|
|
conjunction with a vector or vector expression, the return value is
|
|
|
|
not a vector but rather a single value.
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
var x[3] := { 1, 2, 3 };
|
2014-10-14 11:06:52 +00:00
|
|
|
|
|
|
|
sum(1 + 2x) == 15
|
2014-11-17 11:03:10 +00:00
|
|
|
avg(3x + 1) == 7
|
|
|
|
min(1 / x) == (1 / 3)
|
|
|
|
max(x / 2) == (3 / 2)
|
2014-10-14 11:06:52 +00:00
|
|
|
|
|
|
|
|
2014-06-08 09:24:53 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
[15 - USER DEFINED FUNCTIONS]
|
2014-05-27 21:10:40 +00:00
|
|
|
ExprTk provides a means whereby custom functions can be defined and
|
|
|
|
utilized within expressions. The concept requires the user to
|
|
|
|
provide a reference to the function coupled with an associated name
|
|
|
|
that will be invoked within expressions. Function can take in numerous
|
2014-12-01 17:48:39 +00:00
|
|
|
inputs but will always return a single value of the underlying numeric
|
|
|
|
type.
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
During expression compilation when required the reference to the
|
|
|
|
function will be obtained from the associated symbol_table and be
|
|
|
|
embedded into the expression.
|
|
|
|
|
|
|
|
There are two types of function interface:
|
|
|
|
|
|
|
|
(1) ifunction
|
|
|
|
(2) ivararg_function
|
2014-11-30 09:48:19 +00:00
|
|
|
(3) igeneric_function
|
2014-12-07 19:33:10 +00:00
|
|
|
(4) igeneric_function II
|
|
|
|
(5) function_compositor
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
(1) ifunction
|
|
|
|
This interface supports zero to 20 input parameters. The usage
|
|
|
|
requires a custom function be derived from ifunction and to override
|
|
|
|
one of the 21 function operators. As part of the constructor the
|
|
|
|
custom function will define how many parameters it expects to handle.
|
|
|
|
The following example defines a 3 parameter function called 'foo':
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct foo : public exprtk::ifunction<T>
|
|
|
|
{
|
|
|
|
foo() : exprtk::ifunction<T>(3)
|
|
|
|
{}
|
|
|
|
|
|
|
|
T operator()(const T& v1, const T& v2, const T& v3)
|
|
|
|
{
|
|
|
|
return T(1) + (v1 * v2) / T(v3);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
(2) ivararg_function
|
|
|
|
This interface supports a variable number of arguments as input into
|
|
|
|
the function. The function operator interface uses a std::vector
|
|
|
|
specialized upon type T to facilitate parameter passing. The following
|
|
|
|
example defines a vararg function called 'boo':
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct boo : public exprtk::ivararg_function<T>
|
|
|
|
{
|
|
|
|
inline T operator()(const std::vector<T>& arglist)
|
|
|
|
{
|
|
|
|
T result = T(0);
|
2014-11-17 11:03:10 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
for (std::size_t i = 0; i < arglist.size(); ++i)
|
|
|
|
{
|
|
|
|
result += arglist[i] / arglist[i > 0 ? (i - 1) : 0];
|
|
|
|
}
|
2014-11-17 11:03:10 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(3) igeneric_function
|
|
|
|
This interface supports a variable number of arguments and types as
|
|
|
|
input into the function. The function operator interface uses a
|
|
|
|
std::vector specialized upon the type_store type to facilitate
|
|
|
|
parameter passing.
|
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
Scalar <-- function(i_0, i_1, i_2....., i_N)
|
|
|
|
|
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
The fundamental types that can be passed into the function as
|
|
|
|
parameters and their views are as follows:
|
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(1) Scalar - scalar_view
|
|
|
|
(2) Vector - vector_view
|
|
|
|
(3) String - string_view
|
2014-11-30 09:48:19 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
The above denoted type views provide non-const reference-like access
|
|
|
|
to each parameter, as such modifications made to the input parameters
|
|
|
|
will persist after the function call has completed. The following
|
|
|
|
example defines a generic function called 'too':
|
2014-11-30 09:48:19 +00:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct too : public exprtk::igeneric_function<T>
|
|
|
|
{
|
|
|
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
|
|
|
parameter_list_t;
|
|
|
|
|
|
|
|
too()
|
|
|
|
{}
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
inline T operator()(parameter_list_t parameters)
|
2014-11-30 09:48:19 +00:00
|
|
|
{
|
|
|
|
for (std::size_t i = 0; i < parameters.size(); ++i)
|
|
|
|
{
|
2014-12-01 17:48:39 +00:00
|
|
|
...
|
2014-11-30 09:48:19 +00:00
|
|
|
}
|
|
|
|
return T(0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
In the above example, the input 'parameters' to the function operator,
|
|
|
|
parameter_list_t, is a type of std::vector of type_store. Each
|
|
|
|
type_store instance has a member called 'type' which holds the
|
|
|
|
enumeration pertaining the underlying type of the type_store. There
|
|
|
|
are three type enumerations:
|
2014-11-30 09:48:19 +00:00
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
(1) e_scalar - literals, variables, vector elements, expressions
|
|
|
|
eg: 123.456, x, vec[3x + 1], 2x + 3
|
2014-11-30 09:48:19 +00:00
|
|
|
|
|
|
|
(2) e_vector - vectors, vector expressions
|
|
|
|
eg: vec1, 2 * vec1 + vec2 / 3
|
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
(3) e_string - strings, string literals and range variants of both
|
2014-12-10 15:59:06 +00:00
|
|
|
eg: 'AString', s0, 'AString'[x:y], s1[1 + x:] + 'AString'
|
2014-12-01 17:48:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
Each of the parameters can be accessed using its designated view. A
|
|
|
|
typical loop for processing the parameters is as follows:
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
inline T operator()(parameter_list_t parameters)
|
2014-12-01 17:48:39 +00:00
|
|
|
{
|
|
|
|
typedef typename exprtk::igeneric_function<T>::generic_type
|
|
|
|
generic_type;
|
|
|
|
|
|
|
|
typedef typename generic_type::scalar_view scalar_t;
|
|
|
|
typedef typename generic_type::vector_view vector_t;
|
|
|
|
typedef typename generic_type::string_view string_t;
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < parameters.size(); ++i)
|
|
|
|
{
|
|
|
|
generic_type& gt = parameters[i];
|
|
|
|
|
|
|
|
if (generic_type::e_scalar == gt.type)
|
|
|
|
{
|
|
|
|
scalar_t x(gt);
|
|
|
|
...
|
|
|
|
}
|
|
|
|
else if (generic_type::e_vector == gt.type)
|
|
|
|
{
|
|
|
|
vector_t vector(gt);
|
|
|
|
...
|
|
|
|
}
|
|
|
|
else if (generic_type::e_string == gt.type)
|
|
|
|
{
|
|
|
|
string_t string(gt);
|
|
|
|
...
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return T(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Most often than not a custom generic function will require a specific
|
|
|
|
sequence of parameters, rather than some arbitrary sequence of types.
|
|
|
|
In those situations, ExprTk can perform compile-time type checking to
|
|
|
|
validate that function invocations are carried out using the correct
|
|
|
|
sequence of parameters. Furthermore performing the checks at compile
|
|
|
|
-time rather than at run-time (aka every time the function is invoked)
|
2014-12-01 18:07:42 +00:00
|
|
|
will result in expression evaluation performance gains.
|
2014-12-01 17:48:39 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
Compile-time type checking of input parameters can be requested by
|
|
|
|
passing a string to the constructor of the igeneric_function that
|
|
|
|
represents the required sequence of parameter types. When no parameter
|
|
|
|
sequence is provided, it is implied the function can accept a variable
|
2014-12-14 06:38:05 +00:00
|
|
|
number of parameters comprised of any of the fundamental types.
|
2014-12-01 17:48:39 +00:00
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
Each fundamental type has an associated character. The following is a
|
|
|
|
listing of said characters and their meanings:
|
2014-12-01 17:48:39 +00:00
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
(1) T - Scalar
|
|
|
|
(2) V - Vector
|
|
|
|
(3) S - String
|
|
|
|
(4) ? - Any type (Scalar, Vector or String)
|
|
|
|
(5) * - Wildcard operator
|
|
|
|
(6) | - Parameter sequence delimiter
|
2014-12-01 17:48:39 +00:00
|
|
|
|
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
No other characters other than the six denoted above may be included
|
|
|
|
in the parameter sequence definition. If any such invalid characters
|
|
|
|
do exist, registration of the associated generic function to a symbol
|
|
|
|
table ('add_function' method) will fail. If the parameter sequence is
|
|
|
|
modified resulting in it becoming invalid after having been added to
|
|
|
|
the symbol table but before the compilation step, a compilation error
|
|
|
|
will be incurred.
|
2014-12-01 17:48:39 +00:00
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
The following example demonstrates a simple generic function
|
|
|
|
implementation with a user specified parameter sequence:
|
2014-12-01 17:48:39 +00:00
|
|
|
|
|
|
|
template <typename T>
|
2014-12-14 06:38:05 +00:00
|
|
|
struct moo : public exprtk::igeneric_function<T>
|
2014-12-01 17:48:39 +00:00
|
|
|
{
|
|
|
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
|
|
|
parameter_list_t;
|
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
moo()
|
|
|
|
: exprtk::igeneric_function<T>("SVTT")
|
2014-12-01 17:48:39 +00:00
|
|
|
{}
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
inline T operator()(parameter_list_t parameters)
|
2014-12-01 17:48:39 +00:00
|
|
|
{
|
|
|
|
...
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
In the example above the generic function 'moo' expects exactly four
|
2014-12-01 17:48:39 +00:00
|
|
|
parameters in the following sequence:
|
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
(1) String
|
|
|
|
(2) Vector
|
|
|
|
(3) Scalar
|
|
|
|
(4) Scalar
|
2014-11-30 09:48:19 +00:00
|
|
|
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
(4) igeneric_function II
|
|
|
|
This interface is identical to the igeneric_function, in that in can
|
|
|
|
consume an arbitrary number of parameters of varying type, but the
|
|
|
|
difference being that the function returns a string and as such is
|
|
|
|
treated as a string when invoked within expressions. As a result the
|
|
|
|
function call can alias a string and interact with other strings in
|
|
|
|
situations such as concatenation and equality operations.
|
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
String <-- function(i_0, i_1, i_2....., i_N)
|
|
|
|
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
The following example defines an generic function named 'toupper' with
|
2014-12-14 06:38:05 +00:00
|
|
|
the string return type function operator being explicitly overridden:
|
2014-12-07 19:33:10 +00:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct toupper : public exprtk::igeneric_function<T>
|
|
|
|
{
|
|
|
|
typedef exprtk::igeneric_function<T> igenfunct_t
|
|
|
|
typedef typename igenfunct_t::generic_type generic_t;
|
|
|
|
typedef typename igenfunct_t::parameter_list_t parameter_list_t;
|
|
|
|
typedef typename generic_t::string_view string_t;
|
|
|
|
|
|
|
|
toupper()
|
|
|
|
: exprtk::igeneric_function<T>("S")
|
|
|
|
{}
|
|
|
|
|
|
|
|
inline T operator()(std::string& result,
|
|
|
|
parameter_list_t parameters)
|
|
|
|
{
|
|
|
|
result.clear();
|
|
|
|
for (std::size_t i = 0; i < string.size(); ++i)
|
|
|
|
{
|
|
|
|
result += std::toupper(string[i]);
|
|
|
|
}
|
|
|
|
return T(0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
In the example above the generic function 'toupper' expects only one
|
2014-12-14 06:38:05 +00:00
|
|
|
input parameter of type string, as noted by the parameter sequence
|
2014-12-07 19:33:10 +00:00
|
|
|
string passed during the constructor. When executed, the function will
|
|
|
|
return as a result a copy of the input string converted to uppercase
|
2014-12-14 06:38:05 +00:00
|
|
|
form. An example expression using the toupper function registered as
|
|
|
|
the symbol 'toupper' is as follows:
|
|
|
|
|
|
|
|
"'ABCDEF' == toupper('aBc') + toupper('DeF')"
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
Note: When adding a string type returning generic function to a symbol
|
2014-12-07 19:33:10 +00:00
|
|
|
table, the 'add_function' is invoked with an extra parameter
|
|
|
|
(e_ft_strfunc) that denotes the function should be treated as a string
|
|
|
|
returning function type. The following example demonstrates how this
|
|
|
|
is done:
|
|
|
|
|
|
|
|
toupper<T> tu;
|
|
|
|
|
|
|
|
exprtk::symbol_table<T> symbol_table;
|
|
|
|
|
|
|
|
symbol_table.add_function("toupper",
|
|
|
|
tu,
|
|
|
|
symbol_table_t::e_ft_strfunc);
|
|
|
|
|
|
|
|
|
2014-12-14 06:38:05 +00:00
|
|
|
Note: There are two further refinements to the type checking facility
|
|
|
|
are the possibilities of a variable number of common types which can
|
|
|
|
be accomplished by using a wildcard '*' and a special 'any type' which
|
|
|
|
is done using the '?' character. It should be noted that the wildcard
|
|
|
|
operator is associated with the previous type in the sequence and
|
|
|
|
implies one or more of that type.
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct zoo : public exprtk::igeneric_function<T>
|
|
|
|
{
|
|
|
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
|
|
|
parameter_list_t;
|
|
|
|
|
|
|
|
zoo()
|
|
|
|
: exprtk::igeneric_function<T>("SVT*V?")
|
|
|
|
{}
|
|
|
|
|
|
|
|
inline T operator()(parameter_list_t parameters)
|
|
|
|
{
|
|
|
|
...
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
In the example above the generic function 'zoo' expects at least five
|
|
|
|
parameters in the following sequence:
|
|
|
|
|
|
|
|
(1) String
|
|
|
|
(2) Vector
|
|
|
|
(3) One or more Scalars
|
|
|
|
(4) Vector
|
|
|
|
(5) Any type (one type of either a scalar, vector or string)
|
|
|
|
|
|
|
|
|
|
|
|
A final piece of type checking functionality is available for the
|
2014-12-22 11:00:49 +00:00
|
|
|
scenarios where a single function name is intended to be used for
|
2014-12-25 19:31:45 +00:00
|
|
|
multiple distinct parameter sequences, another name for this feature
|
|
|
|
is function overloading. The parameter sequences are passed to the
|
|
|
|
constructor as a single string delimited by the pipe '|' character.
|
|
|
|
Two specific overrides of the function operator are provided one for
|
|
|
|
standard generic functions and one for string returning functions. The
|
|
|
|
overrides are as follows:
|
2014-12-14 06:38:05 +00:00
|
|
|
|
|
|
|
// f(psi,i_0,i_1,....,i_N) --> Scalar
|
|
|
|
inline T operator()(const std::size_t& ps_index,
|
|
|
|
parameter_list_t parameters)
|
|
|
|
{
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
// f(psi,i_0,i_1,....,i_N) --> String
|
|
|
|
inline T operator()(const std::size_t& ps_index,
|
|
|
|
std::string& result,
|
|
|
|
parameter_list_t parameters)
|
|
|
|
{
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
When the function operator is invoked the 'ps_index' parameter will
|
|
|
|
have as its value the index of the parameter sequence that matches the
|
|
|
|
specific invocation. This way complex and time consuming type checking
|
|
|
|
conditions need not be executed in the function itself but rather a
|
|
|
|
simple and efficient dispatch to a specific implementation for that
|
|
|
|
particular parameter sequence can be performed.
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct roo : public exprtk::igeneric_function<T>
|
|
|
|
{
|
|
|
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
|
|
|
parameter_list_t;
|
|
|
|
|
|
|
|
moo()
|
|
|
|
: exprtk::igeneric_function<T>("SVTT|SS|TTV|S?V*S")
|
|
|
|
{}
|
|
|
|
|
2014-12-17 16:55:45 +00:00
|
|
|
inline T operator()(const std::size_t& ps_index,
|
|
|
|
parameter_list_t parameters)
|
2014-12-14 06:38:05 +00:00
|
|
|
{
|
|
|
|
...
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
In the above example there are four distinct parameter sequences that
|
|
|
|
can be processed by the generic function 'roo'. Any other parameter
|
2014-12-16 11:50:10 +00:00
|
|
|
sequences will cause a compilation error. The four valid sequences are
|
2014-12-14 06:38:05 +00:00
|
|
|
as follows:
|
|
|
|
|
2014-12-16 11:50:10 +00:00
|
|
|
Sequence-0 Sequence-1 Sequence-2 Sequence-3
|
|
|
|
'SVTT' 'SS' 'TTV' 'S?V*S'
|
|
|
|
(1) String (1) String (1) Scalar (1) String
|
|
|
|
(2) Vector (2) String (2) Scalar (2) Any Type
|
|
|
|
(3) Scalar (3) Vector (3) One or more Vectors
|
|
|
|
(4) Scalar (4) String
|
2014-12-14 06:38:05 +00:00
|
|
|
|
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
(5) function_compositor
|
2014-11-17 11:03:10 +00:00
|
|
|
The function compositor interface allows a user to define a function
|
|
|
|
using ExprTk syntax. The functions are limited to returning a single
|
|
|
|
scalar value and consuming up to six parameters as input.
|
2014-05-27 21:10:40 +00:00
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
All composited functions are registered with a symbol table, allowing
|
|
|
|
them to call other functions that have been registered with the symbol
|
|
|
|
table instance, furthermore the functions can be recursive in nature.
|
|
|
|
The following example defines, using two different methods, composited
|
|
|
|
functions then implicitly registers the functions with the denoted
|
|
|
|
symbol table.
|
|
|
|
|
|
|
|
typedef exprtk::symbol_table<T> symbol_table_t;
|
|
|
|
typedef exprtk::function_compositor<T> compositor_t;
|
|
|
|
typedef typename compositor_t::function function_t;
|
|
|
|
|
|
|
|
symbol_table_t symbol_table;
|
|
|
|
|
|
|
|
compositor_t compositor(symbol_table);
|
|
|
|
|
|
|
|
// define function koo0(v1,v2) { ... }
|
|
|
|
compositor
|
|
|
|
.add("koo0",
|
|
|
|
" 1 + cos(v1 * v2) / 3;",
|
|
|
|
"v1","v2");
|
|
|
|
|
|
|
|
// define function koo1(x,y,z) { ... }
|
|
|
|
compositor
|
|
|
|
.add(function_t()
|
|
|
|
.name("koo1")
|
|
|
|
.var("x").var("y").var("z")
|
|
|
|
.expression("1 + cos(x * y) / z;"));
|
|
|
|
|
|
|
|
|
|
|
|
(4) Using Functions In Expressions
|
|
|
|
For the above denoted custom and composited functions to be used in an
|
|
|
|
expression, an instance of each function needs to be registered with a
|
|
|
|
symbol_table that has been associated with the expression instance.
|
|
|
|
The following demonstrates how all the pieces are put together:
|
|
|
|
|
|
|
|
typedef exprtk::symbol_table<double> symbol_table_t;
|
|
|
|
typedef exprtk::expression<double> expression_t;
|
|
|
|
typedef exprtk::parser<double> parser_t;
|
|
|
|
typedef exprtk::function_compositor<T> compositor_t;
|
|
|
|
typedef typename compositor_t::function function_t;
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
foo<double> f;
|
|
|
|
boo<double> b;
|
2014-12-01 17:48:39 +00:00
|
|
|
too<double> t;
|
2014-12-07 19:33:10 +00:00
|
|
|
toupper<double> tu;
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
symbol_table_t symbol_table;
|
2014-12-01 17:48:39 +00:00
|
|
|
compositor_t compositor(symbol_table);
|
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
symbol_table.add_function("foo",f);
|
2014-11-30 09:48:19 +00:00
|
|
|
symbol_table.add_function("boo",b);
|
2014-12-01 17:48:39 +00:00
|
|
|
symbol_table.add_function("too",t);
|
2014-05-27 21:10:40 +00:00
|
|
|
|
2014-12-07 19:33:10 +00:00
|
|
|
symbol_table.add_function("toupper",
|
|
|
|
tu,
|
|
|
|
symbol_table_t::e_ft_strfunc);
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
compositor
|
|
|
|
.add(function_t()
|
|
|
|
.name("koo")
|
|
|
|
.var("v1")
|
|
|
|
.var("v2")
|
|
|
|
.expression("1 + cos(v1 * v2) / 3;"));
|
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
expression_t expression;
|
|
|
|
expression.register_symbol_table(symbol_table);
|
|
|
|
|
|
|
|
std::string expression_str =
|
2014-12-01 17:48:39 +00:00
|
|
|
" if (foo(1,2,3) + boo(1) > boo(1/2,2/3,3/4,4/5)) "
|
|
|
|
" koo(3,4); "
|
|
|
|
" else "
|
|
|
|
" too(2 * v1 + v2 / 3, 'abcdef'[2:4], 3.3); "
|
|
|
|
" ";
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
parser_t parser;
|
|
|
|
parser.compile(expression_str,expression);
|
|
|
|
|
|
|
|
expression.value();
|
|
|
|
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
(5) Function Side-Effects
|
2014-10-14 11:06:52 +00:00
|
|
|
All function calls are assumed to have side-effects by default. This
|
|
|
|
assumption implicitly disables constant folding optimisations when all
|
|
|
|
parameters being passed to the function are deduced as being constants
|
|
|
|
at compile time.
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
If it is certain that the function being registered does not have any
|
|
|
|
side effects and can be correctly constant folded where appropriate,
|
|
|
|
then during the construction of the function a 'false' can be passed
|
|
|
|
to the constructor to denote the lack of side-effects.
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct foo : public exprtk::ifunction<T>
|
|
|
|
{
|
|
|
|
foo() : exprtk::ifunction<T>(3,false)
|
|
|
|
{}
|
|
|
|
|
|
|
|
T operator()(const T& v1, const T& v2, const T& v3)
|
|
|
|
{ ... }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-11-17 11:03:10 +00:00
|
|
|
(6) Zero Parameter Functions
|
2014-06-19 12:22:44 +00:00
|
|
|
When either an ifunction or ivararg_function derived type is defined
|
|
|
|
with zero number of parameters, there are two calling conventions
|
|
|
|
within expressions that are allowed. For a function named 'foo' with
|
|
|
|
zero input parameters the calling styles are as follows:
|
2014-05-27 21:10:40 +00:00
|
|
|
|
|
|
|
(1) x + sin(foo()- 2) / y
|
|
|
|
(2) x + sin(foo - 2) / y
|
|
|
|
|
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[16 - EXPRESSION DEPENDENTS]
|
|
|
|
Any expression that is not a literal (aka constant) will have
|
|
|
|
dependencies. The types of 'dependencies' an expression can have are
|
|
|
|
as follows:
|
|
|
|
|
|
|
|
(a) Variables
|
|
|
|
(b) Vectors
|
|
|
|
(c) Strings
|
|
|
|
(d) Functions
|
|
|
|
(e) Assignments
|
|
|
|
|
|
|
|
|
|
|
|
In the following example the denoted expression has its various
|
|
|
|
dependencies listed:
|
|
|
|
|
|
|
|
z := abs(x + sin(2 * pi / y))
|
|
|
|
|
|
|
|
(a) Variables: x, y, z and pi
|
|
|
|
(b) Functions: abs, sin
|
|
|
|
(c) Assignments: z
|
|
|
|
|
|
|
|
|
|
|
|
ExprTk allows for the derivation of expression dependencies via the
|
|
|
|
'dependent_entity_collector' (DEC). When activated either through
|
|
|
|
'compile_options' at the construction of the parser or through calls
|
|
|
|
to enabler methods just prior to compilation, the DEC will proceed to
|
|
|
|
collect any of the relevant types that are encountered during the
|
|
|
|
parsing phase. Once the compilation process has successfully
|
|
|
|
completed, the caller can then obtain a list of symbols and their
|
|
|
|
associated types from the DEC.
|
|
|
|
|
|
|
|
The following example demonstrates usage of the DEC in determining the
|
|
|
|
dependents of the given expression:
|
|
|
|
|
|
|
|
typedef typename parser_t::
|
|
|
|
dependent_entity_collector::symbol_t symbol_t;
|
|
|
|
|
|
|
|
std::string expression_string =
|
|
|
|
"z := abs(x + sin(2 * pi / y))";
|
|
|
|
|
|
|
|
parser_t parser;
|
|
|
|
symbol_table_t symbol_table;
|
|
|
|
|
|
|
|
expression_t expression;
|
|
|
|
expression.register_symbol_table(symbol_table);
|
|
|
|
|
|
|
|
//Collect only variable and function symbols
|
|
|
|
parser.dec().collect_variables() = true;
|
|
|
|
parser.dec().collect_functions() = true;
|
|
|
|
|
|
|
|
if (!parser.compile(expression_string,expression))
|
|
|
|
{
|
|
|
|
// error....
|
|
|
|
}
|
|
|
|
|
|
|
|
std::deque<symbol_t> symbol_list;
|
|
|
|
|
|
|
|
parser.dec().symbols(symbol_list);
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < symbol_list.size(); ++i)
|
|
|
|
{
|
|
|
|
symbol_t& symbol = symbol_list[i];
|
|
|
|
|
|
|
|
switch (symbol.second)
|
|
|
|
{
|
2014-12-17 16:55:45 +00:00
|
|
|
case parser_t::e_st_variable : ... break;
|
|
|
|
case parser_t::e_st_vector : ... break;
|
|
|
|
case parser_t::e_st_string : ... break;
|
|
|
|
case parser_t::e_st_function : ... break;
|
2014-12-17 16:43:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Note: The 'symbol_t' type is a pair comprising of the symbol name
|
|
|
|
(std::string) and the associated type of the symbol as denoted by the
|
|
|
|
cases in the switch statement.
|
|
|
|
|
|
|
|
Having particular symbols (variable or function) present in an
|
|
|
|
expression is one form of dependency. Another and just as interesting
|
|
|
|
and important type of dependency is that of assignments. Assignments
|
|
|
|
are the set of dependent symbols that 'may' have their values modified
|
|
|
|
within an expression. The following are example expressions and their
|
|
|
|
associated assignments:
|
|
|
|
|
|
|
|
Assignments Expression
|
|
|
|
1. x x := y + z
|
|
|
|
2. x, y x += y += z
|
|
|
|
3. x, y, z x := y += sin(z := w + 2)
|
|
|
|
4. z, w if (x > y, z := x + 2, w := 'A String')
|
|
|
|
5. None x + y + z
|
|
|
|
|
|
|
|
|
|
|
|
Note: In expression 4, both variables 'z' and 'w' are denoted as being
|
|
|
|
assignments even though only one of them can be modified at the time
|
|
|
|
of evaluation. Furthermore the determination of which of the two
|
|
|
|
variables the modification will occur upon can only be known with
|
2014-12-17 16:55:45 +00:00
|
|
|
certainty at evaluation time and not beforehand, hence both are listed
|
|
|
|
as being candidates for assignment.
|
2014-12-17 16:43:27 +00:00
|
|
|
|
|
|
|
The following builds upon the previous example demonstrating the usage
|
|
|
|
of the DEC in determining the 'assignments' of the given expression:
|
|
|
|
|
|
|
|
//Collect assignments
|
|
|
|
parser.dec().collect_assignments() = true;
|
|
|
|
|
|
|
|
if (!parser.compile(expression_string,expression))
|
|
|
|
{
|
|
|
|
// error....
|
|
|
|
}
|
|
|
|
|
|
|
|
std::deque<symbol_t> symbol_list;
|
|
|
|
|
|
|
|
parser.dec().assignment_symbols(symbol_list);
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < symbol_list.size(); ++i)
|
|
|
|
{
|
|
|
|
symbol_t& symbol = symbol_list[i];
|
|
|
|
|
|
|
|
switch (symbol.second)
|
|
|
|
{
|
2014-12-17 16:55:45 +00:00
|
|
|
case parser_t::e_st_variable : ... break;
|
|
|
|
case parser_t::e_st_vector : ... break;
|
|
|
|
case parser_t::e_st_string : ... break;
|
2014-12-17 16:43:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Note: The assignments will only consist of variable types and as such
|
|
|
|
will not contain symbols denoting functions.
|
|
|
|
|
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[17 - COMPILATION ERRORS]
|
2014-11-17 11:03:10 +00:00
|
|
|
When attempting to compile a malformed or otherwise erroneous ExprTk
|
|
|
|
expression, the compilation process will result in an error, as is
|
|
|
|
indicated by the 'compile' method returning a false value. A
|
|
|
|
diagnostic indicating the first error encountered and its cause can be
|
|
|
|
obtained by invoking the 'error' method, as is demonstrated in the
|
|
|
|
following example:
|
|
|
|
|
|
|
|
if (!parser.compile(expression_string,expression))
|
|
|
|
{
|
|
|
|
printf("Error: %s\n", parser.error().c_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Any error(s) resulting from a failed compilation will be stored in the
|
|
|
|
parser instance until the next time a compilation is performed. Before
|
|
|
|
then errors can be enumerated in the order they occurred by invoking
|
|
|
|
the 'get_error' method which itself will return a 'parser_error' type.
|
|
|
|
A parser_error object will contain an error diagnostic, an error mode
|
|
|
|
(or class), and the character position of the error in the expression
|
|
|
|
string. The following example demonstrates the enumeration of error(s)
|
|
|
|
in the event of a failed compilation.
|
|
|
|
|
|
|
|
if (!parser.compile(expression_string,expression))
|
|
|
|
{
|
|
|
|
for (std::size_t i = 0; i < parser.error_count(); ++i)
|
|
|
|
{
|
|
|
|
typedef exprtk::parser_error::type error_t;
|
|
|
|
|
|
|
|
error_t error = parser.get_error(i);
|
|
|
|
|
|
|
|
printf("Error[%02d] Position: %02d Type: [%14s] Msg: %s\n",
|
|
|
|
i,
|
|
|
|
error.token.position,
|
|
|
|
exprtk::parser_error::to_str(error.mode).c_str(),
|
|
|
|
error.diagnostic.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
For expressions comprised of multiple lines, the error position
|
|
|
|
provided in the parser_error object can be converted into a pair of
|
|
|
|
line and column numbers by invoking the 'update_error' function as is
|
|
|
|
demonstrated by the following example:
|
|
|
|
|
|
|
|
if (!parser.compile(program_str,expression))
|
|
|
|
{
|
|
|
|
for (std::size_t i = 0; i < parser.error_count(); ++i)
|
|
|
|
{
|
|
|
|
typedef exprtk::parser_error::type error_t;
|
|
|
|
|
|
|
|
error_t error = parser.get_error(i);
|
|
|
|
|
|
|
|
exprtk::parser_error::update_error(error,program_str);
|
|
|
|
|
|
|
|
printf("Error[%02d] at line: %d column: %d\n",
|
|
|
|
i,
|
|
|
|
error.line_no,
|
|
|
|
error.column_no);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-10 18:23:16 +00:00
|
|
|
Note: There are five distinct error modes in ExprTk which denote the
|
2014-11-17 11:03:10 +00:00
|
|
|
class of an error. These classes are as follows:
|
|
|
|
|
|
|
|
(a) Syntax
|
|
|
|
(b) Token
|
|
|
|
(c) Numeric
|
|
|
|
(d) Symbol Table
|
|
|
|
(e) Lexer
|
|
|
|
|
|
|
|
|
|
|
|
(a) Syntax Errors
|
|
|
|
These are errors related to invalid syntax found within the denoted
|
|
|
|
expression. Examples are invalid sequences of operators and variables,
|
|
|
|
incorrect number of parameters to functions, invalid conditional or
|
|
|
|
loop structures and invalid use of keywords.
|
|
|
|
|
|
|
|
eg: 'for := sin(x,y,z) + 2 * equal > until[2 - x,3]'
|
|
|
|
|
|
|
|
|
|
|
|
(b) Token Errors
|
|
|
|
Errors in this class relate to token level errors detected by one or
|
|
|
|
more of the following checkers:
|
|
|
|
|
|
|
|
(1) Bracket Checker
|
|
|
|
(2) Numeric Checker
|
|
|
|
(3) Sequence Checker
|
|
|
|
|
|
|
|
(c) Numeric Errors
|
|
|
|
This class of error is related to conversion of numeric values from
|
|
|
|
their string form to the underlying numerical type (float, double
|
|
|
|
etc).
|
|
|
|
|
|
|
|
(d) Symbol Table Errors
|
|
|
|
This is the class of errors related to failures when interacting with
|
|
|
|
the registered symbol_table instance. Errors such as not being able to
|
|
|
|
find, within the symbol_table, symbols representing variables or
|
|
|
|
functions, to being unable to create new variables in the symbol_table
|
|
|
|
via the 'unknown symbol resolver' mechanism.
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[18 - EXPRTK NOTES]
|
2014-05-27 21:10:40 +00:00
|
|
|
The following is a list of facts and suggestions one may want to take
|
|
|
|
into account when using Exprtk:
|
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(00) Precision and performance of expression evaluations are the
|
2013-04-04 09:45:19 +00:00
|
|
|
dominant principles of the ExprTk library.
|
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(01) ExprTk uses a rudimentary imperative programming model with
|
2014-12-10 15:59:06 +00:00
|
|
|
syntax based on languages such as Pascal and C. Furthermore
|
|
|
|
ExprTk is an LL(2) type grammar and is processed using a
|
|
|
|
recursive descent parsing algorithm.
|
2014-05-27 21:10:40 +00:00
|
|
|
|
2014-10-14 11:06:52 +00:00
|
|
|
(02) Supported types are float, double, long double and MPFR/GMP.
|
2013-03-14 21:38:09 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(03) Standard mathematical operator precedence is applied (BEDMAS).
|
2013-03-14 21:38:09 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(04) Results of expressions that are deemed as being 'valid' are to
|
2013-07-28 11:35:06 +00:00
|
|
|
exist within the set of Real numbers. All other results will be
|
2013-10-16 21:44:15 +00:00
|
|
|
of the value: Not-A-Number (NaN).
|
2013-07-28 11:35:06 +00:00
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
(05) Supported user defined types are numeric and string
|
|
|
|
variables, numeric vectors and functions.
|
2013-03-14 21:38:09 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(06) All reserved words, keywords, variable, vector, string and
|
|
|
|
function names are case-insensitive.
|
2013-03-14 21:38:09 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(07) Variable, vector and function names must begin with a letter
|
2014-12-01 17:48:39 +00:00
|
|
|
(A-Z or a-z), then can be comprised of any combination of
|
2013-04-04 09:45:19 +00:00
|
|
|
letters, digits and underscores. (eg: x, var1 or power_func99)
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(08) Expression lengths and sub-expression lists are limited only by
|
2013-07-08 22:32:08 +00:00
|
|
|
storage capacity.
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(09) The life-time of objects registered with or created from a
|
|
|
|
specific symbol-table must span at least the life-time of the
|
|
|
|
compiled expressions which utilize objects, such as variables,
|
|
|
|
of that symbol-table, otherwise the result will be undefined
|
2013-07-28 11:35:06 +00:00
|
|
|
behavior.
|
2013-04-01 09:30:28 +00:00
|
|
|
|
2014-12-10 15:59:06 +00:00
|
|
|
(10) Equal and Nequal are normalised-epsilon equality routines,
|
|
|
|
which use epsilons of 0.0000000001 and 0.000001 for double and
|
|
|
|
float types respectively.
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(11) All trigonometric functions assume radian input unless stated
|
|
|
|
otherwise.
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(12) Expressions may contain white-space characters such as space,
|
|
|
|
tabs, new-lines, control-feed et al.
|
2013-03-14 21:38:09 +00:00
|
|
|
('\n', '\r', '\t', '\b', '\v', '\f')
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-10-14 11:06:52 +00:00
|
|
|
(13) Strings may be comprised of any combination of letters, digits
|
|
|
|
or special characters including (~!@#$%^&*()[]|=+ ,./?<>;:"`~_),
|
|
|
|
and must be enclosed with single-quotes.
|
|
|
|
eg: 'Frankly my dear, 1 do n0t give a damn!'
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(14) User defined normal functions can have up to 20 parameters,
|
2014-12-07 19:33:10 +00:00
|
|
|
where as user defined generic-functions and vararg-functions
|
|
|
|
can have an unlimited number of parameters.
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(15) The inbuilt polynomial functions can be at most of degree 12.
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
(16) Where appropriate constant folding optimisations may be applied.
|
|
|
|
(eg: The expression '2 + (3 - (x / y))' becomes '5 - (x / y)')
|
2013-03-11 13:29:59 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(17) If the strength reduction compilation option has been enabled,
|
2014-02-09 09:20:15 +00:00
|
|
|
then where applicable strength reduction optimisations may be
|
|
|
|
applied.
|
2014-01-22 20:32:55 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(18) String processing capabilities are available by default. To
|
|
|
|
turn them off, the following needs to be defined at compile
|
|
|
|
time: exprtk_disable_string_capabilities
|
2013-03-24 17:54:44 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(19) Composited functions can call themselves or any other functions
|
2013-04-17 14:43:00 +00:00
|
|
|
that have been defined prior to their own definition.
|
2013-04-13 08:26:57 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(20) Recursive calls made from within composited functions will have
|
2013-07-12 13:08:57 +00:00
|
|
|
a stack size bound by the stack of the executing architecture.
|
2013-07-08 22:32:08 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(21) User defined functions by default are assumed to have side
|
2014-05-03 21:49:15 +00:00
|
|
|
effects. As such an "all constant parameter" invocation of such
|
2014-11-30 09:48:19 +00:00
|
|
|
functions wont result in constant folding. If the function has
|
|
|
|
no side effects then that can be noted during the constructor
|
|
|
|
of the ifunction allowing it to be constant folded where
|
2014-05-03 21:49:15 +00:00
|
|
|
appropriate.
|
|
|
|
|
2014-12-01 17:48:39 +00:00
|
|
|
(22) The entity relationship between symbol_table and an expression
|
|
|
|
is one-to-many. Hence the intended use case where possible is
|
|
|
|
to have a single symbol table manage the variable and function
|
2014-10-14 11:06:52 +00:00
|
|
|
requirements of multiple expressions.
|
2014-01-21 21:13:37 +00:00
|
|
|
|
2014-11-30 09:48:19 +00:00
|
|
|
(23) The common use-case for an expression is to have it compiled
|
2014-12-01 17:48:39 +00:00
|
|
|
only ONCE and then subsequently have it evaluated multiple
|
2014-11-30 09:48:19 +00:00
|
|
|
times. An extremely inefficient and suboptimal approach would
|
|
|
|
be to recompile an expression from its string form every time
|
2014-04-19 11:10:15 +00:00
|
|
|
it requires evaluating.
|
2014-01-21 21:13:37 +00:00
|
|
|
|
2014-12-25 19:31:45 +00:00
|
|
|
(24) Where appropriate the return values of method invocations from
|
|
|
|
the parser and symbol_table should be taken into account.
|
|
|
|
Specifically the 'compile' method of the parser and the
|
|
|
|
'add_xxx' set of methods of the symbol table as they denote
|
|
|
|
success or failure of the invoked call.
|
|
|
|
|
|
|
|
(25) The following are examples of compliant floating point value
|
2013-12-30 10:09:57 +00:00
|
|
|
representations:
|
2014-12-01 17:48:39 +00:00
|
|
|
|
2014-05-27 21:10:40 +00:00
|
|
|
(a) 12345 (e) -123.456
|
|
|
|
(b) +123.456e+12 (f) 123.456E-12
|
|
|
|
(c) +012.045e+07 (g) .1234
|
|
|
|
(d) 123.456f (h) -321.654E+3L
|
2013-12-08 22:30:01 +00:00
|
|
|
|
2014-12-25 19:31:45 +00:00
|
|
|
(26) Expressions may contain any of the following comment styles:
|
2014-12-01 17:48:39 +00:00
|
|
|
|
2013-03-26 14:20:20 +00:00
|
|
|
1. // .... \n
|
|
|
|
2. # .... \n
|
|
|
|
3. /* .... */
|
2013-03-24 17:54:44 +00:00
|
|
|
|
2014-12-25 19:31:45 +00:00
|
|
|
(27) The 'null' value type is a special non-zero type that
|
2014-11-30 09:48:19 +00:00
|
|
|
incorporates specific semantics when undergoing operations with
|
|
|
|
the standard numeric type. The following is a list of type and
|
|
|
|
boolean results associated with the use of 'null':
|
|
|
|
|
2014-10-20 19:11:38 +00:00
|
|
|
1. null +,-,*,/,% x --> x
|
|
|
|
2. x +,-,*,/,% null --> x
|
|
|
|
3. null +,-,*,/,% null --> null
|
|
|
|
4. null == null --> true
|
|
|
|
5. null == x --> true
|
|
|
|
6. x == null --> true
|
|
|
|
7. x != null --> false
|
|
|
|
8. null != null --> false
|
|
|
|
9. null != x --> false
|
|
|
|
|
2014-12-25 19:31:45 +00:00
|
|
|
(28) The following is a list of reserved words and symbols used by
|
2014-11-30 09:48:19 +00:00
|
|
|
ExprTk. Attempting to add a variable or custom function to a
|
|
|
|
symbol table using any of the reserved words will result in a
|
|
|
|
failure.
|
2014-11-11 20:01:09 +00:00
|
|
|
|
|
|
|
abs, acos, acosh, and, asin, asinh, atan, atan2, atanh, avg,
|
|
|
|
break, case, ceil, clamp, continue, cosh, cos, cot, csc,
|
|
|
|
default, deg2grad, deg2rad, else, equal, erfc, erf, exp,
|
|
|
|
expm1, false, floor, for, frac, grad2deg, hypot, iclamp, if,
|
|
|
|
ilike, in, inrange, in, like, log, log10, log1p, log2, logn,
|
|
|
|
mand, max, min, mod, mor, mul, nand, ncdf, nor, not,
|
|
|
|
not_equal, not, null, or, pow, rad2deg, repeat, root,
|
|
|
|
roundn, round, sec, sgn, shl, shr, sinc, sinh, sin, sqrt,
|
|
|
|
sum, swap, switch, tanh, tan, true, trunc, until, var,
|
|
|
|
while, xnor, xor, xor
|
|
|
|
|
2014-12-25 19:31:45 +00:00
|
|
|
(29) Every valid ExprTk statement is a "value returning" expression.
|
2014-11-30 09:48:19 +00:00
|
|
|
Unlike some languages that limit the types of expressions that
|
|
|
|
can be performed in certain situations, in ExprTk any valid
|
2014-12-14 06:38:05 +00:00
|
|
|
expression can be used in any "value consuming" context. eg:
|
2014-10-14 11:06:52 +00:00
|
|
|
|
|
|
|
var y := 3;
|
|
|
|
for (var x := switch
|
|
|
|
{
|
2014-12-25 19:31:45 +00:00
|
|
|
case 1 : 7;
|
|
|
|
case 2 : -1 + ~{var x{};};
|
|
|
|
default : y > 2 ? 3 : 4;
|
2014-10-14 11:06:52 +00:00
|
|
|
};
|
|
|
|
x != while (y > 0) { y -= 1; };
|
|
|
|
x -= {if(min(x,y) < 2 * max(x,y))
|
|
|
|
x + 2;
|
|
|
|
else
|
|
|
|
x + y - 3;}
|
|
|
|
)
|
|
|
|
{
|
|
|
|
(x + y) / (x - y);
|
|
|
|
}
|
|
|
|
|
2013-03-11 13:29:59 +00:00
|
|
|
|
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[19 - SIMPLE EXPRTK EXAMPLE]
|
2013-01-30 13:28:22 +00:00
|
|
|
--- snip ---
|
|
|
|
#include <cstdio>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "exprtk.hpp"
|
|
|
|
|
2013-04-01 09:30:28 +00:00
|
|
|
template <typename T>
|
|
|
|
struct myfunc : public exprtk::ifunction<T>
|
|
|
|
{
|
|
|
|
myfunc() : exprtk::ifunction<T>(2) {}
|
|
|
|
|
2013-12-30 10:09:57 +00:00
|
|
|
T operator()(const T& v1, const T& v2)
|
2013-04-01 09:30:28 +00:00
|
|
|
{
|
|
|
|
return T(1) + (v1 * v2) / T(3);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-01-30 13:28:22 +00:00
|
|
|
int main()
|
|
|
|
{
|
|
|
|
typedef exprtk::symbol_table<double> symbol_table_t;
|
|
|
|
typedef exprtk::expression<double> expression_t;
|
|
|
|
typedef exprtk::parser<double> parser_t;
|
|
|
|
typedef exprtk::parser_error::type error_t;
|
|
|
|
|
2014-04-06 21:01:02 +00:00
|
|
|
std::string expression_str =
|
|
|
|
"z := 2 myfunc([4 + sin(x / pi)^3],y ^ 2)";
|
2013-01-30 13:28:22 +00:00
|
|
|
|
|
|
|
double x = 1.1;
|
|
|
|
double y = 2.2;
|
|
|
|
double z = 3.3;
|
|
|
|
|
2013-04-01 09:30:28 +00:00
|
|
|
myfunc<double> mf;
|
|
|
|
|
2013-01-30 13:28:22 +00:00
|
|
|
symbol_table_t symbol_table;
|
|
|
|
symbol_table.add_constants();
|
|
|
|
symbol_table.add_variable("x",x);
|
|
|
|
symbol_table.add_variable("y",y);
|
|
|
|
symbol_table.add_variable("z",z);
|
2013-04-01 09:30:28 +00:00
|
|
|
symbol_table.add_function("myfunc",mf);
|
2013-01-30 13:28:22 +00:00
|
|
|
|
|
|
|
expression_t expression;
|
|
|
|
expression.register_symbol_table(symbol_table);
|
|
|
|
|
|
|
|
parser_t parser;
|
|
|
|
|
|
|
|
if (!parser.compile(expression_str,expression))
|
|
|
|
{
|
2014-05-27 21:10:40 +00:00
|
|
|
// A compilation error has occurred. Attempt to
|
|
|
|
// print all errors to stdout.
|
2014-02-09 09:20:15 +00:00
|
|
|
|
2013-01-30 13:28:22 +00:00
|
|
|
printf("Error: %s\tExpression: %s\n",
|
|
|
|
parser.error().c_str(),
|
|
|
|
expression_str.c_str());
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < parser.error_count(); ++i)
|
|
|
|
{
|
2014-02-09 09:20:15 +00:00
|
|
|
// Include the specific nature of each error
|
|
|
|
// and its position in the expression string.
|
|
|
|
|
2013-01-30 13:28:22 +00:00
|
|
|
error_t error = parser.get_error(i);
|
2014-02-11 09:39:45 +00:00
|
|
|
|
2013-10-16 21:44:15 +00:00
|
|
|
printf("Error: %02d Position: %02d "
|
|
|
|
"Type: [%s] "
|
|
|
|
"Message: %s "
|
|
|
|
"Expression: %s\n",
|
2013-01-30 13:28:22 +00:00
|
|
|
static_cast<int>(i),
|
|
|
|
static_cast<int>(error.token.position),
|
|
|
|
exprtk::parser_error::to_str(error.mode).c_str(),
|
|
|
|
error.diagnostic.c_str(),
|
|
|
|
expression_str.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-02-09 09:20:15 +00:00
|
|
|
// Evaluate the expression and obtain its result.
|
|
|
|
|
2013-01-30 13:28:22 +00:00
|
|
|
double result = expression.value();
|
|
|
|
|
|
|
|
printf("Result: %10.5f\n",result);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
--- snip ---
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[20 - BUILD OPTIONS]
|
2014-06-08 09:24:53 +00:00
|
|
|
When building ExprTk there are a number of defines that will enable or
|
|
|
|
disable certain features and capabilities. The defines can either be
|
|
|
|
part of a compiler command line switch or scoped around the include to
|
|
|
|
the ExprTk header.
|
|
|
|
|
|
|
|
(1) exprtk_enable_debugging
|
2014-10-14 11:06:52 +00:00
|
|
|
This define will enable printing of debug information to stdout during
|
|
|
|
the compilation process.
|
2014-06-08 09:24:53 +00:00
|
|
|
|
|
|
|
(2) exprtk_disable_comments
|
|
|
|
This define will disable the ability for expressions to have comments.
|
|
|
|
Expressions that have comments when parsed with a build that has this
|
|
|
|
option, will result in a compilation failure.
|
|
|
|
|
|
|
|
(3) exprtk_disable_break_continue
|
|
|
|
This define will disable the loop-wise 'break' and 'continue'
|
|
|
|
capabilities. Any expression that contains those keywords will result
|
|
|
|
in a compilation failure.
|
|
|
|
|
|
|
|
(4) exprtk_disable_sc_andor
|
|
|
|
This define will disable the short-circuit '&' (and) and '|' (or)
|
|
|
|
operators
|
|
|
|
|
|
|
|
(5) exprtk_disable_enhanced_features
|
|
|
|
This define will disable all enhanced features such as strength
|
|
|
|
reduction and special function optimisations and expression specific
|
|
|
|
type instantiations. This feature will reduce compilation times and
|
|
|
|
binary sizes but will also result in massive performance degradation
|
|
|
|
of expression evaluations.
|
|
|
|
|
|
|
|
(6) exprtk_disable_string_capabilities
|
|
|
|
This define will disable all string processing capabilities. Any
|
|
|
|
expression that contains a string or string related syntax will result
|
|
|
|
in a compilation failure.
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[21 - FILES]
|
2014-11-17 11:03:10 +00:00
|
|
|
The source distribution of ExprTk is comprised of the following set of
|
|
|
|
files:
|
|
|
|
|
|
|
|
(00) Makefile
|
|
|
|
(01) readme.txt
|
|
|
|
(02) exprtk.hpp
|
|
|
|
(03) exprtk_test.cpp
|
|
|
|
(04) exprtk_benchmark.cpp
|
|
|
|
(05) exprtk_simple_example_01.cpp
|
|
|
|
(06) exprtk_simple_example_02.cpp
|
|
|
|
(07) exprtk_simple_example_03.cpp
|
|
|
|
(08) exprtk_simple_example_04.cpp
|
|
|
|
(09) exprtk_simple_example_05.cpp
|
|
|
|
(10) exprtk_simple_example_06.cpp
|
|
|
|
(11) exprtk_simple_example_07.cpp
|
|
|
|
(12) exprtk_simple_example_08.cpp
|
|
|
|
(13) exprtk_simple_example_09.cpp
|
|
|
|
(14) exprtk_simple_example_10.cpp
|
|
|
|
(15) exprtk_simple_example_11.cpp
|
|
|
|
(16) exprtk_simple_example_12.cpp
|
|
|
|
(17) exprtk_simple_example_13.cpp
|
|
|
|
(18) exprtk_simple_example_14.cpp
|
|
|
|
(19) exprtk_simple_example_15.cpp
|
|
|
|
(20) exprtk_simple_example_16.cpp
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-17 16:43:27 +00:00
|
|
|
[22 - LANGUAGE STRUCTURE]
|
2014-05-27 21:10:40 +00:00
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|00 - If Statement |
|
|
|
|
| |
|
|
|
|
| [if] ---> [(] ---> [condition] -+-> [,] -+ |
|
|
|
|
| | | |
|
|
|
|
| +---------------<---------------+ | |
|
|
|
|
| | | |
|
|
|
|
| | +------------------<------------------+ |
|
|
|
|
| | | |
|
|
|
|
| | +--> [consequent] ---> [,] ---> [alternative] ---> [)] |
|
|
|
|
| | |
|
|
|
|
| +--> [)] --+-> [{] ---> [expression*] ---> [}] --+ |
|
|
|
|
| | | |
|
|
|
|
| | +---------<----------+ |
|
|
|
|
| +----<-----+ | |
|
|
|
|
| | v |
|
|
|
|
| +--> [consequent] --> [;] -{*}-> [else-statement] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|01 - Else Statement |
|
|
|
|
| |
|
|
|
|
| [else] -+-> [alternative] ---> [;] |
|
|
|
|
| | |
|
|
|
|
| +--> [{] ---> [expression*] ---> [}] |
|
|
|
|
| | |
|
|
|
|
| +--> [if-statement] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|02 - Ternary Statement |
|
|
|
|
| |
|
|
|
|
| [condition] ---> [?] ---> [consequent] ---> [:] --+ |
|
|
|
|
| | |
|
|
|
|
| +------------------------<------------------------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [alternative] --> [;] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|03 - While Loop |
|
|
|
|
| |
|
|
|
|
| [while] ---> [(] ---> [condition] ---> [)] ---+ |
|
|
|
|
| | |
|
|
|
|
| +----------------------<----------------------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [{] ---> [expression*] ---> [}] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|04 - Repeat Until Loop |
|
|
|
|
| |
|
|
|
|
| [repeat] ---> [expression*] ---+ |
|
|
|
|
| | |
|
|
|
|
| +--------------<---------------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [until] ---> [(] ---> [condition] --->[)] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|05 - For Loop |
|
|
|
|
| |
|
|
|
|
| [for] ---> [(] -+-> [initialise expression] --+--+ |
|
|
|
|
| | | | |
|
|
|
|
| +------------->---------------+ v |
|
|
|
|
| | |
|
|
|
|
| +-----------------------<------------------------+ |
|
|
|
|
| | |
|
2014-07-01 10:46:51 +00:00
|
|
|
| +--> [;] -+-> [condition] -+-> [;] ---+ |
|
2014-05-27 21:10:40 +00:00
|
|
|
| | | | |
|
|
|
|
| +------->--------+ v |
|
|
|
|
| | |
|
|
|
|
| +------------------<---------+--------+ |
|
|
|
|
| | | |
|
|
|
|
| +--> [increment expression] -+-> [)] --+ |
|
|
|
|
| | |
|
|
|
|
| +------------------<-------------------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [{] ---> [expression*] ---> [}] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|06 - Switch Statement |
|
|
|
|
| |
|
|
|
|
| [switch] ---> [{] ---+ |
|
|
|
|
| | |
|
|
|
|
| +---------<----------+-----------<-----------+ |
|
|
|
|
| | | |
|
|
|
|
| +--> [case] ---> [condition] ---> [:] ---+ | |
|
|
|
|
| | | |
|
|
|
|
| +-------------------<--------------------+ | |
|
|
|
|
| | | |
|
|
|
|
| +--> [consequent] ---> [;] --------->--------+ |
|
|
|
|
| | | |
|
|
|
|
| | | |
|
|
|
|
| +--> [default] ---> [consequent] ---> [;] ---+ |
|
|
|
|
| | | |
|
|
|
|
| +---------------------<----------------------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [}] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|07 - Multi Subexpression Statement |
|
|
|
|
| |
|
|
|
|
| +--------------<---------------+ |
|
|
|
|
| | | |
|
|
|
|
| [~] ---> [{\(] -+-> [expression] -+-> [;\,] ---+ |
|
|
|
|
| | |
|
|
|
|
| +----------------<----------------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [}\)] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|08 - Multi Case-Consequent Statement |
|
|
|
|
| |
|
|
|
|
| [[*]] ---> [{] ---+ |
|
|
|
|
| | |
|
|
|
|
| +--------<--------+--------------<----------+ |
|
|
|
|
| | | |
|
|
|
|
| +--> [case] ---> [condition] ---> [:] ---+ | |
|
|
|
|
| | | |
|
|
|
|
| +-------------------<--------------------+ | |
|
|
|
|
| | | |
|
|
|
|
| +--> [consequent] ---> [;] ---+------>------+ |
|
|
|
|
| | |
|
|
|
|
| +--> [}] |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|09 - Variable Definition Statement |
|
|
|
|
| |
|
2014-12-14 06:38:05 +00:00
|
|
|
| [var] ---> [symbol] -+-> [:=] -+-> [expression] -+-> [;] |
|
|
|
|
| | | | |
|
|
|
|
| | +-----> [{}] -->--+ |
|
2014-05-27 21:10:40 +00:00
|
|
|
| | | |
|
|
|
|
| +------------->-------------+ |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
|
|
|
|10 - Vector Definition Statement |
|
|
|
|
| |
|
|
|
|
| [var] ---> [symbol] ---> [[] ---> [constant] ---> []] --+ |
|
|
|
|
| | |
|
|
|
|
| +---------------------------<---------------------------+ |
|
|
|
|
| | |
|
|
|
|
| | +--------->---------+ |
|
|
|
|
| | | | |
|
2014-12-10 15:59:06 +00:00
|
|
|
| +--> [:=] ---> [{] -+-+-> [expression] -+-> [}] ---> [;] |
|
2014-05-27 21:10:40 +00:00
|
|
|
| | | |
|
|
|
|
| +--<--- [,] <-----+ |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|
2014-12-10 15:59:06 +00:00
|
|
|
|11 - Range Statement |
|
|
|
|
| |
|
|
|
|
| +-------->--------+ |
|
|
|
|
| | | |
|
|
|
|
| [[] -+-> [expression] -+-> [:] -+-> [expression] -+--> []] |
|
|
|
|
| | | |
|
|
|
|
| +-------->--------+ |
|
|
|
|
| |
|
|
|
|
+-------------------------------------------------------------+
|