C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
9cddffaf52
commit
628477bf47
2422
exprtk.hpp
2422
exprtk.hpp
File diff suppressed because it is too large
Load Diff
|
@ -39,14 +39,14 @@ void square_wave()
|
||||||
|
|
||||||
static const T pi = T(3.141592653589793238462643383279502);
|
static const T pi = T(3.141592653589793238462643383279502);
|
||||||
|
|
||||||
T f = pi / T(10);
|
const T f = pi / T(10);
|
||||||
T t = T(0);
|
const T a = T(10);
|
||||||
T a = T(10);
|
T t = T(0);
|
||||||
|
|
||||||
symbol_table_t symbol_table;
|
symbol_table_t symbol_table;
|
||||||
symbol_table.add_variable("f",f);
|
|
||||||
symbol_table.add_variable("t",t);
|
symbol_table.add_variable("t",t);
|
||||||
symbol_table.add_variable("a",a);
|
symbol_table.add_constant("f",f);
|
||||||
|
symbol_table.add_constant("a",a);
|
||||||
symbol_table.add_constants();
|
symbol_table.add_constants();
|
||||||
|
|
||||||
expression_t expression;
|
expression_t expression;
|
||||||
|
|
|
@ -30,9 +30,9 @@ void polynomial()
|
||||||
|
|
||||||
std::string expression_string = "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1";
|
std::string expression_string = "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1";
|
||||||
|
|
||||||
T r0 = T(0);
|
const T r0 = T(0);
|
||||||
T r1 = T(1);
|
const T r1 = T(1);
|
||||||
T x = T(0);
|
T x = T(0);
|
||||||
|
|
||||||
symbol_table_t symbol_table;
|
symbol_table_t symbol_table;
|
||||||
symbol_table.add_variable("x",x);
|
symbol_table.add_variable("x",x);
|
||||||
|
|
|
@ -70,7 +70,7 @@ void fibonacci()
|
||||||
|
|
||||||
for (std::size_t i = 0; i < 40; ++i)
|
for (std::size_t i = 0; i < 40; ++i)
|
||||||
{
|
{
|
||||||
x = i;
|
x = static_cast<T>(i);
|
||||||
|
|
||||||
T result = expression.value();
|
T result = expression.value();
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ void primes()
|
||||||
|
|
||||||
for (std::size_t i = 0; i < 100; ++i)
|
for (std::size_t i = 0; i < 100; ++i)
|
||||||
{
|
{
|
||||||
x = i;
|
x = static_cast<T>(i);
|
||||||
|
|
||||||
T result1 = expression1.value();
|
T result1 = expression1.value();
|
||||||
T result2 = expression2.value();
|
T result2 = expression2.value();
|
||||||
|
|
|
@ -72,7 +72,7 @@ void newton_sqrt()
|
||||||
|
|
||||||
for (std::size_t i = 0; i < 100; ++i)
|
for (std::size_t i = 0; i < 100; ++i)
|
||||||
{
|
{
|
||||||
x = i;
|
x = static_cast<T>(i);
|
||||||
|
|
||||||
T result = expression.value();
|
T result = expression.value();
|
||||||
|
|
||||||
|
|
|
@ -4848,7 +4848,7 @@ inline std::size_t load_expressions(const std::string& file_name,
|
||||||
|
|
||||||
std::size_t line_count = 0;
|
std::size_t line_count = 0;
|
||||||
|
|
||||||
while (std::getline(stream,buffer))
|
while (std::getline(stream,(buffer)))
|
||||||
{
|
{
|
||||||
if (buffer.empty())
|
if (buffer.empty())
|
||||||
continue;
|
continue;
|
||||||
|
@ -7685,7 +7685,7 @@ struct my_usr_ext : public exprtk::parser<T>::unknown_symbol_resolver
|
||||||
{
|
{
|
||||||
static T var_default_value = 1.0;
|
static T var_default_value = 1.0;
|
||||||
|
|
||||||
if (!(result = symbol_table.create_variable(unknown_symbol, var_default_value++)))
|
if ((result = symbol_table.create_variable(unknown_symbol, var_default_value++)) == false)
|
||||||
{
|
{
|
||||||
error_message = "Failed to create variable(" + unknown_symbol + ") in primary symbol table";
|
error_message = "Failed to create variable(" + unknown_symbol + ") in primary symbol table";
|
||||||
}
|
}
|
||||||
|
@ -7694,7 +7694,7 @@ struct my_usr_ext : public exprtk::parser<T>::unknown_symbol_resolver
|
||||||
{
|
{
|
||||||
static T cvar_default_value = 1.0;
|
static T cvar_default_value = 1.0;
|
||||||
|
|
||||||
if (!(result = symbol_table.add_constant(unknown_symbol, cvar_default_value++)))
|
if ((result = symbol_table.add_constant(unknown_symbol, cvar_default_value++)) == false)
|
||||||
{
|
{
|
||||||
error_message = "Failed to create const variable(" + unknown_symbol + ") in primary symbol table";
|
error_message = "Failed to create const variable(" + unknown_symbol + ") in primary symbol table";
|
||||||
}
|
}
|
||||||
|
|
208
readme.txt
208
readme.txt
|
@ -224,7 +224,7 @@ of C++ compilers:
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| true | True state or any value other than zero (typically 1). |
|
| true | True state or any value other than zero (typically 1). |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| false | False state, value of zero. |
|
| false | False state, value of exactly zero. |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| and | Logical AND, True only if x and y are both true. |
|
| and | Logical AND, True only if x and y are both true. |
|
||||||
| | (eg: x and y) |
|
| | (eg: x and y) |
|
||||||
|
@ -275,7 +275,7 @@ of C++ compilers:
|
||||||
| clamp | Clamp x in range between r0 and r1, where r0 < r1. |
|
| clamp | Clamp x in range between r0 and r1, where r0 < r1. |
|
||||||
| | (eg: clamp(r0,x,r1)) |
|
| | (eg: clamp(r0,x,r1)) |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| equal | Equality test between x and y using normalized epsilon |
|
| equal | Equality test between x and y using normalised epsilon |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| erf | Error function of x. (eg: erf(x)) |
|
| erf | Error function of x. (eg: erf(x)) |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
|
@ -321,7 +321,7 @@ of C++ compilers:
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| ncdf | Normal cumulative distribution function. (eg: ncdf(x)) |
|
| ncdf | Normal cumulative distribution function. (eg: ncdf(x)) |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| nequal | Not-equal test between x and y using normalized epsilon |
|
| nequal | Not-equal test between x and y using normalised epsilon |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
| pow | x to the power of y. (eg: pow(x,y) == x ^ y) |
|
| pow | x to the power of y. (eg: pow(x,y) == x ^ y) |
|
||||||
+----------+---------------------------------------------------------+
|
+----------+---------------------------------------------------------+
|
||||||
|
@ -499,7 +499,7 @@ of C++ compilers:
|
||||||
| | eg: |
|
| | eg: |
|
||||||
| | 1. if (x > y) z; else w; |
|
| | 1. if (x > y) z; else w; |
|
||||||
| | 2. if (x > y) z; else if (w != u) v; |
|
| | 2. if (x > y) z; else if (w != u) v; |
|
||||||
| | 3. if (x < y) {z; w + 1;} else u; |
|
| | 3. if (x < y) { z; w + 1; } else u; |
|
||||||
| | 4. if ((x != y) and (z > w)) |
|
| | 4. if ((x != y) and (z > w)) |
|
||||||
| | { |
|
| | { |
|
||||||
| | y := sin(x) / u; |
|
| | y := sin(x) / u; |
|
||||||
|
@ -651,7 +651,7 @@ expressions. The types are as follows:
|
||||||
|
|
||||||
(1) Scalar Type
|
(1) Scalar Type
|
||||||
The scalar type is a singular numeric value. The underlying type is
|
The scalar type is a singular numeric value. The underlying type is
|
||||||
that used to specialize the ExprTk components (float, double, long
|
that used to specialise the ExprTk components (float, double, long
|
||||||
double, MPFR et al).
|
double, MPFR et al).
|
||||||
|
|
||||||
|
|
||||||
|
@ -673,7 +673,7 @@ however can not interact with scalar or vector types.
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
[SECTION 10 - COMPONENTS]
|
[SECTION 10 - COMPONENTS]
|
||||||
There are three primary components, that are specialized upon a given
|
There are three primary components, that are specialised upon a given
|
||||||
numeric type, which make up the core of ExprTk. The components are as
|
numeric type, which make up the core of ExprTk. The components are as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
|
@ -791,8 +791,9 @@ methods:
|
||||||
4. bool add_vector (const std::string& name, vector_type&)
|
4. bool add_vector (const std::string& name, vector_type&)
|
||||||
|
|
||||||
|
|
||||||
The 'vector' type must consist of a contiguous array of scalars which
|
Note: The 'vector' type must be comprised from a contiguous array of
|
||||||
can be one of the following:
|
scalars with a size that is larger than zero. The vector type itself
|
||||||
|
can be any one of the following:
|
||||||
|
|
||||||
1. std::vector<scalar_t>
|
1. std::vector<scalar_t>
|
||||||
2. scalar_t(&v)[N]
|
2. scalar_t(&v)[N]
|
||||||
|
@ -800,6 +801,18 @@ can be one of the following:
|
||||||
4. exprtk::vector_view<scalar_t>
|
4. exprtk::vector_view<scalar_t>
|
||||||
|
|
||||||
|
|
||||||
|
When registering a variable, vector, string or function with an
|
||||||
|
instance of a symbol_table, the call to 'add_...' may fail and return
|
||||||
|
a false result due to one or more of the following reasons:
|
||||||
|
|
||||||
|
1. Variable name contains invalid characters or is ill-formed
|
||||||
|
2. Variable name conflicts with a reserved word (eg: 'while')
|
||||||
|
3. Variable name conflicts with a previously registered variable
|
||||||
|
4. A vector of size (length) zero is being registered
|
||||||
|
5. A free function exceeding fifteen parameters is being registered
|
||||||
|
6. The symbol_table instance is in an invalid state
|
||||||
|
|
||||||
|
|
||||||
(2) Expression
|
(2) Expression
|
||||||
A structure that holds an abstract syntax tree or AST for a specified
|
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 and is used to evaluate said expression. Evaluation of the
|
||||||
|
@ -920,8 +933,8 @@ including which control block each expression references and their
|
||||||
associated reference counts.
|
associated reference counts.
|
||||||
|
|
||||||
|
|
||||||
exprtk::expression e0; // constructed expression, eg: x + 1
|
exprtk::expression e0; // constructed expression, eg: x + 1
|
||||||
exprtk::expression e1; // constructed expression, eg: 2z + y
|
exprtk::expression e1; // constructed expression, eg: 2z + y
|
||||||
|
|
||||||
+-----[ e0 cntrl block]----+ +-----[ e1 cntrl block]-----+
|
+-----[ e0 cntrl block]----+ +-----[ e1 cntrl block]-----+
|
||||||
| 1. Expression Node 'x+1' | | 1. Expression Node '2z+y' |
|
| 1. Expression Node 'x+1' | | 1. Expression Node '2z+y' |
|
||||||
|
@ -934,7 +947,7 @@ associated reference counts.
|
||||||
+--------------------+ +--------------------+
|
+--------------------+ +--------------------+
|
||||||
|
|
||||||
|
|
||||||
e0 = e1; // e0 and e1 are now 2z+y
|
e0 = e1; // e0 and e1 are now 2z+y
|
||||||
|
|
||||||
+-----[ e1 cntrl block]-----+
|
+-----[ e1 cntrl block]-----+
|
||||||
| 1. Expression Node '2z+y' |
|
| 1. Expression Node '2z+y' |
|
||||||
|
@ -1226,7 +1239,7 @@ In the following example, the return value of the expression will be
|
||||||
within the loop body on its last iteration:
|
within the loop body on its last iteration:
|
||||||
|
|
||||||
var x := 1;
|
var x := 1;
|
||||||
x + for (var i := i; i < 10; i += 1)
|
x + for (var i := x; i < 10; i += 1)
|
||||||
{
|
{
|
||||||
i / 2;
|
i / 2;
|
||||||
i + 1;
|
i + 1;
|
||||||
|
@ -1303,7 +1316,7 @@ lets review the following expression:
|
||||||
|
|
||||||
var x := 2; // Statement 1
|
var x := 2; // Statement 1
|
||||||
var y := x + 2; // Statement 2
|
var y := x + 2; // Statement 2
|
||||||
x + y // Statement 3
|
x + y; // Statement 3
|
||||||
y := x + 3y; // Statement 4
|
y := x + 3y; // Statement 4
|
||||||
x - y; // Statement 5
|
x - y; // Statement 5
|
||||||
|
|
||||||
|
@ -1332,9 +1345,9 @@ ExprTk support two forms of conditional branching or otherwise known
|
||||||
as if-statements. The first form, is a simple function based
|
as if-statements. The first form, is a simple function based
|
||||||
conditional statement, that takes exactly three input expressions:
|
conditional statement, that takes exactly three input expressions:
|
||||||
condition, consequent and alternative. The following is an example
|
condition, consequent and alternative. The following is an example
|
||||||
expression that utilizes the function based if-statement.
|
expression that utilises the function based if-statement.
|
||||||
|
|
||||||
x := if (y < z, y + 1, 2* z)
|
x := if (y < z, y + 1, 2 * z)
|
||||||
|
|
||||||
|
|
||||||
In the example above, if the condition 'y < z' is true, then the
|
In the example above, if the condition 'y < z' is true, then the
|
||||||
|
@ -1345,7 +1358,7 @@ essentially the simplest form of an if-then-else statement. A simple
|
||||||
variation of the expression where the value of the if-statement is
|
variation of the expression where the value of the if-statement is
|
||||||
used within another statement is as follows:
|
used within another statement is as follows:
|
||||||
|
|
||||||
x := 3 * if (y < z, y + 1, 2* z) / 2
|
x := 3 * if (y < z, y + 1, 2 * z) / 2
|
||||||
|
|
||||||
|
|
||||||
The second form of if-statement resembles the standard syntax found in
|
The second form of if-statement resembles the standard syntax found in
|
||||||
|
@ -1401,37 +1414,29 @@ The second variation of the if-statement is to allow for the use of
|
||||||
Else and If-Else cascading statements. Examples of such statements are
|
Else and If-Else cascading statements. Examples of such statements are
|
||||||
as follows:
|
as follows:
|
||||||
|
|
||||||
Example 1: Example 2:
|
Example 1: Example 2: Example 3:
|
||||||
if (x < y) if (x < y)
|
if (x < y) if (x < y) if (x > y + 1)
|
||||||
z := x + 3; {
|
z := x + 3; { y := abs(x - z);
|
||||||
else y := z + x;
|
else y := z + x; else
|
||||||
y := x - z; z := x + 3;
|
y := x - z; z := x + 3; {
|
||||||
}
|
} y := z + x;
|
||||||
else
|
else z := x + 3;
|
||||||
y := x - z;
|
y := x - z; };
|
||||||
|
|
||||||
Example 3: Example 4:
|
|
||||||
if (x > y + 1) if (2 * x < max(y,3))
|
|
||||||
y := abs(x - z); {
|
|
||||||
else y := z + x;
|
|
||||||
{ z := x + 3;
|
|
||||||
y := z + x; }
|
|
||||||
z := x + 3; else if (2y - z)
|
|
||||||
}; y := x - z;
|
|
||||||
|
|
||||||
Example 5: Example 6:
|
Example 4: Example 5: Example 6:
|
||||||
if (x < y) if (x < y or (x + z) > y)
|
if (2 * x < max(y,3)) if (x < y) if (x < y or (x + z) > y)
|
||||||
z := x + 3; {
|
{ z := x + 3; {
|
||||||
else if (2y != z) z := x + 3;
|
y := z + x; else if (2y != z) z := x + 3;
|
||||||
{ y := x - z;
|
z := x + 3; { y := x - z;
|
||||||
z := x + 3; }
|
} z := x + 3; }
|
||||||
y := x - z; else if (abs(2y - z) >= 3)
|
else if (2y - z) y := x - z; else if (abs(2y - z) >= 3)
|
||||||
} y := x - z;
|
y := x - z; } y := x - z;
|
||||||
else else
|
else else
|
||||||
x * x; {
|
x * x; {
|
||||||
z := abs(x * x);
|
z := abs(x * x);
|
||||||
x * y * z;
|
x * y * z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
In the case where there is no final else statement and the flow
|
In the case where there is no final else statement and the flow
|
||||||
|
@ -1451,7 +1456,7 @@ Special functions dramatically decrease the total evaluation time of
|
||||||
expressions which would otherwise have been written using the common
|
expressions which would otherwise have been written using the common
|
||||||
form by reducing the total number of nodes in the evaluation tree of
|
form by reducing the total number of nodes in the evaluation tree of
|
||||||
an expression and by also leveraging the compiler's ability to
|
an expression and by also leveraging the compiler's ability to
|
||||||
correctly optimize such expressions for a given architecture.
|
correctly optimise such expressions for a given architecture.
|
||||||
|
|
||||||
3-Parameter 4-Parameter
|
3-Parameter 4-Parameter
|
||||||
+-------------+-------------+ +--------------+------------------+
|
+-------------+-------------+ +--------------+------------------+
|
||||||
|
@ -1581,25 +1586,28 @@ examples of string variable definitions:
|
||||||
(a) Initialise to a string
|
(a) Initialise to a string
|
||||||
var x := 'abc';
|
var x := 'abc';
|
||||||
|
|
||||||
(b) Initialise to a string expression
|
(b) Initialise to an empty string
|
||||||
|
var x := '';
|
||||||
|
|
||||||
|
(c) Initialise to a string expression
|
||||||
var x := 'abc' + '123';
|
var x := 'abc' + '123';
|
||||||
|
|
||||||
(c) Initialise to a string range
|
(d) Initialise to a string range
|
||||||
var x := 'abc123'[2:4];
|
var x := 'abc123'[2:4];
|
||||||
|
|
||||||
(d) Initialise to another string variable
|
(e) Initialise to another string variable
|
||||||
var x := 'abc';
|
var x := 'abc';
|
||||||
var y := x;
|
var y := x;
|
||||||
|
|
||||||
(e) Initialise to another string variable range
|
(f) Initialise to another string variable range
|
||||||
var x := 'abc123';
|
var x := 'abc123';
|
||||||
var y := x[2:4];
|
var y := x[2:4];
|
||||||
|
|
||||||
(f) Initialise to a string expression
|
(g) Initialise to a string expression
|
||||||
var x := 'abc';
|
var x := 'abc';
|
||||||
var y := x + '123';
|
var y := x + '123';
|
||||||
|
|
||||||
(g) Initialise to a string expression range
|
(h) Initialise to a string expression range
|
||||||
var x := 'abc';
|
var x := 'abc';
|
||||||
var y := (x + '123')[1:3];
|
var y := (x + '123')[1:3];
|
||||||
|
|
||||||
|
@ -1775,7 +1783,7 @@ needs to be 'updated' to either another vector or sub-range, the
|
||||||
vector_view instance can be efficiently rebased, and the expression
|
vector_view instance can be efficiently rebased, and the expression
|
||||||
evaluated as normal.
|
evaluated as normal.
|
||||||
|
|
||||||
exprtk::vector_view<T> view = exprtk::make_vector_view(v, v.size());
|
exprtk::vector_view<T> view = exprtk::make_vector_view(v,v.size());
|
||||||
|
|
||||||
symbol_table_t symbol_table;
|
symbol_table_t symbol_table;
|
||||||
symbol_table.add_vector("v",view);
|
symbol_table.add_vector("v",view);
|
||||||
|
@ -1794,7 +1802,7 @@ evaluated as normal.
|
||||||
|
|
||||||
[SECTION 15 - USER DEFINED FUNCTIONS]
|
[SECTION 15 - USER DEFINED FUNCTIONS]
|
||||||
ExprTk provides a means whereby custom functions can be defined and
|
ExprTk provides a means whereby custom functions can be defined and
|
||||||
utilized within expressions. The concept requires the user to
|
utilised within expressions. The concept requires the user to
|
||||||
provide a reference to the function coupled with an associated name
|
provide a reference to the function coupled with an associated name
|
||||||
that will be invoked within expressions. Functions may take numerous
|
that will be invoked within expressions. Functions may take numerous
|
||||||
inputs but will always return a single value of the underlying numeric
|
inputs but will always return a single value of the underlying numeric
|
||||||
|
@ -1840,7 +1848,7 @@ function called 'foo':
|
||||||
(2) ivararg_function
|
(2) ivararg_function
|
||||||
This interface supports a variable number of scalar arguments as input
|
This interface supports a variable number of scalar arguments as input
|
||||||
into the function. The function operator interface uses a std::vector
|
into the function. The function operator interface uses a std::vector
|
||||||
specialized upon type T to facilitate parameter passing. The following
|
specialised upon type T to facilitate parameter passing. The following
|
||||||
example defines a vararg function called 'boo':
|
example defines a vararg function called 'boo':
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -1863,7 +1871,7 @@ example defines a vararg function called 'boo':
|
||||||
(3) igeneric_function
|
(3) igeneric_function
|
||||||
This interface supports a variable number of arguments and types as
|
This interface supports a variable number of arguments and types as
|
||||||
input into the function. The function operator interface uses a
|
input into the function. The function operator interface uses a
|
||||||
std::vector specialized upon the type_store type to facilitate
|
std::vector specialised upon the type_store type to facilitate
|
||||||
parameter passing.
|
parameter passing.
|
||||||
|
|
||||||
Scalar <-- function(i_0, i_1, i_2....., i_N)
|
Scalar <-- function(i_0, i_1, i_2....., i_N)
|
||||||
|
@ -2335,6 +2343,42 @@ Note: For the igeneric_function type, there also needs to be a 'Z'
|
||||||
parameter sequence defined in order for the zero parameter trait to
|
parameter sequence defined in order for the zero parameter trait to
|
||||||
properly take effect otherwise a compilation error will occur.
|
properly take effect otherwise a compilation error will occur.
|
||||||
|
|
||||||
|
|
||||||
|
(9) Free Functions
|
||||||
|
The ExprTk symbol table supports the registration of free functions
|
||||||
|
and lambdas (anonymous functors) for use in expressions. The basic
|
||||||
|
requirements are similar to those found in ifunction derived user
|
||||||
|
defined functions. This includes support for free functions using
|
||||||
|
anywhere from zero up to fifteen input parameters of scalar type, with
|
||||||
|
a return type that is also scalar. Furthermore such functions will by
|
||||||
|
default be assumed to have side-effects and hence will not participate
|
||||||
|
in constant folding optimisations.
|
||||||
|
|
||||||
|
In the following example, a two input parameter free function named
|
||||||
|
'compute', and a three input parameter lambda will be registered with
|
||||||
|
the given symbol_table instance:
|
||||||
|
|
||||||
|
|
||||||
|
double compute(double v0, double v1)
|
||||||
|
{
|
||||||
|
return 2.0 * v0 + v1 / 3.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||||
|
|
||||||
|
symbol_table_t symbol_table;
|
||||||
|
|
||||||
|
symbol_table.add_function("compute", compute);
|
||||||
|
|
||||||
|
symbol_table.add_function("lambda",
|
||||||
|
[](double v0, double v1, double v2) -> double
|
||||||
|
{ return v0 / v1 + v2; });
|
||||||
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
[SECTION 16 - EXPRESSION DEPENDENTS]
|
[SECTION 16 - EXPRESSION DEPENDENTS]
|
||||||
|
@ -2443,7 +2487,7 @@ associated assignments:
|
||||||
(5) None x + y + z
|
(5) None x + y + z
|
||||||
|
|
||||||
|
|
||||||
Note: In expression 4, both variables 'z' and 'w' are denoted as being
|
Note: In expression 4, both variables 'w' and 'z' are denoted as being
|
||||||
assignments even though only one of them can ever be modified at the
|
assignments even though only one of them can ever be modified at the
|
||||||
time of evaluation. Furthermore the determination of which of the two
|
time of evaluation. Furthermore the determination of which of the two
|
||||||
variables the modification will occur upon can only be known with
|
variables the modification will occur upon can only be known with
|
||||||
|
@ -2489,7 +2533,7 @@ associated with a given expression instance.
|
||||||
|
|
||||||
However as an expression can have more than one symbol table instance
|
However as an expression can have more than one symbol table instance
|
||||||
associated with itself, when building more complex systems that
|
associated with itself, when building more complex systems that
|
||||||
utilize many expressions where each can in turn utilize one or more
|
utilise many expressions where each can in turn utilise one or more
|
||||||
variables from a large set of potential variables, functions or
|
variables from a large set of potential variables, functions or
|
||||||
constants, it becomes evident that grouping variables into layers of
|
constants, it becomes evident that grouping variables into layers of
|
||||||
symbol_tables will simplify and streamline the overall process.
|
symbol_tables will simplify and streamline the overall process.
|
||||||
|
@ -2559,7 +2603,7 @@ own instances of those variables. Examples of such variables could be:
|
||||||
(2) customer_name
|
(2) customer_name
|
||||||
|
|
||||||
|
|
||||||
The following is a diagram depicting the possible version of the
|
The following is a diagram depicting the possible version of the
|
||||||
denoted symbol table hierarchies. In the diagram there are two unique
|
denoted symbol table hierarchies. In the diagram there are two unique
|
||||||
expressions, each of which have a reference to the Global constant,
|
expressions, each of which have a reference to the Global constant,
|
||||||
functions and variables symbol tables and an exclusive reference to a
|
functions and variables symbol tables and an exclusive reference to a
|
||||||
|
@ -2589,8 +2633,8 @@ local symbol table.
|
||||||
|
|
||||||
|
|
||||||
Bringing all of the above together, in the following example the
|
Bringing all of the above together, in the following example the
|
||||||
hierarchy of symbol tables are instantiated and initialised. An
|
hierarchy of symbol tables are instantiated and initialised. An
|
||||||
expression that makes use of various elements of each symbol table is
|
expression that makes use of various elements of each symbol table is
|
||||||
then compiled and later on evaluated:
|
then compiled and later on evaluated:
|
||||||
|
|
||||||
typedef exprtk::symbol_table<double> symbol_table_t;
|
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||||
|
@ -2722,7 +2766,7 @@ expressions:
|
||||||
In this scenario one can use the 'dependent_entity_collector'
|
In this scenario one can use the 'dependent_entity_collector'
|
||||||
component as described in [Section 16] to further determine which of
|
component as described in [Section 16] to further determine which of
|
||||||
the registered variables were actually used in the given expression.
|
the registered variables were actually used in the given expression.
|
||||||
As an example once the set of utilized variables are known, any
|
As an example once the set of utilised variables are known, any
|
||||||
further 'attention' can be restricted to only those variables when
|
further 'attention' can be restricted to only those variables when
|
||||||
evaluating the expression. This can be quite useful when dealing with
|
evaluating the expression. This can be quite useful when dealing with
|
||||||
expressions that can draw from a set of hundreds or even thousands of
|
expressions that can draw from a set of hundreds or even thousands of
|
||||||
|
@ -3427,8 +3471,8 @@ values.
|
||||||
|
|
||||||
expression.value();
|
expression.value();
|
||||||
|
|
||||||
printf("Result0: %15.5f\n",result0 );
|
printf("Result0: %15.5f\n", result0 );
|
||||||
printf("Result1: %s\n" ,result1.c_str());
|
printf("Result1: %s\n" , result1.c_str());
|
||||||
|
|
||||||
|
|
||||||
In the example above, the expression will compute two results. As such
|
In the example above, the expression will compute two results. As such
|
||||||
|
@ -3436,7 +3480,7 @@ two result variables are defined to hold the values named result0 and
|
||||||
result1 respectively. The first is of scalar type (double), the second
|
result1 respectively. The first is of scalar type (double), the second
|
||||||
is of string type. Once the expression has been evaluated, the two
|
is of string type. Once the expression has been evaluated, the two
|
||||||
variables will have been updated with the new result values, and can
|
variables will have been updated with the new result values, and can
|
||||||
then be further utilized from within the calling program.
|
then be further utilised from within the calling program.
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -3753,12 +3797,12 @@ overloads, the definitions of which are:
|
||||||
|
|
||||||
(1) No variables
|
(1) No variables
|
||||||
(2) One variable called x
|
(2) One variable called x
|
||||||
(3) Two variable called x and y
|
(3) Two variables called x and y
|
||||||
(3) Three variable called x, y and z
|
(3) Three variables called x, y and z
|
||||||
|
|
||||||
|
|
||||||
An example use of each of the three overloads for the compute routine
|
Example uses of each of the three overloads for the compute routine
|
||||||
is as follows:
|
are as follows:
|
||||||
|
|
||||||
T result = T(0);
|
T result = T(0);
|
||||||
|
|
||||||
|
@ -3803,11 +3847,11 @@ is as follows:
|
||||||
|
|
||||||
(d) integrate
|
(d) integrate
|
||||||
This free function will attempt to perform a numerical integration of
|
This free function will attempt to perform a numerical integration of
|
||||||
a single variable compiled expression over a defined range and given
|
a single variable compiled expression over a specified range and step
|
||||||
step size. The numerical integration is based on the three point form
|
size. The numerical integration is based on the three point form of
|
||||||
of the Simpson's rule. The integrate function has two overloads, where
|
Simpson's rule. The integrate function has two overloads, where the
|
||||||
the variable of integration can either be passed as a reference or as
|
variable of integration can either be passed as a reference or as a
|
||||||
a name in string form. Example usage of the function is as follows:
|
name in string form. Example usage of the function is as follows:
|
||||||
|
|
||||||
typedef exprtk::parser<T> parser_t;
|
typedef exprtk::parser<T> parser_t;
|
||||||
typedef exprtk::expression<T> expression_t;
|
typedef exprtk::expression<T> expression_t;
|
||||||
|
@ -3863,7 +3907,7 @@ function is as follows:
|
||||||
|
|
||||||
....
|
....
|
||||||
|
|
||||||
// Differentiate expression where value of x = 12.3 using a reference
|
// Differentiate expression at value of x = 12.3 using a reference
|
||||||
// to the x variable
|
// to the x variable
|
||||||
x = T(12.3);
|
x = T(12.3);
|
||||||
T derivative1 = exprtk::derivative(expression,x);
|
T derivative1 = exprtk::derivative(expression,x);
|
||||||
|
@ -4047,7 +4091,7 @@ expressions. As an example, lets take the following expression:
|
||||||
1 / sqrt(2x) * e^(3y)
|
1 / sqrt(2x) * e^(3y)
|
||||||
|
|
||||||
|
|
||||||
Let's say we would like to determine which sub-part of the expression
|
Lets say we would like to determine which sub-part of the expression
|
||||||
takes the most time to evaluate and perhaps attempt to rework the
|
takes the most time to evaluate and perhaps attempt to rework the
|
||||||
expression based on the results. In order to do this we will create a
|
expression based on the results. In order to do this we will create a
|
||||||
text file called 'test.txt' and then proceed to make some educated
|
text file called 'test.txt' and then proceed to make some educated
|
||||||
|
@ -4133,7 +4177,7 @@ into account when using ExprTk:
|
||||||
|
|
||||||
(09) The life-time of objects registered with or created from a
|
(09) The life-time of objects registered with or created from a
|
||||||
specific symbol-table must span at least the life-time of the
|
specific symbol-table must span at least the life-time of the
|
||||||
compiled expressions which utilize objects, such as variables,
|
compiled expressions which utilise objects, such as variables,
|
||||||
of that symbol-table, otherwise the result will be undefined
|
of that symbol-table, otherwise the result will be undefined
|
||||||
behavior.
|
behavior.
|
||||||
|
|
||||||
|
@ -4289,7 +4333,15 @@ into account when using ExprTk:
|
||||||
performance critical code paths, and should instead occur
|
performance critical code paths, and should instead occur
|
||||||
entirely either before or after such code paths.
|
entirely either before or after such code paths.
|
||||||
|
|
||||||
(32) Before jumping in and using ExprTk, do take the time to peruse
|
(32) Deep copying an expression instance for the purposes of
|
||||||
|
persisting to disk or otherwise transmitting elsewhere with the
|
||||||
|
intent to 'resurrect' the expression instance later on is not
|
||||||
|
possible due to the reasons described in the final note of
|
||||||
|
Section 10. The recommendation is to instead simply persist the
|
||||||
|
string form of the expression and compile the expression at
|
||||||
|
run-time on the target.
|
||||||
|
|
||||||
|
(33) Before jumping in and using ExprTk, do take the time to peruse
|
||||||
the documentation and all of the examples, both in the main and
|
the documentation and all of the examples, both in the main and
|
||||||
the extras distributions. Having an informed general view of
|
the extras distributions. Having an informed general view of
|
||||||
what can and can't be done, and how something should be done
|
what can and can't be done, and how something should be done
|
||||||
|
|
Loading…
Reference in New Issue